如何在C语言中不指定数组大小的情况下将数字读入数组

Posted

技术标签:

【中文标题】如何在C语言中不指定数组大小的情况下将数字读入数组【英文标题】:How to read numbers into an array without specifying the array size in C language 【发布时间】:2021-03-16 09:07:55 【问题描述】:

如何从标准输入中读取整数并将它们存储在数组中?我事先不知道我必须从标准输入中读取多少个整数。

输入示例

4 5 6 7 8

(或)

4,5,6,7,8 

(或)

4
5
6
7
8

输出示例:只需打印该数组即可。

在 Python 中我可以这样做:

arr = list(map(int,input().split(' ')))

在 Python 中这很容易,因为我不需要事先指定数组的大小。 如何从输入中读取整数并将它们以这种方式在 C 中存储到数组中?有可能吗?

【问题讨论】:

视情况而定 - 如果将其作为字符串,则可以直接使用。其他类型,有可能但并不容易。 两种语言都有缺点:你当然可以在 C 中做到这一点,但有点乏味。至于 Python,将数组称为 list 正在培养整整一代困惑的程序员。对 GVR 感到羞耻。 这能回答你的问题吗? Read from standard input into a C array 【参考方案1】:

这里的主要问题是创建一个足够宽的数组来存储标准输入中包含的所有整数,但我们不知道要读取多少个值。

输入是硬盘驱动器上的文件

如果你从一个文件中读取,你可以读取文件两次:第一次,你不存储值,你只计算有多少值;第二次,您使用malloc() 分配一个大小合适的数组,并将整数存储到数组中。

从标准输入读取输入

另一方面,如果你从标准输入读取,你不能读取输入两次,因为你一读取它就被消耗掉了。所以你需要计算数组的大小,同时将元素存储在数组中。为此,首先分配一个大小为 10 的数组,然后从标准输入读取 10 个值,如果数组不够大,则分配另一个更大的值,复制从第一个数组读取的值进入第二个数组,删除第一个数组,然后继续执行此操作,直到用完所有输入。

算法如下:

    malloc() 分配一个由10 个整数组成的数组。 使用scanf() 从标准输入中读取整数,直到输入结束或数组已满。 如果没有更多整数可以从标准输入中读取,请停止。 否则,使用函数realloc() 将数组大小加倍,然后返回步骤2。realloc() 函数可能会分配具有新大小的第二个数组,将第一个数组中的整数复制到第二个数组的前半部分(如果第一个数组结束后没有足够的可用空间来扩展它,则会发生这种情况)。

如果太难了

它不像 Python 那样是单行的。对于初学者来说,正确地做到这一点实际上是相当困难的。如果您太费劲,只需将标准输入转储到硬盘驱动器上的临时文件中,然后使用两次读取文件的技巧。

如果输入是由您控制的东西产生的,您也可以尝试更改输入的格式。例如,如果您将需要读取的值的数量添加为输入的第一个元素,它将简化您的任务。

【讨论】:

很抱歉我没明白你能用代码简单解释一下吗。 @RalphS,您也可以提及4,5,6,7,8 形式的读取输入,我们需要使用fgets等函数 @UDAY 是的,我会添加更详细的解释。 @UDAY,关键是您需要跟踪 1) 数组当前可以容纳多少元素,以及 2) 当前填充了数组的多少元素。大多数时候,您将拥有一些已分配但实际上并未使用的元素。 Python 会在幕后为您做到这一点。 @UDAY 是否足够清楚,还是需要更详细的解释?【参考方案2】:

(最)灵活的解决方案是使用动态链表(它仍然具有数组的属性,您可以在其中迭代/遍历它)。在下面的示例中,您可以使用链表找到两 (2) 个场景,其中在场景 #1 中,用户使用逗号分隔的整数列表提供一次输入;而对于场景 #2,将提示用户,直到提供特定输入。 示例输出

=== Scenario 1 ===
Enter comma delimited integer (e.g. 1,2,3,4): 1,6,8,9
=Print List=
1
6
8
9

=== Scenario 2 ===
Enter integer (-99 to stop): 3
Enter integer (-99 to stop): 4
Enter integer (-99 to stop): 5
Enter integer (-99 to stop): 6
Enter integer (-99 to stop): 7
Enter integer (-99 to stop): -99
=Print List=
3
4
5
6
7

示例代码:

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

struct Element

    int data;
    struct Element *next;
;

void printList(struct Element *list) 
    printf("=Print List=\n");
    while(list != NULL) 
        printf("%d\n", list->data);
        list = list->next;
     //end while


int main(void) 
    /* 1. This is for the case where input from user is expected to be once and is using comma delimited.
    Data will be stored on a dynamic linked list.
    Note: input is not validated. */
    char str1[256];
    char delimiter[2] = "," ;
    struct Element *listResult = NULL; //this is to store the result list
    struct Element *lastElement=NULL;

    printf("=== Scenario 1 ===\n");
    printf("Enter comma delimited integer (e.g. 1,2,3,4): ");
    scanf("%s", str1);
    char *token = strtok(str1, delimiter);

    //Parse the input and put into the linked list
    while(token != NULL ) 
        int intData = atoi(token);
        struct Element *newElmt = (struct Element *) malloc (sizeof(struct Element));
        newElmt->data = intData;
        newElmt->next = NULL;

        if (listResult == NULL)  //listResult is initially empty, put the new element as the head
            listResult = newElmt;
            lastElement = newElmt;
         else  //listResult is NOT empty, put the new element as the tail
            lastElement->next = newElmt;
            lastElement = newElmt;
         //end if
        token = strtok(NULL, ",");
     //end while
    printList(listResult);

    /* 2. This is for the case where input from user is expected to be multiple times until specific input is provided (i.e. -99).
    Data will be stored on a dynamic linked list.
    Note: input is not validated. */
    int inputInt=0;
    struct Element *listResult2 = NULL; //this is to store the result list
    struct Element *lastElement2 = NULL;

    printf("\n=== Scenario 2 ===\n");
    do 
        printf("Enter integer (-99 to stop): ");
        scanf("%d", &inputInt);

        if (inputInt != -99) 
            struct Element *newElmt = (struct Element *) malloc (sizeof(struct Element));
            newElmt->data = inputInt;
            newElmt->next = NULL;

            if (listResult2 == NULL)  //listResult2 is initially empty, put the new element as the head
                listResult2 = newElmt;
                lastElement2 = newElmt;
             else  //listResult2 is NOT empty, put the new element as the tail
                lastElement2->next = newElmt;
                lastElement2 = newElmt;
             //end if
         //end if
     while (inputInt != -99);
    printList(listResult2);

    return 0;

【讨论】:

以上是关于如何在C语言中不指定数组大小的情况下将数字读入数组的主要内容,如果未能解决你的问题,请参考以下文章

c语言中怎么用二维数组作为函数参数

C#如何在不知道新数组长度的情况下将数组中的值保存到新数组中

如何在不转换为json的情况下将C#数组用于javascript数组?

如何在不使用向量的情况下将数组传递给函数?

动态内存分配

标准C语言中如何将字符串中的内容转换为字符数组?