【问题标题】:Double pointer doubts in CC中的双指针疑问
【发布时间】:2009-07-22 18:23:47
【问题描述】:

我编写了一个程序,在主函数中我声明了一个指针数组,然后我调用一个函数来拆分给定的句子,然后将其分配给main() 中的指针数组。我做不到。请检查下面粘贴的代码:

   int  main(void)
   {
      char *data[3];

      allocate(data);
      /* Unable to print the strings here */
      printf("Main is %s\n", data[0] );
      printf(""   

   }

   void allocate(char **dt)
   { 
       int i;
       char buf[] = "The great Scorpion";
       char delims[] = " ";

       size_t len;
       char *p;
       char *result = NULL;
       result = strtok(buf," ");
       *dt = result;
       int j = 1;
       while(result!=NULL)
       {   

            result = strtok( NULL, delims );
            dt[j]=result;
            j++;

       }
      /* able to print values here */
      printf( "result is %s\n", dt[0]); 
      printf( "result is %s\n", dt[1] );
      printf( "result is %s\n", dt[2] );
    }

谁能帮帮我?

【问题讨论】:

  • 我想我认为 strtok 函数可能有问题。如果我直接在 allocate 函数中给出字符串,我可以得到这些值反映在 main 函数中。
  • 列出的代码有什么问题?您想要回答的实际问题是什么?
  • 我希望在 allocate 函数中分配的字符串反映在 main 函数中。
  • 代码块的最后一行是“谁能帮帮我??”。您应该删除它,使其不是代码的一部分。
  • main() 中 printf("" 的末尾缺少一个 )。

标签: c pointers


【解决方案1】:

strtok 不分配新字符串,它返回一个指向现有字符串的指针(并用空字符替换分隔符)。所以在allocate 中,你用指向buf 的指针填充dt。由于buf是一个自动变量,它的生命周期在allocate返回时结束,dt中的所有指针都失效了。

【讨论】:

  • 您可以通过执行 char const * const buf = "The great scorpion" b/c 来解决自动变量问题,然后 buf 将是指向静态 const 字符串的指针,BUT 那么您就不会能够使用strtok(),因为那将要修改buf指向的字符串,这是不允许的。
  • 所以他实际上可以通过给 buf 静态存储持续时间来解决问题: static char buf[] = "The great Scorpion";
【解决方案2】:

如果我没记错的话,strtok() 不会进行动态分配,它实际上会修改您在第一次调用它时传递给它的字符串。因此,在这种情况下,它会修改 buf。所以 dt 是一个指向 buf 的指针数组。而当你退出函数时,buf 会被销毁。

【讨论】:

    【解决方案3】:

    实际上,您可能只是将静态添加到您的 buf 声明中。

    【讨论】:

      【解决方案4】:

      好的,

      1. 您有一个allocate 函数,您将返回指针数组传递给该函数。
        • 在函数内部,您在 stack 上分配了一个字符串,并且,
        • 使strtok 在函数外返回指向此堆栈区域的指针
        • 此时您有指向字符串的“悬空”指针 -- 有效
        • 然后你调用printf 杀死未分配堆栈中的数据
        • 你错过了 printf 中的字符串。

      如果您想这样做,正确的方法是
      真正在您的 allocate 函数中分配字符串并
      然后在你完成它们后将它们从 main 中释放出来。

      使用strtok 的旧方法是在allocate 中使用strdup,以后可以免费使用。


      旧物... 我认为您需要将 &data 传递给您的 allocate 函数。
      要么这样,要么我还没有完全清醒。

      【讨论】:

      • 他不需要那个。 data(char*)[] 类型,将衰减为函数参数类型 char**。如果他按照你的建议做,他会得到 (char[])*,这不是兼容的参数类型。
      【解决方案5】:

      顺便说一句(这实际上不会对您的程序产生影响),您的循环结构错误。

         int j = 1;
         while(result!=NULL)
         {   
      
              result = strtok( NULL, delims );
              dt[j]=result;
              j++;
         }
      

      您正确设置了 dt[0]、dt[1] 和 dt[2]。然而,由于您的循环的性质(您检查、调用 strtok,然后插入到 dt 中),您还将 NULL 分配给 dt[3]。在这个简单的示例中,这可能运行良好,但您可能正在浪费您的堆栈。你真的应该像

      那样构建你的循环
         result = strtok(buf," ");
         int j=0
         while(result != NULL)
         {   
              dt[j]=result;
              j++;
              result = strtok(NULL, delims);
         }
      

      【讨论】:

        【解决方案6】:

        您正在尝试返回本地非静态变量的地址;一旦 allocate() 函数退出,buf 数组就不再存在,因此数据数组中的指针不再指向任何有意义的东西。

        您需要做的是保存令牌的副本,而不仅仅是指向它的指针:

        void allocate(char **dt)
        {
          char buf[] = "The Great Scorpion";
          char delim[] = " ";
          size_t i = 0;
          char *result = strtok(buf, delim);
          while (result)
          {
            dt[i] = malloc(strlen(result) + 1);
            if (dt[i])
            {
              strcpy(dt[i++], result);
            }
            result = strtok(NULL, delim);
          }
        }
        
        int main(void)
        {
          char *data[3];
          allocate(data);
          ...
        }
        

        或者,您可以将 data 定义为 char 的二维数组,而不仅仅是指针数组,但您需要确保它的大小能够处理最大字符串长度;此外,传递给分配更改的类型:

        #define STRING_SIZE ... /* large enough for longest string */
        void allocate(char (*dt)[STRING_SIZE+1])
        {
          char buf[] = "The Great Scorpion";
          char delim[] = " ";
          size_t i = 0;
          char *result = strtok(buf, delim);
          while (result)
          {
            strcpy(dt[i++], result);
            result = strtok(NULL, delim);
          }
        }
        
        int main(void)
        {
          char data[3][STRING_SIZE];
          allocate(data);
          ...
        }
        

        动态分配内存更加灵活,但需要进行一些记账,并且您必须记住在完成后释放它。

        【讨论】:

          【解决方案7】:

          为了不破坏堆栈,while 循环应使用传递参数“char *data[3]”的大小进行保护,在这种情况下为 3,即额外参数。

          但我同意将静态添加到“static char buf[] = ....”是摆脱指向已终止函数的解除分配堆栈的最快答案。

          【讨论】:

            【解决方案8】:

            您还没有分配要在 data[X] 内部使用的内存,只是分配了数据。

            数据[0] == 空指针

            【讨论】:

            • 对我来说很有意义。 j 从 1 开始,而不是 0。
            • 罗伯特:我正在使用 strtok 函数。所以只是想进入循环。
            • 你错过了*dt = result; - 它设置了dt[0]
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多