【问题标题】:Using strtok in C language在 C 语言中使用 strtok
【发布时间】:2011-11-26 15:43:36
【问题描述】:

我在 C 中使用 strtok 时遇到问题。我使用 fgets 从命令行获取用户输入,我想用管道(“|”)作为分隔符对其进行标记,并将结果放入双指针变量中。这是我的代码:

char** argv;
char *token;
token = strtok(userInput, "|");
while(token != NULL){
  *(argv++) = token;
   token = strtok(NULL, "|");
}

*argv = '\0';

然后我使用此代码来验证它是否被很好地标记

while(*argv!= NULL)
{
   if((strcmp(*argv, "|") == 0){
   count = count + 1;
   }
   argv++;
}
printf("%d pipes", count);

但它不起作用。 char** argv 不包含任何内容。代码的执行停止并返回-1。当我尝试打印 argv 时,argv 不包含任何值。

有什么想法吗?谢谢。

编辑:

我想做的是这个

userInput = "abc|cde";

使用 strtok 后。我想要一个 **argv

**argv = "abc";

【问题讨论】:

  • 但它不起作用。到底发生了什么?
  • 当你说它不起作用时,你得到了什么错误?
  • “不起作用”是什么意思?该代码完全按照您的要求执行。这可能与您的预期不同,但如果您不愿意告诉我们,则无法猜测。
  • 对不起,如果我不清楚。我的意思是 char** argv 什么都不包含。代码的执行停止并返回-1。当我尝试打印 argv 时,argv 不包含任何值。

标签: c linux pointers strtok


【解决方案1】:

一个问题是您似乎没有初始化argv。您需要为其分配足够的内存以容纳所需数量的char *s。否则,您正在写入一些随机的内存块。 (只是你没有给我们看相关的代码吗?)

另一个问题是你实际上是在修改argv,所以在循环结束时,它指向最后一个标记的过去(然后你将*argv设置为NULL);但是您的验证码假定它指向第一个令牌,并首先确认*argv不是 NULL。 (只是您没有向我们展示一些相关代码吗?)编辑添加:我从您上面的评论中看到“argv 不包含任何值”。我非常有信心就是原因。

顺便说一句,您将'\0'(空字节)与NULL(空指针)混淆了。从技术上讲,这是正确的——'\0' 被提升为00 被转换为NULL——但我发现你混淆它们有点令人担忧,因为从概念上它们是完全不同的。你应该写*argv = NULL而不是*argv = '\0',如果没有别的,为了清楚起见。

【讨论】:

    【解决方案2】:

    您的标记化代码的工作方式如下: 如果

    userInput = "a|b|c"
    

    然后

    argv = { "a", "b", "c" }
    

    你可能会期待

    argv = {"a","|","b","|","c"}
    

    您计算管道的代码应该是:

    while(*argv != NULL)
    {
       count = count + 1;
       argv++;
    }
    printf("%d pipes", count-1);
    

    我认为它会起作用

    【讨论】:

    • 这有点接近我想要的。其实我想要的是:如果我有一个像{a b | c d NULL} 这样的用户输入,我想要一个char **argv = {"a", "b", NULL}
    • 你是说你只想要第一个'|'之前的子字符串分隔符。 ??
    • 没错!我想在第一个分隔符之前和之后使用字符串。所以例如在管道之前我可以有ls -l所以我想把这个ls -l放在**argv中并使用execvp执行它。
    【解决方案3】:

    我使用的是这种用于搜索 300x400 的格式。寻找“x”以摆脱 x 并使用两侧,即 300 和 400 。这对我有用。

     char *tok1, *tok2, *saveptr;
    
     tok1 = strtok_r(argv, "x", &saveptr);
     tok2 = strtok_r(NULL, "x", &saveptr);
    
     printf("this tok1 %s this is tok2 %s\n", tok1, tok2);
    

    使用 strtok_r 函数

    【讨论】:

      【解决方案4】:

      问题是当您尝试从中获取结果时,您的 argv 未指向第一个元素。

      问题出现在这里: *(argv++) = 令牌

      argv(指向 char* 的指针)在您将令牌指针添加到 argv 数组时增加(我假设您已正确初始化它)。因此,当您使用代码的第二部分获取结果时,argv 已经指向最后一个元素,在您的情况下为 '\0',这将不会产生任何输出。

      而且,您正在将 '\0' 与 NULL 混合,尽管它们在语法上都是正确的,但在您的情况下使用 NULL 更好,因为它表示指针,但 '\0' 表示 C 中的空终止-字符串

      您可以将您的代码更改为以下内容:

      /* Init argv array */
      char** argv;
      size_t argc=0;  // token count
      char *token;
      token = strtok(userInput, "|");
      while(token != NULL){
         argv[argc++] = token;
         token = strtok(NULL, "|");
      }
      argv[argc] = NULL;  // the last element of argv array is a NULL pointer
      
      /* get result from argv */
      
      while(*argv!= NULL)
      {
         if((strcmp(*argv, "|") == 0){
         count = count + 1;
         }
         argv++;
      }
      printf("%d pipes", count);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 2016-01-01
        • 1970-01-01
        相关资源
        最近更新 更多