c-Struct Array打印了最后一个元素



我想打印输入中所有输入的元素。但是,打印的代码是最近输入的代码。我期望该程序打印输入到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"移出循环,因此它只显示一次——它是有意重复的,以提醒用户如何结束数据或菜单项(

仔细看看,如果你还有问题,请告诉我。

最新更新