我想打印输入中所有输入的元素。但是,打印的代码是最近输入的代码。我期望该程序打印输入到Struct数组中的每一个输入。我试着切换到gets和fgets,输出仍然显示出相同的结果。因此,我不知道如何让程序打印所有来自用户的给定输入。
以下是我的代码:
#include <stdio.h>
#include <stdlib.h>
#define MAX 1
struct Number
{
char name[100];
};
void read(struct Number *data);
void show(struct Number *data);
int main()
{
int i, j;
struct Number data[MAX];
int option;
printf("Choose 1 to Read data or Choose 2 to Show Data");
do
{ printf(" nChoose ");
scanf("%d", &option);
if(option==1)
{
read(data);
}
else if(option==2)
{
show(data);
}
else
{
printf("Error! n");
}
}
while(1);
}
void show(struct Number *data)
{
int i;
for (i=0; i<MAX; i++)
{
printf("%s n", data[i].name);
}
}
void read(struct Number *data)
{
int j;
for (j=0; j<MAX; j++)
{
printf("Name: ");
scanf("%s", data[j].name);
}
}
以下是我的输出:
Choose 1 to Read data or Choose 2 to Show Data
Choose 1
Name: ted
Choose 1
Name: alex
Choose 2
alex
谢谢大家!非常感谢
问题的简单答案是您已经定义了#define MAX 1
,因此结构体struct Number data[MAX];
的数组中只有1个元素,这意味着您只能读取一个名称。
除此之外,你还有许多领域遇到了麻烦。进行用户输入时,除非检查输入函数的返回以确定输入是成功还是失败,否则无法正确进行输入。使用scanf("%s", ...
读取名称时会遇到问题,因为"%s"
格式说明符会停止读取遇到的第一个空白。这意味着您将永远无法将"Siam C."
作为名称读取。
建议您使用fgets()
,以便每次使用一整行输入,而不是使用scanf()
进行用户输入。这样,stdin
中剩余的未读内容不取决于scanf()
格式说明符以及是否发生匹配失败。使用fgets()
读取整行,然后可以使用sscanf()
从该行提取任何所需的数值。然后,在匹配失败的情况下,stdin
中不会留下任何内容来中断您的下一次尝试读取。
显示菜单时,请使其在代码中可读。除非您正在转换一个数字以进行输出,否则不需要printf()
,而只需要简单的puts()
(如果需要线路末端控制,则为fputs()
(,例如
while (1) { /* loop continually */
/* make your menu readable */
fputs ("nPress 'Enter' on a blank line when donenn"
" 1) Read datan"
" 2) Show Datann"
"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()
函数,这样您就知道要显示多少个structs(也可以检查它是否为零并显示"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: %sn", 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: %sn", 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 donenn"
" 1) Read datan"
" 2) Show Datann"
"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"
移出循环,因此它只显示一次——它是有意重复的,以提醒用户如何结束数据或菜单项(
仔细看看,如果你还有问题,请告诉我。