【问题标题】:C program malloc with array of strings带有字符串数组的 C 程序 malloc
【发布时间】:2018-10-10 03:54:25
【问题描述】:

在程序开始时,我需要为未知数量的大小未知的字符串动态分配内存,以便以后使用。要从我拥有的用户那里获取字符串的数量:

int main(int argc, char *argv[]){

int number = atoi(argv[1]);

到目前为止一切顺利。 “数字”现在保存用户在命令行上输入的用于执行代码的数字。现在到了我不太明白的部分。我现在需要动态存储字符串的长度以及字符串的内容。例如,我希望程序像这样运行:

Enter the length of string 1: 5
Please enter string 1: hello
Enter the length of string 2: ...

为此,我认识到我必须创建一个字符串数组。但是,我不太明白指针指针的概念以及什么不是。我想要的可能是简化如何实现这一点?

【问题讨论】:

  • 你的程序到底需要什么?
  • @AsthaSrivastava 我希望这些字符串稍后比较长度、连接它们、复制它们等,但我对这些东西很熟悉。我只是不知道如果有未知长度的未知数字如何动态分配它们。
  • Enter the length of string 1: 5 然后Please enter string 1: hello 小心,虽然您可以在 array [5] char 中存储 5 个字符 'h''e''l''l''o',它不会是一个 string 字符。 (最后没有 nul-terminating 字符——这需要 6 个字符的存储空间)任何使用包含 "hello" 的数组作为 string 的尝试都会导致 Undefined Behavior 因为字符串函数疯狂地搜索整个堆栈以寻找 nul-character...
  • 另外,不要使用atoi(argv[1])——它提供错误检查功能(如果argv[1] = "duck"呢?而是使用strtol,它提供可靠的错误处理能力。
  • 程序应该做的第一件事是测试argc 以确保用户实际输入了参数。如果没有输入参数,则输出 USAGE 语句 (fprintf( stderr, (USAGE: %s [numberOfStrings]\n", argv[0] );` 然后调用 exit( EXIT_FAILURE ) 其中 exit()EXIT_FAILURE 是发现于stdlib.h

标签: c string dynamic-memory-allocation


【解决方案1】:

您从一开始就知道要存储number 字符串,因此您需要一个大小为number 的数组来存储指向每个字符串的指针。

您可以使用mallocnumber char 指针动态分配足够的内存:

char** strings = malloc(number * sizeof(char*));

现在您可以循环number 次并动态分配每个字符串:

for (int i = 0; i < number; i++) {
   // Get length of string
   printf("Enter the length of string %d: ", i);
   int length = 0;
   scanf("%d", &length);

   // Clear stdin for next input
   int c = getchar(); while (c != '\n' && c != EOF) c = getchar();

   // Allocate "length" characters and read in string
   printf("Please enter string %d: ", i);
   strings[i] = malloc(length * sizeof(char));
   fgets(strings[i], length, stdin);
}

【讨论】:

  • 我可以按照大部分内容进行操作。澄清一下:char** 是指向 char 的指针吗?至于 fgets 我不熟悉该功能,但我可以研究。谢谢。
  • char** 是对的,它是一个指向字符指针的指针。在这种情况下,如果char* 是一个字符串,那么char** 本质上是一个动态分配的数组如果是字符串。
  • 你可以阅读fgets here
  • 哈哈 一个指针指向一个指针有点弯曲我的大脑,但感谢您的回答以及我可以了解新功能的地方。
  • 除非你已经重定向了一个包含 10 个数字的文件作为输入,fseek(stdin,0,SEEK_END); 将调用 Undefined Behavior 因为stdin 是不可搜索的,除非输入是由文件重定向提供的。 (例如可查找的文件)要将stdin 清除到行尾,只需使用int c = getchar(); while (c != '\n' &amp;&amp; c != EOF) c = getchar();
【解决方案2】:

由于您想保存 both 长度和字符串,我建议您将它们放在一个结构中。喜欢

struct string
{
    int length;
    char* str;
};

现在您可以动态创建此结构的数组并为各个字符串动态分配内存。

类似:

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

struct string
{
    int length;
    char* str;
};

int main(void) {
    int i;
    char tmp[128];
    int number = 3;
    struct string* strings = malloc(number * sizeof *strings);

    // read the input
    for (i=0; i<number; ++i)
    {
        printf("length?\n");
        if (fgets(tmp, sizeof tmp, stdin) == NULL)
        {
            printf("error 1");
            exit(1);
        }
        int length;
        if (sscanf(tmp, "%d", &length) != 1)
        {
            printf("error 2");
            exit(1);
        }
        strings[i].length = length;
        strings[i].str = calloc(length + 2, 1);
        printf("string?\n");
        if (fgets(strings[i].str, length + 2, stdin) == NULL)
        {
            printf("error 3");
            exit(1);
        }
        if (strings[i].str[length] != '\n')
        {
            printf("error 4");
            exit(1);
        }
        strings[i].str[length] = '\0';
    }

    // print the strings
    for (i=0; i<number; ++i)
    {
      printf("len=%d str=%s\n", strings[i].length, strings[i].str);
    }

    // Clean up, i.e. free the memory allocated
    for (i=0; i<number; ++i)
    {
        free(strings[i].str);
    }
    free(strings);

    return 0;
}

注意:您还应该检查所有malloc/calloc 是否成功,即不返回NULL。为了清楚起见,我跳过了。

【讨论】:

  • 通过使用fgets(strings[i].str, length + 1, stdin) 准确读取字符的确切数量fgets 将使用+1 作为nul-character 的存储空间,您将留下每个@987654328 @(由用户按 [Enter] 生成)在 stdin 中未读,必须在下次调用 fgets 之前将其删除,以避免将未读的 '\n' 读取为下一个输入。
猜你喜欢
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多