简体   繁体   English

strtok不会遍历所有令牌

[英]strtok not going through all tokens

I'm trying to implement a shell as part of a school assignment, and I'm stuck on the file input/output redirection part. 我正在尝试将外壳实现为学校作业的一部分,并且卡在文件输入/输出重定向部分中。

More specifically, I've come up with a function which allows me to detect whether or not the command entered in specifies a '>' or '<' or even a '|'. 更具体地说,我想出了一个函数,该函数使我能够检测输入的命令是否指定了'>'或'<'甚至是'|'。

Ideally, if I enter ls -a > ls.tx ', then the tokens ls -a and ls.txt should be returned. 理想情况下,如果输入ls -a > ls.tx ',则应该返回令牌ls -als.txt

My code doesn't do this, it only returns ls -a then stops. 我的代码不执行此操作,它仅返回ls -a然后停止。

My code is below: 我的代码如下:

/*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, ">");
}

I've tried it in another test file just to see if there was something wrong, but this test file (code below) returns the expected result (that is, ls -a and ls.txt ) 我已经在另一个测试文件中尝试过它,只是为了看看是否有问题,但是此测试文件(下面的代码)返回了预期的结果(即ls -als.txt

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

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

Is there something that I'm just not understanding? 有我只是不了解的东西吗? I don't really see where I'm going wrong, since the code itself is nearly the same in both cases. 我真的看不出我要去哪里,因为两种情况下代码本身几乎相同。

Note that strncpy won't zero terminate a string unless the zero termination is part of the source being copied. 请注意,除非零终止是要复制的源的一部分,否则strncpy不会零终止字符串。 See man strncpy . 参见man strncpy It says: 它说:

Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated. 警告:如果src的前n个字节中没有空字节,则放置在dest中的字符串将不会以空值结尾。

That could be horsing something else up depending upon what parseCommand does. 取决于parseCommand的功能,这可能会使其他事情陷入困境。

In this case, you should just do a strcpy . 在这种情况下,您应该只执行strcpy A strncpy doesn't really do anything for you if you're giving it the length of the source string, unless you're intentionally trying to avoid copying the null terminator. 如果给strncpy提供源字符串的长度,它实际上并不会为您做任何事情,除非您有意避免复制空终止符。 So you should use, strcpy(parsedCpy, parsedLine); 因此,您应该使用strcpy(parsedCpy, parsedLine); .

I cannot see how parsedLine is declared , but it needs to be handled explicitly and carefully. 我看不到parsedLine是如何声明的 ,但是需要显式和谨慎地处理它。 ie make sure the pointer to that value is not changed except by strtok() , and make sure that it remains null terminated. 即,确保指向该值的指针除了strtok()之外没有更改,并确保其保持为null终止。 One thing I do when using strtok() for multiple calls, is to use an intermediate value to collect results, helping to keep the target buffer pure and unchanged except by strtok() 使用strtok()进行多次调用时,我要做的一件事是使用中间值来收集结果,这有助于保持目标缓冲区的纯净和不变,除非strtok()

A small code snippet to illustrate: 一个小代码段来说明:

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

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

This usage of strtok() is clean, ie it does not allow buff to be affected except by another call to strtok() 这种对strtok()用法是干净的,即除非再次调用strtok() ,否则它不会影响buff。

By comparison , this section of your code is a little scary because I do not know the output of the strncpy() which depends so heavily on the third argument, and can corrupt (place unexpected results into) parseCommand : 相比之下 ,您的代码这一部分有些令人恐惧,因为我不知道strncpy()的输出非常依赖第三个参数,并且可能破坏parseCommand(将意外结果放入):

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

Along the lines of keeping the target buffer pure, ( even though it does not appear to be an issue here ), strtok() is not thread safe. 按照保持目标缓冲区纯净的原则( 即使在这里似乎没有问题 ), strtok()也不是线程安全的。 If a function using strtok() is used in a multi threaded process, the target buffer is subject to any number of calls, resulting in unexpected, and perhaps even undefined behavior. 如果在多线程进程中使用了使用strtok()的函数,则目标缓冲区将受到任意数量的调用,从而导致意外的甚至是未定义的行为。 In this case using strtok_r() is a better option 在这种情况下,使用strtok_r()是更好的选择

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM