0

我为链表编写了代码:

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

struct student{
       char name[256];
       int id;  
       struct student *next;
};
  struct student *start;
  struct student *last;     

void enter(void);
void add( struct student *i,struct student **last);
void display(struct student *first);       

int main(int argc, char *argv[])
{
  start=last=NULL;

   enter();
   enter();
   enter();
   display(start);

  system("PAUSE");  
  return 0;
}

void add( struct student *i,struct student **last)
{
     if (!*last){ *last=i; start=i;}
     else {(*last)->next=i;*last=i;}
     i->next=NULL;

     }
void enter(void)
{
   struct student *info;

   info=(struct student *)malloc(sizeof(struct student));



    printf("Enter the name of the student:\n");
    fgets(info->name,255,stdin);
    fflush(stdin);
    // gets(info->name);
     printf("Enter the student id:\n");
     scanf("%d%",&info->id); 
     add(info,&last);

 }

 void display(struct student *first)
 {
      while(first)
      {
                  printf("\n\n\n\nName: %s\n",first->name);
                  printf("Id: %d\n", first->id);
                  first=first->next;
                  }
  }

它确实创建了一个链接列表,但是当我尝试输入值时:它显示

输出

对于第一个元素,它为 id 正确使用名称,我需要在 id 数字之后手动输入 \n(否则它不会退出 scanf 模式),并且从第二个元素开始,它不会提示输入名称,它会跳过“Enter name”并询问 id 我需要在哪里再次手动输入 \n。在显示链表元素时,它确实显示名字,但从第二个名字开始显示\n。我已经使用了 fflush(stdin)。您能否让我知道为什么会出现这种行为?我附上了o / p图片。

谢谢

4

1 回答 1

2

如果我有一个镍...

无论如何,这里有很多问题:

1)不要fflush(stdin),那是未定义的行为

scanf2) 混合s 和s从来都不是一个好主意fgets,它只会让事情变得混乱。

scanf(" %s", info->name); // will do instead of your fgets statement

%3)你的scanf中有一个额外的:

scanf("%d%",&info->id);  // should be scanf("%d",&info->id);

为了完整...

为什么你现在遇到问题:

fgets()接受一个字符串并包含换行符,因此当您询问名称时,您会得到 "name\n"

scanf()接受号码并离开换行符。因此,当您要求提供 ID 时,您会输入数字,但换行符'\n'仍在stdin.

下次您fgets()运行时,它会自动将其作为第二个名称的输入。似乎“跳过”输入请求。


编辑
如果您使用的原因fgets()是读取其中包含空格的字符串(如"first_name last_name"),也可以scanf()使用 Negated scanset 选项来完成:

scanf(" %[^\n]",info->name); 
于 2012-12-12T18:56:09.140 回答