图一结果展示
图二问题部分代码
经过测试 在这个//fill the command structrue部分之后,这里的token[2]就消失了,我测试的用例是“abc;”, 测试结果为图1
command.c
#include
#include "command.h"
#include
#include
// whether is separator
int separator(char *token)
{
int i = 0;
char *commandSeparators[] = {pipeSep, conSep, seqSep, NULL};
while(commandSeparators[i] != NULL) {
if(strcmp(token, commandSeparators[i]) == 0)
{
return 1;
}
++i;
}
printf("\nin separator\ntoken: %s\n", token);
return 0;
}
// fill one command structure with details
void fillCommandStructure(Command *cp, int first, int last, char *sep)
{
cp->first = first;
cp->last = last - 1;
cp->sep = sep;
}
// process standard in/out redirections in a command
void searchRedirection(int tknum, char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
int i;
for( i = cp->first; i <= cp->last; ++i)
{
if(strcmp(token[i], "<") == 0)
{
// convert from char array to char
int k = 0;
char t[cp->last-i];
for(int j = i + 1; j <= cp->last; j++)
{
t[k] = token[j][0];
++k;
}
// dynamic allocate memory
cp->stdin_file = (char*)malloc(cp->last-i);
for(int l = 0; l < cp->last -i; l++)
{
cp->stdin_file[l] = t[l];
}
cp->stdin_file[cp->last-i] = '\0';
++i;
} else if (strcmp(token[i], ">") == 0)
{
int k = 0;
char t[cp->last-i];
for(int j = i + 1; j <= cp->last; j++)
{
t[k] = token[j][0];
++k;
}
cp->stdout_file = (char*)malloc(cp->last-i);
for(int l = 0; l < cp->last - i; l++)
{
cp->stdout_file[l] = t[l];
}
cp->stdout_file[cp->last-i] = '\0';
++i;
}
}
}
// build command line argument vector for execvp function
void buildCommandArgumentArray(char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
int n = cp->last - cp->first + 1;
printf("n: %d\n", n);
// re-allocate memoery for argument vector
cp->argv = (char**) realloc(cp->argv, sizeof(char*)*n );
if(cp->argv == NULL)
{
perror("realloc");
exit(1);
}
// build the argument vector
int i;
int k = 0;
printf("first: %d\n last: %d\n", cp->first, cp->last);
for(i = cp->first; i <= cp->last; ++i)
{
if(strcmp(token[i], ">") == 0 || strcmp(token[i], "<") == 0)
++i;
else
{
cp->argv[k] = token[i];
printf("k %d\nargvk %s\ntoken %s\n", k, cp->argv[k], token[i]);
++k;
}
}
cp->argv[k] == NULL;
}
int separateCommands(char (*token)[MAX_NUM_COMMANDS], Command command[], int nTokens)
{
for(int i = 0; i < nTokens;++i)
{
printf("token: %s\n", token[i]);
}
// if line is empty
if (nTokens == 0)
return 0;
// check the first token
if (separator(token[0]))
return -3;
// check the last token, add ";" if necessary
if (!separator(token[nTokens-1]))
{
strcpy(token[nTokens], seqSep);
++nTokens;
}
//fill the command structure
int first = 0;
int last = 0;
char *sep;
int c = 0;
for(int i = 0; i < nTokens; ++i)
{
last = i;
if (separator(token[i]))
{
sep = token[i];
if(first == last)
return -2;
fillCommandStructure(&(command[c]), first, last, sep);
++c;
first = i + 1;
}
}
printf("\nafter fill\n");
for(int i = 0; i < nTokens;++i)
{
printf("token: %s\n", token[i]);
}
// check the last token of the last command
if (strcmp(token[last], pipeSep) == 0)
return -4;
int nCommands = c;
// handle standard in/out redirection and build command line argument vector
for (int i=0; i < nCommands; ++i)
{
searchRedirection(nTokens, token, &(command[i]));
buildCommandArgumentArray(token, &(command[i]));
}
return nCommands;
command.h
#define MAX_NUM_COMMANDS 1000
#define pipeSep "|"
#define conSep "&"
#define seqSep ";"
struct CommandStruct {
int first;
int last;
char *sep;
// new fields
char ** argv;
char *stdin_file;
char *stdout_file;
};
typedef struct CommandStruct Command;
int separateCommands(char (*token)[MAX_NUM_COMMANDS], Command command[], int cmd_num);
main.c
#include
#include
#include
#include
#include "command.h"
char* s_gets(char* st, int n)
{
char* ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
{
st[i] = '\0';
}
else
{
while (getchar() != '\n')
{
continue;
}
}
}
return ret_val;
}
char* tostring(char des[], char src)
{
des[0] = src;
des[1] = '\0';
return des;
}
int main()
{
while(1)
{
char str[MAX_NUM_COMMANDS];
char tokens[2][MAX_NUM_COMMANDS];
int cmd_num = 0;
printf("$\n");
s_gets(str, MAX_NUM_COMMANDS);
cmd_num = strlen(str);
for(int i = 0; i < cmd_num; ++i)
{
tostring(tokens[i], str[i]);
}
Command cmdlst[MAX_NUM_COMMANDS];
cmd_num = separateCommands(tokens, cmdlst, cmd_num);
puts("");
printf("return value is: %d\n",cmd_num);
puts("");
for(int i = 0; i < cmd_num; ++i)
{
printf("fst %d\n", cmdlst[i].first);
printf("lst %d\n", cmdlst[i].last);
printf("sep %s\n", cmdlst[i].sep);
if(cmdlst[i].stdin_file != NULL)
printf("stdin file: %s\n", cmdlst[i].stdin_file);
if(cmdlst[i].stdout_file != NULL)
printf("stdout file: %s\n", cmdlst[i].stdout_file);
puts("");
}
// clean pointer
for(int i = 0; i < cmd_num; ++i)
{
if(cmdlst[i].stdin_file != NULL)
free(cmdlst[i].stdin_file);
if(cmdlst[i].stdout_file != NULL)
free(cmdlst[i].stdout_file);
}
puts("");
}
return 0;
}
该回答引用GPTᴼᴾᴱᴺᴬᴵ
根据提供的代码和信息,出现问题的地方可能是在fillCommandStructure函数中:
void fillCommandStructure(Command *cp, int first, int last, char *sep)
{
cp->first = first;
cp->last = last - 1;
cp->sep = sep;
}
其中,cp->last 的值是 last - 1。由于 last 的值是从 0 开始计数的索引,因此在使用此索引访问数组时,数组中的最后一个元素将被忽略。这可能是导致出现问题的原因。
·
为了解决这个问题,你可以尝试将 fillCommandStructure 函数中的 cp->last = last - 1 修改为 cp->last = last,或者在调用 fillCommandStructure 函数时将 last 参数传递为实际上应该是最后一个元素的索引值加 1,例如 last + 1。
·
另外,fillCommandStructure 函数的调用在 separator 函数中进行。因此,还应该确保 fillCommandStructure 函数的调用不会在数组的最后一个元素上执行。你可以通过在 for 循环中将 i < nTokens - 1 作为条件来实现这一点,以避免在数组的最后一个元素上调用该函数。
调试下是不是越界了,值是不会无故贸然消失的。
参考GPT和自己的思路:在C语言中,指针的值只有在初始化之后才会被确定,并且随时可能发生变化,因此需要注意指针操作的正确性。在你的代码中,可能存在以下几种情况导致指针值的消失:
1 指针未被正确初始化。在使用指针之前,需要先为指针分配内存空间,并将其初始化为某个变量的地址。如果未进行初始化操作,指针的值会是一个随机数,可能指向一个不存在的内存地址,从而导致程序崩溃。
2 指针被误操作修改了值。在对指针进行操作时,需要注意操作的正确性,避免误操作导致指针值的改变。
3 变量的作用域不正确。在C语言中,变量的作用域是有限制的。如果变量的作用域超出了其定义的范围,那么这个变量就不能被访问到,也就相当于消失了。
在你的代码中,出现指针值消失的原因可能是以上任意一种或几种情况的组合。你可以检查一下你的代码,看看是否存在上述情况,并进行相应的修改和优化。
参考GPT和自己的思路,在函数searchRedirection中,动态分配的内存空间大小应该是t[cp->last-i+1],因为需要为字符串结尾的\0留出一个字符的空间。在cp->stdin_file和cp->stdout_file中的内存分配也应该加1。
以下是修改后的代码:
void searchRedirection(int tknum, char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
int i;
for( i = cp->first; i <= cp->last; ++i)
{
if(strcmp(token[i], "<") == 0)
{
// convert from char array to char
int k = 0;
char t[cp->last-i+1];
for(int j = i + 1; j <= cp->last; j++)
{
t[k] = token[j][0];
++k;
}
// dynamic allocate memory
cp->stdin_file = (char*)malloc(cp->last-i+1);
for(int l = 0; l < cp->last -i; l++)
{
cp->stdin_file[l] = t[l];
}
cp->stdin_file[cp->last-i] = '\0';
++i;
} else if (strcmp(token[i], ">") == 0)
{
int k = 0;
char t[cp->last-i+1];
for(int j = i + 1; j <= cp->last; j++)
{
t[k] = token[j][0];
++k;
}
cp->stdout_file = (char*)malloc(cp->last-i+1);
for(int l = 0; l < cp->last - i; l++)
{
cp->stdout_file[l] = t[l];
}
cp->stdout_file[cp->last-i] = '\0';
++i;
}
}
}