您的问题的简单答案是您已定义 #define MAX 1,因此您的结构 struct Number data[MAX]; 数组中只有 1 个元素,这意味着您只能读取一个名称。
除此之外,您还有许多问题所在。在接受用户输入时,除非您检查输入函数的返回以确定输入是成功还是失败,否则无法正确执行。使用scanf("%s", ... 读取名称时会出现问题,因为"%s" 格式说明符在遇到第一个空格时停止读取。这意味着您将永远无法将 "Siam C." 读取为名称。
而不是使用scanf() 进行用户输入,建议您使用fgets(),这样您每次都会消耗一整行输入。这样,stdin 中剩余的未读内容不取决于scanf() 格式说明符以及是否发生匹配失败。使用fgets() 读取整行,然后您可以使用sscanf() 从该行中提取任何需要的数值。然后在匹配失败的情况下,stdin 中没有任何内容可以中断您的下一次尝试读取。
在显示菜单时,使其在您的代码中可读。除非您将数字转换为输出,否则不需要printf() 一个简单的puts()(或fputs(),如果需要行尾控制)就可以了,例如
while (1) { /* loop continually */
/* make your menu readable */
fputs ("\nPress 'Enter' on a blank line when done\n\n"
" 1) Read data\n"
" 2) Show Data\n\n"
"Choice: ", stdout);
当您必须根据多个输入值确定要采用哪个分支时,请考虑使用switch() 语句而不是if ... else if ... else 的长链。它的功能相同,但提供了更结构化的方法,例如
/* use a switch to control */
switch (option) {
case 1: read (data, &nelem); break;
case 2: show (data, nelem); break;
default: fputs ("error: invalid choice.\n", stderr); break;
}
如上所述,您需要保留一个单独的计数器来跟踪填充的结构数量。将其作为参数传递给您的 show() 函数,以便您知道要显示多少个结构(还要检查它是否为零并显示 "empty-list" 或类似的)。
对于您的 read() 函数,您可以将指针传递给计数器并在您的 read() 函数中更新计数器,以便更新后的计数可以在 main() 中返回,或者您可以返回读取的数字并将其添加到保留在main() 中的计数中。 (无论哪种方式都可以,但传递指针更方便一些)例如,您的 read() 函数可以是:
/* update the number of elements filled through the nelem pointer */
void read (struct Number *data, size_t *nelem)
{
putchar ('\n'); /* newline separator */
while (*nelem < MAX) { /* check array not full */
char *p = data[*nelem].name; /* pointer to cut down typing */
fputs ("enter name: ", stdout); /* read with fgets() */
if (!fgets (p, MAX, stdin) || *p == '\n') /* check return & blank line */
break;
p[strcspn (p, "\n")] = 0; /* trim '\n' from end of name */
(*nelem)++; /* increment name count */
}
}
(注意: 输入完姓名后,只需在空白行按 Enter —— 使用fgets() 进行输入的另一个好处。还要注意使用strcspn() 将fgets() 包含的'\n' 从每个名称的末尾删除。这是最简单、最可靠的方法。)
您的show() 函数可以是:
/* pass the number of filled struct as parameter */
void show (struct Number *data, size_t nelem)
{
size_t i;
putchar ('\n'); /* newline separator */
if (nelem == 0) { /* check if list is empty */
puts (" (list-empty)");
return;
}
for (i = 0; i < nelem; i++) /* output all names */
printf(" Name: %s\n", data[i].name);
}
总而言之,您将拥有:
#include <stdio.h>
#include <string.h>
#define MAX 100 /* if you need a constant, #define one (or more) */
struct Number {
char name[MAX];
};
/* pass the number of filled struct as parameter */
void show (struct Number *data, size_t nelem)
{
size_t i;
putchar ('\n'); /* newline separator */
if (nelem == 0) { /* check if list is empty */
puts (" (list-empty)");
return;
}
for (i = 0; i < nelem; i++) /* output all names */
printf(" Name: %s\n", data[i].name);
}
/* update the number of elements filled through the nelem pointer */
void read (struct Number *data, size_t *nelem)
{
putchar ('\n'); /* newline separator */
while (*nelem < MAX) { /* check array not full */
char *p = data[*nelem].name; /* pointer to cut down typing */
fputs ("enter name: ", stdout); /* read with fgets() */
if (!fgets (p, MAX, stdin) || *p == '\n') /* check return & blank line */
break;
p[strcspn (p, "\n")] = 0; /* trim '\n' from end of name */
(*nelem)++; /* increment name count */
}
}
int main (void) {
char line[MAX]; /* buffer to hold line of input */
struct Number data[MAX] = {{""}}; /* initialize all name to empty-string */
size_t nelem = 0; /* number of filled struct */
int option;
while (1) { /* loop continually */
/* make your menu readable */
fputs ("\nPress 'Enter' on a blank line when done\n\n"
" 1) Read data\n"
" 2) Show Data\n\n"
"Choice: ", stdout);
/* read entire line of input into line, break on EOF or blank line */
if (fgets (line, MAX, stdin) == NULL || *line == '\n')
break;
/* parse integer from line */
if (sscanf (line, "%d", &option) != 1) {
fputs (" error: invalid integer input.\n", stderr);
continue;
}
/* use a switch to control */
switch (option) {
case 1: read (data, &nelem); break;
case 2: show (data, nelem); break;
default: fputs ("error: invalid choice.\n", stderr); break;
}
}
}
使用/输出示例
现在您可以使用菜单一次添加任意数量的名称、show() 名称、添加更多名称等。最多可达到 MAX 条目数:
$ ./bin/structnumber
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice: 2
(list-empty)
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice: 1
enter name: Mickey Mouse
enter name: Minnie Mouse
enter name:
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice: 2
Name: Mickey Mouse
Name: Minnie Mouse
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice: 1
enter name: Donald Duck
enter name: Pluto (the dog)
enter name:
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice: 2
Name: Mickey Mouse
Name: Minnie Mouse
Name: Donald Duck
Name: Pluto (the dog)
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice:
现在可以正确处理无效输入:
$ ./bin/structnumber
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice: banannas
error: invalid integer input.
Press 'Enter' on a blank line when done
1) Read data
2) Show Data
Choice:
(注意:您可以将"Press 'Enter' on a blank line when done" 移出循环,因此它只显示一次——故意重复它以提醒用户如何结束数据或菜单条目)
查看一下,如果您还有其他问题,请告诉我。