strtok没有通过所有令牌

时间:2014-02-03 17:43:45

标签: c linux shell strtok

我正在尝试将shell作为学校作业的一部分来实现,而且我被困在文件输入/输出重定向部分。

更具体地说,我提出了一个函数,它允许我检测输入的命令是否指定'>'或'<'甚至是'|'。

理想情况下,如果我输入ls -a > ls.tx',则应返回代币ls -als.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 -als.txt)< / p>

    char myString[] = "ls -a > ls.txt";
char* parsed;

parsed = strtok(myString, ">");
while (parsed != NULL)
{
    printf("%s\n", parsed);
    parsed = strtok(NULL, ">");
}

有什么我不理解的东西吗?我真的没有看到我出错的地方,因为在这两种情况下代码本身几乎都是一样的。

2 个答案:

答案 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()

,否则不会影响buff

通过比较 ,您的代码的这一部分有点可怕,因为我不知道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()是一个更好的选择