【问题标题】:Allocating memory dynamically without knowing the size of the string which is going to be entered在不知道要输入的字符串大小的情况下动态分配内存
【发布时间】:2015-05-26 15:43:55
【问题描述】:

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

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

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

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

到目前为止的代码:

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;
}

【问题讨论】:

  • 变量ch是什么?
  • 是整数,getc返回整数
  • 您的代码无法处理 EOF。
  • str 为 NULL 如果realloc 失败,str[index++] = ch; => NULL[index++] = ch;

标签: c pointers realloc fgetc getc


【解决方案1】:

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

示例(来自同一 URL):

   #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);
   }

【讨论】:

  • 可能想要修复 int 主线。 :)
  • 请注意,POSIX 系统不应要求_GNU_SOURCE 提供对getline() 的访问权限。不过,您可能需要在包含第一个标头之前设置 #define _XOPEN_SOURCE 700#define _POSIX_C_SOURCE 200809L 才能看到 getline() 的声明。
  • @MartinTörnwall 它在两条线上。没什么大不了的
  • @user3711622 对于在实际函数名之前有很多标记的声明,或复杂的返回类型,将函数名放在新行上会很好——这样在查看时更容易发现大量的代码。也就是说,我没有写那个例子。
  • 那个,你可以正则表达式搜索^&lt;function name&gt;。虽然我很少在其他语言中看到它,但这是 C 中非常常见的格式化模式。
【解决方案2】:

“内存分配方法有什么缺陷吗?” 是的,当重新分配失败时,你释放之前的内存指针,分配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

【讨论】:

  • @BLUEPIXY 刚刚注意到你的评论。
猜你喜欢
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 2018-03-05
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 2021-06-11
相关资源
最近更新 更多