在不知道要输入的字符串大小的情况下动态分配内存

时间:2015-05-26 15:43:55

标签: c pointers realloc fgetc getc

下面是一个函数,它返回一个字符指针,该字符串指向使用getc(stdin)初始化的字符串 - 逐个字符。

  1. 内存分配方法有什么缺陷吗?当我们不知道要输入的字符串的大小时,这是一种有效的方法,如果不是,请解释。

  2. 使用getc(stdin) - 会导致缓冲区溢出???()

  3. 如果我不能使用getc(stdin),有什么能帮助我以更有效的方式实现目标?

  4. 到目前为止

    代码:

    char *getstring()
    {
      char *str = NULL, *tmp = NULL;
      int size = 0, index = 0;
      int ch = -1;
      int length=0;
      while (ch!=0) 
      {
        ch = getc(stdin);
    
        if (ch == '\n')
        {   
            ch = 0;
        }
    
        if (size <= index) 
        {
            size += 15;
            tmp = (char*)realloc(str, size);
            if (!tmp) 
            {
                free(str);
                str = NULL;    
            }
            str = tmp;
        }
        str[index++] = ch;
      }
    
      if(size==index)
      {
        return str;
      }
      else if(index<size)
      {
        length=strlen(str);
        tmp = (char*)realloc(str,(length+1));
        str[index]='\0';
        //cout<<"length:"<<length;
        str=tmp;
      }
    
      return str;
    }
    

2 个答案:

答案 0 :(得分:1)

不要重新发明轮子:使用getline(3)

示例(来自相同的网址):

   #define _GNU_SOURCE
   #include <stdio.h>
   #include <stdlib.h>

   int
   main(void)
   {
       FILE *stream;
       char *line = NULL;
       size_t len = 0;
       ssize_t read;

       stream = fopen("/etc/motd", "r");
       if (stream == NULL)
           exit(EXIT_FAILURE);

       while ((read = getline(&line, &len, stream)) != -1) {
           printf("Retrieved line of length %zu :\n", read);
           printf("%s", line);
       }

       free(line);
       fclose(stream);
       exit(EXIT_SUCCESS);
   }

答案 1 :(得分:0)

&#34;内存分配方法是否有任何缺陷?&#34; 是的,当重新分配失败时,释放先前的内存指针,为其分配NULL,然后用tmp覆盖它,其值为NULL,然后使用NULL指针进行翻转。

if (size <= index) 
{
    size += 15;
    tmp = (char*)realloc(str, size);
    if (!tmp)                   // <--- NULL!
    {
        free(str);
        str = NULL;    
    }
    str = tmp;                  // <--- NULL!
}
str[index++] = ch;              // <--- NULL!

但如果realloc失败,你别无选择,只能优雅地放弃手中的任务。

此外,如果您同时允许0终止符,您将保存几行杂乱的代码和另一个重新分配。并且您不必总是插入'\0'

if (size <= index+1)            // allow room for string terminator