C中长度未定义的数组

4

我正在看一本教科书上的一个练习题,它说:创建一个C程序,从键盘输入一个长度为"N"的数组。

问题是:在C语言中,如何创建一个未定义长度的数组?

谢谢大家。


没有这样的事情。数组的长度是静态的,一旦分配就不能更改。对于这样的功能,您必须使用动态内存分配。 - Haris
2
@Haris 当然有:可变长度数组。 - this
@这里,他正在谈论未定义长度数组 - Haris
你的练习要求你创建一个具有N个元素的数组,该数组不是未定义的:首先要求输入长度,然后逐个从stdin读取值。无论如何,我认为这个练习意味着一个通用长度的数组。 - terence hill
编写一个C程序,从键盘输入长度为“N”的数组,并计算该数组的最小值、最大值和算术平均值。您会如何解决这个问题?(抱歉,我正在尝试从意大利语翻译成英语。) - AngeloP
实际上,这个问题有两个角度。第一种是程序必须从输入中填充一个具有N个元素的数组(其中N为常量),并执行操作...。第二种是程序必须创建一个动态数组(VLA)并从输入中填充它,然后执行操作...。在我看来,这是关于第一种情况,因为主题是如何对其进行计算。 - milevyo
3个回答

3
不要创建长度未定义的数组。
在获取所需长度N后,如果使用C99,则使用VLA(可变长度数组)。
int A[N];

...或者分配内存

int *A = malloc(sizeof *A * N);
...
// use A
...
free(A);

[编辑]

在继续之前,最好对 N 进行验证。例如:

if (N <= 0 || N >= Some_Sane_Upper_Limit_Like_1000) return;

当我设置 int A[N]; 时,我收到一个错误:使用了未声明的标识符 'N'。 - AngeloP
@Michelangelo Poli,你的编译器可能不符合C99标准,或者你没有声明“N”。建议使用第二种方法。如果还是不行,请发布你的代码。 - chux - Reinstate Monica
@Michelangelo Poli 如果有代码限制,最好最初在问题中发布它们,而不是后来添加到答案中。 - chux - Reinstate Monica
@cmaster 必须测试 N == 0,因为尝试形成大小为零的VLA会导致未定义的行为。 - M.M
2
我认为堆栈溢出也是一种潜在的错误,因此设置一个上限是个好主意。当然,代码应该被编写成如果输入超过了上限,程序能够正确地处理这种情况。 - M.M
显示剩余4条评论

2

了解有关c99中VLA的更多信息,请参阅The New C:Why Variable Length Arrays?

#include <stdlib.h>


int main(){
    int n;


    printf("size of array: ");
    scanf("%d",&n);
    // limit, and erro verification omited
    int f[n],i;

    printf("\nREADING INPUT\n");    
    for(i=0;i<n;i++){
        printf("\tValue of f[%d]: ", i);
        scanf("%d",f+i);
    }

    /*
    calc_max(f,n);
    calc_min(f,n);
    calc_avg(f,n);
    */
    printf("\n\nPRINTING VALUES:\n");
    for(i=0;i<n;i++){
        printf("\tValue of f[%d]= %d \n", i,f[i]);
    }
    return 0;
}

0

满足您100%的需求并不容易,但您可以尝试一下:

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

char *addMe(void);

int main(void){
    char *test = addMe();
    free(test);
    return 0;
}

char *addMe(void){
    unsigned int maxLength = 15;
    unsigned int i =0;

    char *name;
    int c;

    name = malloc(1);
    if(name == NULL){
        exit(1);
    }

    printf("Enter your name:>  ");

    while ((c = getchar()) != '\n' && c != EOF) {
        name[i++] = (char) c;

        if (i > maxLength) {
            printf("Names longer than %d not allowed!\n",maxLength);
            name[maxLength] = '\0';
            break;
        }else if (i < maxLength){
            name = realloc(name, maxLength + 2);
        }
    }

    name[i] = '\0';
    printf("Your name is:>  %s\nThe length is:>  %zu\n",name ,strlen(name));

    return name;
}

输出:

Enter your name:>  l
Your name is:>  l
The length is:>  1

你可能已经注意到,我只为一个字母分配了内存,如果你需要更多,它将被分配以满足你的需求。使用这种方法,你还可以控制最大尺寸:

Enter your name:>  Michael jacksonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
Names longer than 15 not allowed!
Your name is:>  Michael jackson
The length is:>  15

就像我说的,试一试吧。


“}else if (i < sizeof(char) * 15){” 应该改为 “}else if(i < maxLength){” 吧? - stek29
@stek29,你真是个有趣的家伙:)为什么要写成else if(i < maxLength)呢?两种方式都可以。在我的示例中,(i < sizeof(char) * 15)(i < maxLength)是一样的。我使用(i < sizeof(char) * 15)是有我的原因的。 - Michi
请问您能否解释一下为什么使用它?我只是想学习。 - stek29
1
注意:sizeof(char)的定义为1,因此使用它通常是多余的。 - hyde
此外,这段代码似乎毫无意义... 为什么要在每次输入循环中实现重新分配,而且为什么设置最大长度为15时要设置为30n呢? - hyde
显示剩余8条评论

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