【问题标题】:Reading an array of strings in C在 C 中读取字符串数组
【发布时间】:2012-05-08 09:35:23
【问题描述】:

我想读取数组中的一组字符串。数组的大小将在运行时使用mallocalloc 决定,即接受字符串的数量作为输入。我尝试了以下代码,但没有成功。

char *array;
array=(char*)malloc(sizeof(char)*t); //t is the size of array
for(int temp=0;temp<t;temp++)
{
    gets(a[temp]);
}

在整数数组的情况下也是如此。
请帮助我找到解决方案。

【问题讨论】:

  • BTW sizeof(char) 是多余的;它被 C 标准定义并要求为 1。
  • @glglgl 对,sizeof(char) 是多余的。相反,我应该使用 malloc(1*t)。
  • 为什么不只是malloc(t)? :-)

标签: c arrays string


【解决方案1】:

C 没有任何自动内置支持存储字符串,没有“字符串”变量,并且可以自动增长以容纳适当数量的字符。你需要自己分配内存。

您现在正在做的是为正确数量的字符指针分配位置,而不是为任何字符分配位置。所以gets() 调用正在写入未分配的内存,这是未定义的行为。由于每个整数都完全适合单个分配,这就是为什么类似的代码适用于整数。字符串比较复杂,所以需要做更多的工作。

如果这些字符串的长度有任何已知的上限,您可以使用固定长度的临时缓冲区,然后在知道所需大小后将其复制到新分配的动态内存中。如果没有这样的界限,你需要重复相同的概念,通过读取一个固定的块,存储它,如果没有找到行尾,读取另一个块,使用realloc()增加这个字符串的内存分配,追加新字符,并重复直到行结束。

附带说明,您应该始终避免使用@987654321@,因为它不支持保护您的程序免受缓冲区溢出。使用 fgets() 会好得多,记录在同一页面上。

【讨论】:

    【解决方案2】:

    您分配的空间恰好是一个字符串,以零结尾的格式存储。

    如果你想存储几个字符串的数组,你需要malloc()一个char *的数组加上几个字符串。

    此外,gets() 是不安全的,因为没有大小限制。相反,请使用fgets()。它具有以下签名:

    char *fgets(char *restrict s, int n, FILE *restrict stream);
    

    因为它想要一个流,你应该给stdin

    所以阅读一行的最佳方式是

    char * read_one_line(uint32_t maxbufsize)
    {
        char * s = malloc(maxbufsize);
        if (!fgets(s, maxbufsize, stdin)) {
            free(s);
            return NULL;
        } else {
            char * s2 = realloc(s, strlen(s)+1); // +1 for the NUL at the end
            if (s2) {
                return s2;
            } else {
                return s; // should never happen as the memory block is shrinked
            }
        }
    }
    

    此函数分配一行所需的内存,读取后适当调整大小,并留给调用者在适当的时间再次释放。

    【讨论】:

    • 读取输入字符串数组的另一种有效方法是什么?
    【解决方案3】:

    您需要先为字符串数组 (char*) 分配空间:

    char **array;
    array = (char**)malloc(sizeof(char*)*t);
    

    然后您需要为它们中的每一个分配空间(让50 成为这些字符串的最大字符数):

    int i = 0, m = 50;
    for (i = 0; i < t; ++i)
        array[i] = (char*)malloc(sizeof(char)*51); // 51 = 50 characters + '\0'
    

    然后你就可以做你想做的事了:

    for(i = 0; i < t; ++i)
        scanf("%50s", array[i]);
    

    最好使用具有指定宽度%50s = 50 个字符 + '\0')的scanf,而不是gets

    【讨论】:

      【解决方案4】:

      请记住,最后在字符数组中应该有一个NUL 字符。

      所以用allocmalloc分配t+1字节的内存。

      t 字节用于字符,1 字节用于终止 NUL 字符。

      在您的for 循环之后,即在循环之外,只需编写

      a[temp] = '\0';
      

      那么你就可以在工作中使用它了。

      我希望它会起作用。

      看起来像这样

      char *a = malloc(sizeof((char)*(t+1)));//t is number if characters
      int temp;
      for(temp=0; temp<t; temp++) {
          gets(a[temp]);
      }
      a[temp] = 0;
      

      然后打印数组,你会得到一个字符串。

      printf("%s",a);
      

      【讨论】:

      • 什么,你想为每个字符调用malloc?!
      • malloc 只执行一次 (t+1) 次
      • 在您的上下文中“时间”是什么意思?你是说字节吗?
      • 是的,我的意思是 (t+1) 个字节...,'t' 个字节用于存储字符串,1 个字节用于存储 NULL。
      • 1.您的代码示例仅读取一个字符串(一行)。 2. 它使用了固有的不安全gets()。不好。
      猜你喜欢
      • 2017-02-16
      • 1970-01-01
      • 2017-09-29
      • 2014-11-21
      • 2011-11-01
      • 2013-03-20
      • 2012-10-19
      • 2018-05-02
      • 2023-04-04
      相关资源
      最近更新 更多