【问题标题】:Splitting C char array into words将 C char 数组拆分为单词
【发布时间】:2013-02-23 15:25:36
【问题描述】:

我正在尝试将给定的 char 数组拆分为单独的字符串。我这样做是通过将每个单词的地址放入一个数组中,然后从地址中获取字符串进行打印。

所以我更新了我的代码,但现在程序在打印 numArgs 之后但在“test2”之前冻结。我不明白为什么。

----------------old code-----------------------   
char* parseArgs(char* comPtr){
    char *args[100] = {0};
    char *token;
    int i = 0;
    token = strtok(comPtr, " ");
    while(token != NULL){
        args[i] = malloc(100);
        args[i] = &token;
        token = strtok(NULL, " ");
    }
    return *args;
}

char* args = parseArgs(comPtr);
int i = 0;
while(i < numArgs){
    printf("arg%d: %s\n",i,&args[i]);
    i++;
}
-----------------------end old code--------------------

------------------new code------------------------
int countArgs(char* comPtr){
    char *token;
    int i = 0;
    token = strtok(comPtr, " ");
    while(token != NULL){
        i++;
        token = strtok(NULL, " ");
    }
    return i;
}

char** parseArgs(char* comPtr){
    printf("test1");
    char** args = calloc(100, sizeof(char*));
    char* token;
    int i = 0;
    while(token = strtok(comPtr, " ")){
        args[i] = token;
    }
    printf("test2");
    return args;
}

printf("ComPtr: %s\n",comPtr);
char* path = "/bin/";
//int pid = fork(); //pid always 0 so using pid = 1 to test
//printf("PID:%d",pid);
int pid = 1;
printf("PID:%d",pid);
if(pid != 0){
    int numArgs = countArgs(comPtr);
    printf("test1");
    printf("NumArgs: %d\n",numArgs);
    printf("test2");
    char** args = parseArgs(comPtr);
    int i = 0;
    printf("test3");
    while(i < numArgs){
        printf("arg%d: %s\n",i,args[i]);
        printf("test4");
        i++;
    }
}
else{
    //waitpid();
}

【问题讨论】:

  • 你还没有问过问题。
  • Umm: args[i] = malloc(100); args[i] = &amp;token; 你刚刚泄露了两行短线内存。
  • 你不应该从函数parseArgs返回局部变量args
  • 仅供参考 strtok 将修改其第一个参数。您的字符串中的空格在countArgs 中被替换为\0,然后您尝试解析parseArgs 中的空格(不再存在)。此外,i 永远不会在 parseArgs 中递增。
  • 您的代码无法编译。如果我们无法编译代码,我们应该如何重现错误?请向我们展示一个最小的、可编译的测试用例。

标签: c arrays string pointers char


【解决方案1】:

将指针数组'char *args[100]'声明为全局变量。在您的程序中,您正在为本地指针分配内存,它的生命在函数内。所以在函数结束时你的指针变量范围结束。这里也有内存泄漏。

【讨论】:

    【解决方案2】:

    你已经忘记了你的记忆在哪里,你的指针指向等等。如果你想返回指向标记的指针列表,你需要这样的东西:

    char** parseArgs(char* comPtr){
        char** p_args = calloc(100, sizeof(char*);
        int i = 0;
        char* token;
        while (token = strtok(comPtr, " "))
            p_args[i] = token;
        return p_args;
    }
    
    char** p_args = parseArgs(comPtr);
    int i = 0;
    while(i < numArgs)
    {
        printf("arg%d: %s\n",i,p_args[i]);
        i++;
    }
    free(p_args);
    

    我尚未对其进行测试,但它应该会为您指明正确的方向。仔细考虑它与您的程序有何不同,并在代码中使用调试器和/或printf() 语句来打印地址并查看其工作原理(或在必要时进行调试)。

    【讨论】:

    • 学究起来,如果在freeing 之后将p_args 设置为NULL,岂不是更安全?
    • 谢谢,但由于程序冻结,现在我什至无法测试这个
    • @AnishRam:恕我直言,对此没有总体最佳实践...如果您担心有人再次使用或释放​​它(例如,在一个长而复杂的函数体中),这是有道理的,但是您可能知道这是不可能的(例如,下一个源代码行关闭了在堆栈上创建p_args 的范围)。就个人而言,我很少发现 NULL 指针很有用,但是这些天我编写 C++ 时,释放通常隐藏在析构函数中,而且问题很少存在......
    • @TrentWorkman:如果程序冻结,那么根据我的回答,您应该使用调试器或添加 printf() 语句来识别它冻结的行。如果你这么轻易放弃,你永远不会成为一名程序员。我很高兴为您指明正确的方向,但我不可能一直握着您的手。如果你卡住了,问一个具体的问题ala“它到达了xyz的行,这个指针就是这个,它做了那个,我希望它做别的事情,我试过这个,但它做了那个......发生了什么打开,我该如何解决?”。
    • 谢谢,但我确实告诉了它冻结在哪些行。我完全理解握住我的手,但我真的不明白为什么它会冻结在它所在的地方。它在两个 printf () 语句之间冻结,在我看来这似乎是 printf 有问题
    【解决方案3】:

    冻结是由于

    int i = 0;
    while(token = strtok(comPtr, " ")){
        args[i] = token;
    }
    

    在你重复的地方——在一个无限循环中——在comPtr中找到第一个标记,token在每次迭代中变成&amp;comPtr[0](除非字符串以空格开头),并且分配给args[i]

    在第一次调用之后,所有对strtok 的调用应在同一字符串中找到更多标记(如果有的话)应该有一个NULL 第一个参数。

    此外,您可能应该在循环中增加 i,因为大概您不想用每个新令牌覆盖 args[0]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-25
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      相关资源
      最近更新 更多