如何在C语言中将未知数量的整数读入数组?

3

我知道我可以使用scanf读取一定数量的数字,例如读取3个数字。

scanf("%d %d %d",array[0],array[1],array[2]);

但如果我不知道在输入(非EOF)之前将有多少个数字(整数,而非浮点数)输入到数组中,那该如何扫描它呢?例如

input : 12 43 23(enter) --> array[0]=12, array[1]=43, array[2]=23
input : 10 20 30 40 50(enter) --> array[0]=10, array[1]=20, array[2]=30, array[3]=40, array[4]= 50
etc..

这篇文章讲述了如何将数字输入到整型数组中。

如果可能的话,我想将它保存到一个二维数组中,比如:

input : 12 43 23(enter) --> array[0][0]=12, array[0][1]=43, array[0][2]=23
input : 10 20 30 40 50(enter) --> array[1][0]=10, array[1][1]=20, array[1][2]=30, array[1][3]=40, array[1][4]= 50

1
读取整行并以其他方式解析?可以使用fgetsstrtol函数来实现。 - Some programmer dude
1
动态内存在这里会很方便。 - RoadRunner
此外,问题已经关闭,所以我不能直接回答(而且我认为你所问的并不完全是重复)。您想要保存它们,因此您可以再次创建一个大数组 int buf [1000],然后只需保持计数器(使用示例中的 i)并执行 buf [i] = a 来存储该值(并确保您不会在一行上获得超过1000个条目)。 - Iluvatar
@WeatherVane,根据您提供的链接,数字没有保存到整数数组中,如果我的数组有2行,我不能使用那些代码。 - juliussin
@WeatherVane 的列数与行数未知。 - juliussin
显示剩余10条评论
3个回答

1
这里是如何将东西存储在(动态分配的)数组中。但是,这假定行长度限制为1000个字符。(代码改编自如何使用scanf()获取任意数量的整数?
#include <stdio.h>
#include <stdlib.h>

int main() {
    int val_size = 2;
    int* vals = (int*)malloc(val_size * sizeof(int)); // initial array size
    char buffer[1000]; // for reading in the line
    int pos, bytes_read, num;
    int num_read = 0;

    if (fgets(buffer, sizeof(buffer), stdin) != 0) {
        for (pos = 0; sscanf(buffer+pos, "%d%n", &num, &bytes_read) != EOF; pos += bytes_read) {
            // resize the array if needed
            if (num_read >= val_size) {
                val_size *= 2;
                vals = (int*)realloc(vals, val_size * sizeof(int));
            }

            // store the value in the array
            vals[num_read] = num;
            num_read++;
        }
    }

    // print the values to prove it works
    for (int i = 0; i < num_read; i++) {
        printf("%d ", vals[i]);
    }
    printf("\n");

    free(vals); // important after you're done with it
}

你可以在 if 周围加上一个 while 来获取多行代码。

1
不应该从malloc/realloc中强制转换返回值。https://dev59.com/dHRB5IYBdhLWcg3wgHWr - AndersK
1
这似乎像是一场宗教战争,对吧?或者至少和 if (a == 0) vs if (0 == a) 类似?严格来说,也许它可以减轻一些用户错误,但两种方式都有优缺点。 - Iluvatar
1
虽然它的赞数只有最高赞答案的十分之一,但它们确实存在,而且在我看来大部分都是风格上的区别。 - Iluvatar
2
说实话,int *vals = malloc(val_size * sizeof *vals); 看起来比 int* vals = (int*)malloc(val_size * sizeof(int)); 更简洁。 - RoadRunner
1
@lluvatar 我不相信这个。这个问题标记为C,而不是C ++。如果您在C ++中使用malloc,则肯定做错了什么。 - AndersK
显示剩余4条评论

1
这里是一些代码演示如何将整数扫描到二维数组中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define INITSIZE 5
#define BUFFSIZE 1000

void print_and_free(int **array, int rowsize, int colsize);
void check_ptr(void *ptr, const char *msg);

int
main(void) {
    int **array;
    size_t rowsize = INITSIZE, colsize = INITSIZE;
    int row = 0, col, numdigits;

    char buffer[BUFFSIZE];
    char *number;

    array = malloc(rowsize * sizeof(*array));
    check_ptr(array, "Allocation");

    printf("Enter digits(Enter blank line to end):\n");
    while (fgets(buffer, BUFFSIZE, stdin) != NULL && strlen(buffer) != 1) {
        col = 0;
        numdigits = 0;
        if (rowsize == row) {
            rowsize *= 2;
            array = realloc(array, rowsize * sizeof(*array));
            check_ptr(array, "Reallocation");
        }

        array[row] = malloc(colsize *sizeof(int));
        check_ptr(array[row], "Allocation");

        number = strtok(buffer, " ");
        while (number != NULL) {
            numdigits++;
            if (colsize == numdigits) {
                colsize *= 2;
                array[row] = realloc(array[row], colsize * sizeof(int));
                check_ptr(array[row], "Reallocation");
            }
            array[row][col] = atoi(number);
            col++;
            number = strtok(NULL, " ");
        }
        row++;
    }

    print_and_free(array, row, col);

    return 0;
}

void
print_and_free(int **array, int rowsize, int colsize) {
    int row, col;

    printf("Your numbers:\n");
    for (row = 0; row < rowsize; row++) {
        for (col = 0; col < colsize; col++) {
            printf("array[%d][%d] = %d", row, col, array[row][col]);
            if (col != colsize - 1) {
                printf(", ");
            }
        } 
        free(array[row]);
        array[row] = NULL;
        printf("\n");
    }

    free(array);
}

void
check_ptr(void *ptr, const char *msg) {
    if (!ptr) {
        printf("Unexpected null pointer: %s\n", msg);
        exit(EXIT_FAILURE);
    }
}

顺便问一下,size_t rowsize = INITSIZE, colsize = INITSIZE; 是用来做什么的?谢谢。 - juliussin
不用担心,@juliussin。是的,它们只是从malloc开始分配空间的起始大小。我只是假设5是一个很好的起始大小,如果你的数组最终变得更大,那么就realloc更多的空间。如果你愿意,你可以用int替换size_t,这可能更清晰一些。 - RoadRunner

0
你可以使用一个 while 循环并检查 scanf 的返回值。例如:
int num = 0;
int idx = 0;
int arr[100] = { 0 };
while( scanf( "%d", &num ) == 1 )
{
    arr[idx++] = num;
    if( idx == 99 )  // protect from array overflow
    {
        break;
    }
}
for( int i = 0; i < idx; i++ )
{
    printf( "%d\n", arr[i] );
}

1
我认为这并不是他们想要的...它不能扫描一行中的多个整数。 - Iluvatar
@Iluvatar 是的,它确实如此。 - artm
不,尽管它可以扫描一行上的多个整数,但它未按要求在“Enter(而非EOF)”处终止。 - Weather Vane
是的,它会,但是你必须输入一些导致 scanf 解除阻塞的内容,所以仅仅敲击回车键是不够的。 - Iluvatar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接