【问题标题】:How to create an array of strings of unknown size?如何创建一个未知大小的字符串数组?
【发布时间】:2020-12-16 04:54:06
【问题描述】:

我试图了解如何创建一个 C 程序来声明一个“字符串数组”,其大小在声明时是未知的。这是我到目前为止所得到的:

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

int main(void) {
  int n, i;
  char** words;

    printf("How many strings you want to input? \n");
    scanf("%d", &n);

  words = malloc(sizeof(char*) * n);

  for (i = 0; i < n; i++) {
    printf("Input your %d string: ", i + 1);
    scanf("%s", words[i]);
  }

  for (i = 0; i < n; i++) {
    printf("%s\n", words[i]);
  }

  return 0;
}

程序编译,但我收到Segmentation fault 错误。

【问题讨论】:

  • 您分配了char *[] 数组,现在您需要分配用户输入的每个 字符串,即每个words[i] 都需要分配。你怎么知道大小......大谜团!要么分配一个唯一的大字符串并确保用户输入的内容不超过此,输入其中,分配words[i] 与现在已知的大小,然后将大字符串复制到这个新分配的区域。
  • 不检查返回值就不要使用scanf()...

标签: c string memory-management malloc


【解决方案1】:

您只为指向字符串的指针分配了内存,而没有为字符串本身分配内存。尝试将字符串存储在未分配的内存中会调用未定义的行为。

指针只是指针。您不能在其中存储字符串。您需要为指针应该指向的位置保留内存。

#define STR_SIZE 100              // max length of a string (incl. null terminator)

printf("How many strings you want to input? \n");
if (scanf("%d", &n) != 1)
{
    fputs("Error at input", stderr);
    // further error routine.
}

// allocate memory for the pointer to the strings.
words = malloc(sizeof(*words) * n);      
if (!words)
{
    // error routine if the memory allocation failed.
    perror("malloc"); 
    exit(EXIT_FAILURE);    
}

// allocate memory for the strings themselves.
for (int i = 0; i < n; i++)
{
     words[i] = malloc(sizeof(**words) * STR_SIZE);   
     if (!words[i])
     {
         // error routine if the memory allocation failed.
         perror("malloc"); 
         exit(EXIT_FAILURE); 
     }
}

旁注:

  • 如果分配时发生错误,请务必检查内存管理函数的返回! scanf() 等输入操作也是如此。

  • 请注意,使用 sizeof(*words) 和 sizeof(**words) 而不是 sizeof(char*) 和 sizeof(char) 对于代码更改的情况更安全。

【讨论】:

  • 好答案,我忘了检查内存分配中的错误。在第一次分配中使用sizeof(*words) 和在分配字符串时使用sizeof(**words) 有什么区别?为什么更安全?我的意思是我可以写 *char,因为所有指针的大小都一样吗?
  • @BobbyWan-Kenobi Here 你得到它的详细解释。
  • @BobbyWan-Kenobi 不,指针类型不需要具有相同的大小。这是一个常见的混淆。 Here 是我的另一个答案,我关注它并链接到其他关注它的好答案。
  • 感谢您的肯定。为什么在第一次内存分配中你不使用sizeof(**word)`` and in the second one sizeof(*word)`?看来你把它们交换了没有?
  • @BobbyWan-Kenobi words 是指向char 的指针(类型char **)。如果你取消引用words (*words) 你会得到一个指向char (类型char *) 的指针。这就是我们第一步需要的,因为我们需要为指针分配空间。如果你双重取消引用words (**words) 你会得到一个char。这就是我们在第二步为实际字符串分配内存时所需要的。
【解决方案2】:

您没有为单个字符指针 words[i] 正确分配内存。

这没问题 - 你为指向 char words 的指针分配了内存:

words = malloc(sizeof(char*) * n);

但是您还没有为 words 的各个指针分配。为此,您需要为单个单词提供多少缓冲区。例如,如果每个单词是 100 个字符,那么:

for (i = 0; i < n; i++)
{
    printf("Input your %d string: ", i + 1);
    words[i] = malloc(sizeof(char) * 100);  //<--
    scanf("%s", words[i]);
}

还记得在完成后释放缓冲区。

for (int i=0; i<n; ++i) {
    free(words[i]);
}

free(words);
return 0;

【讨论】:

  • 答案也很好,完成后我根本没有释放内存。现在不知道该选哪个答案了,这个还是上面那个……
猜你喜欢
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
相关资源
最近更新 更多