user-0 提问: 求各位大神帮我修改一下本图书管理系统的BUG，本人万分感谢

回复:
user: user-0
content: 感谢各位帮助了。我改一下试试看。意见好多啊，不过我也受教了。蟹蟹！

user: user-1
content: printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0];  “多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，掰手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

user: user-2
content: //#include"stdafx.h" #include<stdio.h> #include<stdlib.h> #include<string.h>  typedef struct node {     int num;//书号     char title[50];//书名     char author[50];//著作者     int num1;//现存量     int num2;//库存量     char name[50];//借阅者姓名     int idnum;//学生证号     struct node *link; }linklist;  linklist* creatnull(linklist *l)//申请单链表的空间 {     l = (linklist*)malloc(sizeof(linklist));//申请空间     l->link = NULL;//尾结点置空     return l; } void creat(linklist **l)//采编入库 {     int i,n;     linklist *p,*tail,*q;     tail = *l;     if((*l)->link!=NULL)//判断：下一结点不为空         q= (*l)->link;//q指针指向下一个结点     else q = *l;//输入数据读入     while(tail->link!=NULL)     {         tail=tail->link;     };     printf("\n请输入入库图书的数量:");     scanf("%d",&n);     for(i=1;i<=n;i++)     {         p=(linklist*)malloc(sizeof(linklist));         printf("\n请输入入库图书的书号:");         scanf("%d",&p->num);         while(q->num!=p->num&&q->link!=NULL)//输入的书名重复         {             q=q->link;         }         if(q->num==p->num)         {             q->num1=q->num1+1;             q->num2=q->num2+1;             printf("\n该图书已在图书库存在，已自动增加图书数量");}         else         {             printf("\n请输入入库图书的书名:");             scanf("%s", p->title);//传入数据至单链表数据域             printf("\n请输入入库图书的著作者:");             scanf("%s", p->author);             printf("\n请输入入库图书的现存量:");             scanf("%d",&p->num1);             printf("\n请输入入库图书的库存量:");             scanf("%d",&p->num2);             strcpy(p->name,"NULL");             tail->link=p;             tail=p;             tail->link=NULL;//尾结点置空          };     }  } void print(linklist *l)//输出所有图书的信息 {     linklist *p;     p=l->link;     printf("\n输出所有图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");     while(p)//单链表没读完     {         printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         p=p->link;     } }  void locat(linklist *l,int i)//根据书号查找图书    i是输入的书号 {     int count=0;     linklist *p;     p=l->link;     while(p->link!=NULL)     {         if(p->num!=i)         {             p=p->link;//下移一个结点         }         else         {             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");             printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);             p=p->link;             count++;   //同书号的有多少个         }     };     if(p->num==i)     {         printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");         printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         count++;     }     if(count==0)         printf("该图书不在此书库！"); }  void locat1(linklist *l,int j)//根据学号查询 {     int count=0;     linklist *p;     p=l->link;     while(p->link!=NULL)     {         if(p->idnum!=j)         {             p=p->link;         }         else         {             printf("\n输出学生的信息:\n学号\t借阅者姓名\t书号\t书名\t著作者");             printf("\n%d\t%s\t\t%d\t%s\t%s\n",p->idnum,p->name,p->num,p->title,p->author);             p=p->link;             count++;         }     };     if(p->idnum==j)     {         printf("\n输出学生的信息:\n学号\t借阅者姓名\t书号\t书名\t著作者");         printf("\n%d\t%s\t\t%d\t%s\t%s\n",p->idnum,p->name,p->num,p->title,p->author);         p=p->link;         count++;     }     if(count==0)         printf("该学生未借阅！"); }  void borrowbook(linklist *l)//借阅 {     linklist *p;     int i;     int count=0;     printf("\n借阅的图书书号:");     scanf("%d", &i);     p = l->link;      printf("bookno = %d\n", i);     while(p != NULL)     {         if(p->num != i)         {             p=p->link;         }         else         {             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");             printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);             //p = p->link;             break;             count++;         }     }     if(p != NULL && p->num == i)     {         printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");         printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         count++;     }     if(count == 0)     {         printf("该图书不在此书库！");     }     else     {         if(p->num1<=0)         {             printf("\n该书库存不足,读者无法借阅.");         }         else         {             p->num1=p->num1-1;             printf("\n请输入借阅者的姓名:");             scanf("%s", p->name);             printf("\n请输入借阅者的学生证号:");             scanf("%d",&p->idnum);             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量\t借阅者姓名\t学生证号");             printf("\n%d\t%s\t%s\t%d\t%d\t%s\t\t%d\n",p->num,p->title,p->author,p->num1,p->num2,p->name,p->idnum);         }     } }  void returnbook(linklist *l)//归还 {     linklist *p;int i,a;     int count=0;     int counta=0;     printf("\n请输入归还图书的书号:");     scanf("%d",&i);     p = l->link;      while(p != NULL)     {         if(p->num!=i){p=p->link;}         else         {             break;         }     };     if(p->num==i){         count++;     }     if(count==0)     {         printf("该图书不在此书库！");     }     else     {         printf("\n请输入学生证号:");         scanf("%d",&a);         p = l->link;         while(p)         {             if(p->idnum!=a){                 p=p->link;             }             else             {                 break;             }         }         if(p && p->idnum==a) {             counta++;         }         if(counta==0)         {             printf("该学生未借阅图书！");         }         else         {             p->num1=p->num1+1;             strcpy(p->name,"NULL");             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");             printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         }     } } int main() {     linklist l,*head;//初始化单链表头结点     head=creatnull(&l);     printf("                 *********************************\n");     printf("                       欢迎使用图书管理系统       \n");     printf("                 *********************************\n");     printf("\n");     int flag=1,a;     while(flag)     {         printf("               *************************************\n");         printf("                          1:馆藏图书信息            \n");         printf("                          2:采编入库                \n");         printf("                          3:图书查询                \n");         printf("                          4:学号查询                \n");         printf("                          5:读者借阅                \n");         printf("                          6:读者归还                \n");         printf("                          7:退出图书管理系统        \n");         printf("               *************************************\n");         printf("                            请输入您的选项：");         scanf("%d",&a);         switch(a)         {              case 7:flag=0;                    printf("                 *********************************\n");                    printf("                       成功退出图书管理系统       \n");                    printf("                 *********************************\n");                    break;             case 1:flag=1;                    print(head);                    printf("\n\n\n");                    break;             case 2:flag=1;                    creat(&head);                    printf("\n\n\n");                    break;             case 3:flag=1;                    int number;//书号                    printf("\n请输入要查找的图书书号:");                    scanf("%d",&number);                    locat(head,number);                    printf("\n\n\n");                    break;             case 4:flag=1;                    int idnumber;//学号                    printf("\n请输入要查找的学号:");                    scanf("%d",&idnumber);                    locat1(head,idnumber);                    printf("\n\n\n");                    break;             case 5:                    flag=1;                      borrowbook(head);                    printf("\n\n\n");                    break;             case 6:flag=1;                    returnbook(head);                    printf("\n\n\n");                    break;         }     }     system("pause");     return 1; } 除了scanf处输入有若干错误；主要是scanf以%s输入时，不需要加前面的&，因为数组名本身就是地址。 借书和还书还有问题，逻辑上还存在问题。链表遍历时，不能遍历到最后一个节点，所以改成while (p)形式判断。另外，若找到节点，不应该再执行p = p->link，而是直接跳出循环。 以上改动，详见代码！

user: user-3
content: 示例(部分代码) 	printf("    21点\n"); 	printf("1.开始游戏\n"); 	printf("2.操作设置\n"); 	printf("3.难度设置\n"); 	printf("4.查看排名\n"); 	printf("5.操作帮助\n"); 	printf("6.退出游戏\n");  	printf("\n选择菜单: "); 	scanf("%d",&menu);  	while( menu<=0 || menu>=7) 	{ 		if(menu<-10000) 		{ 			getchar(); 			printf("\n好端端的,干嘛输入字母!\n"); 			printf("请重新选择菜单: "); 			scanf("%d",&menu); 		}else 		{ 			printf("\n菜单选择错误!\n请重新选择菜单: "); 			scanf("%d",&menu); 		} 	}  这里解释下,我在这里判断menu的值看是否输入了字母.因为定义menu时,没给值,它会随机地被赋予一个很大的负数. 通过判断不是很大的负数默认来确定有没有成功地获取用户输入的数据. 但这方法不够""判断sanf返回值来确定有没有成功地获取用户输入的数据"好

user: user-3
content: 引用 4 楼 ghxujei 的回复:其实我也希望直接写一个函数，然后每次从键盘输入的时候都调用一下判定是否为数字，这样的话所有的地方就都不会出问题了。但是我确实是不会写。真的不知道从何入手。 可以这样实现,用%s读取用户输入的数据并存到数组str 然后遍历str,若存在0-9为外的字符,返回false

user: user-3
content: 解决方法:         出错时,加条语句来清空缓冲区       方法一:scanf("%s", s);        方法二: scanf(“%*[^\n]%*c”): 出错原因:       用scanf("d",&n);只会从缓冲区获取数字,就是说,输入了字母的话,他就获取不了缓冲区的字符!       如果是循环获取的话,就永远卡死,因为scanf("d",&n);永远获取不到应有的数字.       所以,你该把字母读走然后再scanf("d",&n);       所以,你也可以用读把n声明为char类型,这样的话就不会出现这样的问题(要读取数字,却有字符阻拦着)了!  其次,你还可以通过sanf的返回值去判断,是否读到了字符,没有的话就用清空缓冲区  关于缓冲区的问题,你也可以看看我博客中初学c常见问题,里面有提到过缓冲区的

user: user-0
content: 其实我也希望直接写一个函数，然后每次从键盘输入的时候都调用一下判定是否为数字，这样的话所有的地方就都不会出问题了。但是我确实是不会写。真的不知道从何入手。

user: user-0
content: 是这样。  while(tail->link!=NULL)     {         tail=tail->link;     };     printf("\n请输入入库图书的数量:");     scanf("%d",&n);  当我在提示之后输入字母，他会出错。我想在程序中加上一段代码，可以检测我输入的是否为数字，如果不是数字，就提示请正确输入数字，然后重新输入。如果是数字的话，才进行下一步。

user: user-4
content: printf("               *************************************\n"); 		printf("                          1:馆藏图书信息            \n"); 		printf("                          2:采编入库                \n"); 		printf("                          3:图书查询                \n"); 		printf("                          4:学号查询                \n"); 		printf("                          5:读者借阅                \n"); 		printf("                          6:读者归还                \n"); 		printf("                          7:退出图书管理系统        \n"); 		printf("               *************************************\n");  		printf("                            请输入您的选项：");                      		scanf("%d",&a); 这个要求程序属于一个数字，且要求是1-7，如果是其他数字或字符，程序就会进入死循环。

user: user-5
content: printf("\n请输入入库图书的现存量:");                 scanf("%d",&p->num1);                 printf("\n请输入入库图书的库存量:");                 scanf("%d",&p->num2);  你是说的这两个吗？输入非数字的时候你们的程序还能运行？ 如果是这里，把控制台输入当成字符串，读入字符串后判断字符串是不是全数字，不是全数字提示错误 信息，让用户重新输入，知道输入你们认为合法的值。 建议，应该用界面的方式进行录入。还有最后的书籍不应该保存在内存中。最好能用数据库保存。 以上建议仅供参考。