【问题标题】:strtok not going through all tokensstrtok 没有遍历所有令牌
【发布时间】:2014-02-03 17:43:45
【问题描述】:

我正在尝试实现一个 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

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

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

有什么我不明白的吗?我真的不知道我哪里出错了,因为这两种情况下的代码本身几乎相同。

【问题讨论】:

  • 请注意,strncpy 不会以零终止字符串,除非零终止符是被复制源的一部分。见man strncpy。它说:警告:如果 src 的前 n 个字节中没有空字节,则放置在 dest 中的字符串将不会以空值结尾。这可能会导致其他问题,具体取决于 @987654332 @ 会。
  • 您的问题出在其他地方。这是一个可以正常工作的修改版本:ideone.com/WLfQER
  • 你应该只做一个strcpy。如果您给它提供源字符串的长度,strncpy 并没有真正为您做任何事情,除非您有意避免复制空终止符。 strcpy(parsedCpy, parsedLine);
  • @mbratch - 你的 cmets 值得回答。

标签: c linux shell strtok


【解决方案1】:

请注意,strncpy 不会以零终止字符串,除非零终止符是被复制源的一部分。见man strncpy。它说:

警告:如果 src 的前 n 个字节中没有空字节,则放在 dest 中的字符串不会以空结尾。

根据 parseCommand 的功能,这可能会导致其他问题。

在这种情况下,您应该只做一个strcpy。如果您给它提供源字符串的长度,strncpy 并没有真正为您做任何事情,除非您有意避免复制空终止符。所以你应该使用strcpy(parsedCpy, parsedLine);

【讨论】:

  • 非常感谢!原来这就是我一直在寻找的答案!非空终止字符串在传递给 parseCommand 后正在做一些疯狂的事情
【解决方案2】:

我看不到 parsedLine 是如何声明的,但需要明确且谨慎地处理。即确保指向该值的指针不会被strtok() 更改,并确保它保持为空终止。我在使用strtok() 进行多次调用时做的一件事是使用中间值来收集结果,这有助于保持目标缓冲区的纯净和不变,除非strtok()

一个小代码sn-p来说明:

char a[] = {"ls -a > ls.tx"};
char *buff;
char keep[80];

buff = strtok(a, ">");
    strcpy(keep, buff);
buff = strtok(NULL, ">");
    strcat(keep, buff);    

strtok() 的这种用法是干净的,即它不允许 buff 受到影响,除非再次调用 strtok()

相比之下,你的这部分代码有点吓人,因为我不知道strncpy() 的输出严重依赖第三个参数,并且可能会损坏(将意外结果放入) parseCommand :

if (counter == 0)
{
    strncpy(parsedCpy, parsedLine, strlen(parsedLine));
    parseCommand(parsedCpy, commands);
    counter++;
}
else
{
    redirect->re_stdout = parsedLine;
}
parsedLine = strtok(NULL, ">");

沿着保持目标缓冲区纯净的思路,(即使在这里看起来不是问题),@987654329 @ 不是线程安全的。如果在多线程进程中使用使用strtok() 的函数,则目标缓冲区会受到任意数量的调用,从而导致意外,甚至可能是未定义的行为。在这种情况下使用strtok_r() 是更好的选择

【讨论】:

    猜你喜欢
    • 2012-11-17
    • 2015-12-29
    • 2017-10-12
    • 2017-02-03
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    相关资源
    最近更新 更多