这个问题说明我从用户那里获得输入,使用C中的结构输入n个名称。我写了下面的代码:
#include<stdio.h>
typedef struct employee{
int code;
char name[];
} emp;
int main () {
emp em;
int n;
printf ("Number of entries: ");
scanf ("%d", &n);
int i;
for (i=0;i<n;i++){
printf ("Enter name: ");
gets(em[i].name);
}
return 0;
}
我在这段代码中得到一个错误:
T2.c:16:16: error: subscripted value is neither array nor pointer nor vector
gets(em[i].name);
如何编写正确的代码??
我甚至尝试在使用的两个数组中放置维度,并使用scanf
函数。似乎什么都不起作用,我一次又一次地出错,
2条答案
按热度按时间nr9pn0ug1#
这里有几个问题。首先,定义的结构体的大小是一个
int
:name
参数的大小为0。这种定义在更高级的分配方法中很有用,我猜这有点超出您的技能范围。我们需要提供一个实际的大小:代码中的原始错误是由于试图访问定义的结构体,就好像它是一个数组,当它是一个单一的示例:
我在评论中建议的方法是使用
n
:如果你的编译器支持它,这是可以的,但是,这是一种特殊的数组,称为VLA。如果我们想避免这种情况,我们可以像对
name
参数一样,提供一个大小:就我个人而言,我甚至不知道如何使用
scanf
,因为它在像这样的家庭作业之外非常无用。我用你使用的scanf
和gets
替换了fgets
,它是gets
的安全哥哥。Don't use gets。注意atoi
是一个简单的字符串到int的转换函数。因为我们刚刚为students数组定义了一个最大大小,所以我们需要强制执行该限制,这样我们就不会在该数组的边界之外读取:这里是一个最终的解决方案,应该让你开始:
请注意,这个问题的一个更通用的解决方案(不包括使用这些
MAX_*
常量)将通过malloc
或calloc
使用动态内存分配。这种解决方案将允许学生的数量和他们名字的长度仅受系统上可用内存量的限制。但是,根据作业来猜测,你还没有谈到那个主题。li9yvcax2#
在循环中
你似乎在使用
em
,就好像它是一个n
元素的数组。但是,它不是数组。它只是一个单一的元素。要解决这个问题,您可以将
em
定义为variable-length array,如下所示:然而,并非所有编译器都支持可变长度数组,ISO C标准也不要求编译器支持它们。
或者,你可以定义一个固定长度的数组,像这样:
此解决方案适用于所有编译器,因为它不要求编译器支持可变长度数组。
另一个问题是,在行
您有责任确保有足够的内存来存储字符串。在程序中,没有足够的内存来存储任何长度的字符串,因为您甚至没有为字符串的终止空字符提供足够的空间。
在宣言中
成员
name
是flexible array member。如果你决定使用灵活数组成员,那么你有责任确保在对象之后立即有额外的可用内存来存储灵活数组成员的数据。在你的程序中,你不会这样做。您可能一开始就不想使用灵活的数组成员,因此我不会进一步解释如何使用它。为了确保
name
有足够的空间来存储字符串,您可以指定为存储字符串保留的固定字符数,例如:但是,如果用户输入的字符超过100个,那么程序将overflow数组
name
,这将调用undefined behavior。这意味着您的程序可能会崩溃或以其他方式行为不当。为了防止这种情况,我建议您使用函数
fgets
而不是gets
。但是请注意,与gets
不同,fgets
会将换行符写入字符串中,因此您可能希望将其删除。另一个问题是
将在输入流上留下换行符,这将导致下一次调用
gets
/fgets
读取一个空行,这不是您想要的。因此,您必须丢弃这个换行符(以及该行上的任何其他剩余字符),例如:下面是整个程序,它不使用可变长度数组:
此程序具有以下行为:
但是,我通常不建议使用
scanf
进行用户输入,因为对于基于行的用户输入,它的行为方式不直观。如前所述,它总是在缓冲区中留下换行符,可能还有其他一些字符。每当调用scanf
时,总是要删除它们,这是一件痛苦的事情。另外,在使用fgets
时,总是要检查换行符以验证是否读入了整行,并删除换行符,这是一件痛苦的事情。出于这个原因,我建议您编写自己的函数来处理所有这些。在下面的代码中,我将这些函数称为
get_int_from_user
和get_line_from_user
。我设计这些函数的方式是,它们还验证输入,如果输入无效,则重新提示用户。请注意,使用这些函数会使函数
main
更短更简单:下面是程序行为的一个示例:
正如您所看到的,当输入无效的输入时,该输入被丢弃,并重新提示用户输入。