我正在尝试将shell作为学校作业的一部分来实现,而且我被困在文件输入/输出重定向部分。
更具体地说,我提出了一个函数,它允许我检测输入的命令是否指定'>'或'<'甚至是'|'。
理想情况下,如果我输入ls -a > ls.tx
',则应返回代币ls -a
和ls.txt
。
我的代码没有这样做,它只返回ls -a
然后停止。
我的代码如下:
/*commandLine is a char* taken in from the user, and is a null-terminated string */
int counter = 0;
parsedLine = strtok(commandLine, ">");
while (parsedLine != NULL)
{
if (counter == 0)
{
strncpy(parsedCpy, parsedLine, strlen(parsedLine));
parseCommand(parsedCpy, commands);
counter++;
}
else
{
redirect->re_stdout = parsedLine;
}
parsedLine = strtok(NULL, ">");
}
我在另一个测试文件中尝试过它只是为了查看是否有错误,但是这个测试文件(下面的代码)返回了预期的结果(即ls -a
和ls.txt
)< / p>
char myString[] = "ls -a > ls.txt";
char* parsed;
parsed = strtok(myString, ">");
while (parsed != NULL)
{
printf("%s\n", parsed);
parsed = strtok(NULL, ">");
}
有什么我不理解的东西吗?我真的没有看到我出错的地方,因为在这两种情况下代码本身几乎都是一样的。
答案 0 :(得分:1)
请注意,strncpy
不会使字符串终止,除非零终止是要复制的源的一部分。见man strncpy
。它说:
警告:如果src的前n个字节中没有空字节,则放在dest中的字符串将不会以空值终止。
根据parseCommand的作用,这可能会引发其他事情。
在这种情况下,您应该只做strcpy
。如果你给它源字符串的长度,strncpy
并没有真正为你做任何事情,除非你故意试图避免复制空终止符。所以你应该使用strcpy(parsedCpy, parsedLine);
。
答案 1 :(得分:0)
我看不出如何声明parsedLine ,但需要谨慎处理。即确保除strtok()
之外不更改指向该值的指针,并确保它保持为空终止。使用strtok()
进行多次调用时,我要做的一件事是使用中间值来收集结果,有助于保持目标缓冲区的纯净和不变,除了strtok()
一个小代码片段,用于说明:
char a[] = {"ls -a > ls.tx"};
char *buff;
char keep[80];
buff = strtok(a, ">");
strcpy(keep, buff);
buff = strtok(NULL, ">");
strcat(keep, buff);
strtok()
的这种用法是干净的,即除非另一次调用strtok()
通过比较 ,您的代码的这一部分有点可怕,因为我不知道strncpy()
的输出,它依赖于第三个参数,并且可以腐败(将意外结果放入)parseCommand:
if (counter == 0)
{
strncpy(parsedCpy, parsedLine, strlen(parsedLine));
parseCommand(parsedCpy, commands);
counter++;
}
else
{
redirect->re_stdout = parsedLine;
}
parsedLine = strtok(NULL, ">");
保持目标缓冲区纯净的 (即使它似乎不是一个问题),{{ 1}}不是线程安全的。如果在多线程进程中使用使用strtok()
的函数,则目标缓冲区将受到任意数量的调用,从而导致意外的,甚至可能是未定义的行为。在这种情况下,使用strtok()
是一个更好的选择