【问题标题】:How to allow user input for an array without initial size?如何允许用户输入没有初始大小的数组?
【发布时间】:2017-04-11 12:32:07
【问题描述】:

我一直在阅读有关如何在事先不知道数组大小时声明数组的内容。据我了解,这样做的方法是为用户输入的数组分配一些内存,然后根据需要重新分配或释放。对于一个字符数组,我是这样做的:

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

int main()
{
    //allocation of memory
    char *a = malloc(200 * sizeof(char));

    //allow user input
    fgets(a, 200, stdin);

    int i = 0;

    //find the length of the array
    int lstring = strlen(a);

    printf("%d", lstring-1);

    free(a);

    return 0;
}

这里用户没有输入char数组的实际大小,但可以通过查看字符串字符结束的位置来知道。

另一方面,对于整数数组,我有这个:

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

int main()
{
    //allocation of memory
    int *b = malloc(200 * sizeof(int));

    b[0] = 2;
    b[1] = 76;
    b[2] = 123;

    printf("%d", b[0]);

    free(b);

    return 0;
}

我的问题是,我怎样才能让用户输入整数?

我想到的第一件事是创建一个带有scanf()for 循环,但除非允许用户先输入数组的大小,否则这是行不通的。有没有一种方法(等同于或不等同于注意到的 char 数组)在不让用户显式输入大小的情况下执行此操作?

【问题讨论】:

  • @WeatherVane Ups!我的意思是int *b = malloc(200 * sizeof(int));
  • 请查看使用realloc 扩展数组。
  • 暂时忽略代码,您希望它如何从用户的角度工作?他们是否希望在同一行输入所有数字?还是他们应该输入某种“我完成了”的指示符?也许 Ctrl-D/Ctrl-Z 表示文件结束?
  • @JohnKugelman 好吧,实际上我的实际任务是反转用户输入的整数的顺序。因此,正如我的作业示例所提出的,用户在同一行输入数字1 7 5,单击回车,下面会打印出序列5 7 1。我的问题不是整数的实际交换,而是用户未输入 (:.

标签: c arrays


【解决方案1】:

我想到的第一件事是创建一个带有scanf()for 循环,但除非允许用户先输入数组的大小,否则这是行不通的。有没有一种方法(等同于或不等同于注意到的 char 数组)在不让用户明确输入大小的情况下执行此操作?

你在正确的轨道上...... 使用特殊的 / 标志值,以了解用户条目的结束,例如这里我使用-1 表示用户条目的结束

//allocating memory
int *b = malloc(200 * sizeof *b);

//notify the user with a message:
printf("enter -1 to stop entry\n");

//loop to scan user entries
for(int i = 0; i < 200; i++){
    //scanning user's input
    scanf("%d", &b[i]);

    //break when user enters -1
    if(b[i] == -1){ 
        break;
    }
}

您还可以使用-1,就像使用'\0' 来标记字符串的结尾一样。例如:

int length = 0; //variable to know length of array

//printing all the values of int array and knowing its length:
for(int i = 0; b[i] != -1; i++){
    //for printing array elements
    printf("%d ", b[i]);

    //to know the length
    length++; 
}

如果用户输入的整数数量超过预期怎么办?

你可以使用realloc 并且每次达到最大值时都使用双倍数组的大小

例如:

int max_entry = 100; //instead you can initialise max_entry by taking user's input 

//allocating memory
int *b = malloc(max_entry * sizeof *b);

//notify the user with a message:
printf("enter -1 to stop entry\n");

//loop to scan user entries
for(int i = 0; ; i++){
    scanf("%d", &b[i]);

    if( i == max_entry - 1 && b[i] != -1){
        //increasing max entry
        max_entry *= 2;

        //reallocating to increase size of array
        int *temp = NULL;
        temp = realloc(b, max_entry * sizeof *b);

        if(temp == NULL){
            //allocation failed, handle it
        }
        else{
            b = temp;
        }
    }

    //break when user enters -1
    if(b[i] == -1){ 
        break;
    }
}

【讨论】:

    【解决方案2】:

    是的,您可以为此使用realloc()。一种常见的方法是创建一个结构,它将代表您的数组,可以扩展。该结构可能如下所示:

    typedef struct
    {
        int allocated; // Here you can save how many elements you have allocated space for
        int used; // Here is how many elements are in the array
        int * array; // here is pointer to the array
    
    } Array;
    

    然后你应该创建一个函数来初始化这个数组结构:

    void initArray(Array * a)
    {
        a->allocated = INIT_SIZE;
        a->used = 0;
        a->array = malloc(INIT_SIZE * sizeof(int));
    }
    

    现在数组已初始化,您已经为INIT_SIZE 元素分配了内存。现在最重要的部分 - 实际添加元素。您也可以为此创建一个函数:

    bool insertEl(Array * a, int el)
    {
        if(a->used == a->allocated) //If there is no more space, then we need to realloc
        {
            int * temp = realloc(a->array, 2 * a->allocated * sizeof(int));
            if(!temp) // Just check if realloc succeeded
            {
                printf("Reallocation failed!\n");
                return false;
            }
            a->array = temp;
            a->allocated *= 2;
        }
    
        a->array[a->used] = el;
        a->used++;
    
        return true;
    }
    

    由于重新分配是一项非常昂贵的操作,因此增加分配的元素数量而不是仅仅增加一些常量是个好主意。我通常把空间加倍。由于您使用了malloc()realloc() 来分配内存,因此您应该在完成后使用free()

    void freeArray(Array * a)
    {
        free(a->array);
        a->array = NULL;
        a->allocated = 0;
        a-> used = 0;
    }
    

    一旦你有一个这样的数组结构,你可以在循环中运行scanf(),直到有一个EOF,在每个循环中,你scanf()输入并使用insertEl()函数将它添加到数组。

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 2021-12-31
      • 2017-09-21
      • 2017-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-01
      • 1970-01-01
      相关资源
      最近更新 更多