免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4207 | 回复: 14

利用清除缓冲区解决死循环,问题已解决。 [复制链接]

论坛徽章:
0
发表于 2012-03-02 15:27 |显示全部楼层
本帖最后由 tankMowei101 于 2012-03-09 20:39 编辑

#include <stdio.h>
int main()
{
  int x;
  int ch;/* */
  printf("lease enter an integer num then the program will judge between odd numbers and even numbers\n";
  printf("You can enter -1 to end the input\n";

  scanf("%d",&x);
  
  if(x==0)
    printf("The 0 isn't even number and odd number\n";

  if(x<0)
    printf("You should input a positive number\n";

  while( (ch=getchar())!= '\n' && ch != EOF );
  
  if(x>0) {
    while(x!=(-1)&&x>0)
      {
        if(x%2==0)
          printf("The num %d that you enter is an even number\n",x);
        else
          printf("The num %d that you enter is an odd number\n",x);

        printf("Go on(entering -1 to end the input)\n";
        scanf("%d",&x);/*继续输入*/
        while( (ch = getchar()) != '\n' && ch != EOF );
      }
  }
  return 0;
}


------------------------------------2012.3.9


利用清除缓冲区解决死循环,问题已解决。














这个小程序是DEITEL的C程序大学教程上的一个程序设计题目,我编了这个小程序,很简单,输入一个整数,程序判断是偶数还是奇数,用while循环语句反复判断,如果输入的是1或0就推出循环。

  这个程序如果输入浮点数,例如3.1,那么会发生循环语句自动执行的情况,只能强行关闭终端,我一开始猜问题是出在赋值语句上可能发生某种错误,我用GDB调试过了,在while语句里此处自动进入输入语句,继续开始while循环,而输入整型变量2,3,4,5......n则不会发生这个情况,只会正常执行scanf语句,等待手动输入。求深入解释,是否是跟栈错误有关?

我想请坛子上的专家们深入解释下这个问题。


   错误发生在第23个断点处。




   下面的表情符号不是我故意打的,呵呵,抱歉。



[tankwei@tankwei Ce5test]$ gcc -Werror -g test2_24.c -o test2_24
[tankwei@tankwei Ce5test]$ gdb
GNU gdb (GDB) Fedora (7.2-16.fc14)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file test2_24
Reading symbols from /home/tankwei/Ce5test/test2_24...done.
(gdb) list
1        #include <stdio.h>
2        int main()
3        {
4          int x=0;
5          printf("lease enter an integer num then the program will judge between odd numbers and even numbers\n";
6          printf("You can enter 1 to end the input\n";
7          
8          scanf("%d",&x);
9       
10          if(x==0)
(gdb)
11            printf("Error,the 0 isn't even number and odd number\n";
12         
13          if(x<0)
14            printf("Error,you should input a positive number\n";
15          
16          if(x>0) {
17            while(x!=1&&x>0)
18              {
19                if(x%2==0)
20                  printf("The num %d that you enter is an even number\n",x);
(gdb)
21                else
22                  printf("The num %d that you enter is an odd number\n",x);
23                scanf("%d",&x);/*继续输入*/
24              }
25          }
26          return 0;
27        }
(gdb) break 8
Breakpoint 1 at 0x804846d: file test2_24.c, line 8.
(gdb) break 10
Breakpoint 2 at 0x8048482: file test2_24.c, line 10.
(gdb) break 16
Breakpoint 3 at 0x80484aa: file test2_24.c, line 16.
(gdb) break 17
Breakpoint 4 at 0x80484b2: file test2_24.c, line 17.
(gdb) break 19
Breakpoint 5 at 0x80484b4: file test2_24.c, line 19.
(gdb) break 23
Breakpoint 6 at 0x80484eb: file test2_24.c, line 23.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804846d in main at test2_24.c:8
2       breakpoint     keep y   0x08048482 in main at test2_24.c:10
3       breakpoint     keep y   0x080484aa in main at test2_24.c:16
4       breakpoint     keep y   0x080484b2 in main at test2_24.c:17
5       breakpoint     keep y   0x080484b4 in main at test2_24.c:19
6       breakpoint     keep y   0x080484eb in main at test2_24.c:23
(gdb) run
Starting program: /home/tankwei/Ce5test/test2_24
Please enter an integer num then the program will judge between odd numbers and even numbers
You can enter 1 to end the input

Breakpoint 1, main () at test2_24.c:8
8          scanf("%d",&x);
Missing separate debuginfos, use: debuginfo-install glibc-2.13-2.i686
(gdb) frame
#0  main () at test2_24.c:8
8          scanf("%d",&x);
(gdb) bt
#0  main () at test2_24.c:8
(gdb) info frame
Stack level 0, frame at 0xbffff370:
eip = 0x804846d in main (test2_24.c:; saved eip 0xbaee36
source language c.
Arglist at 0xbffff368, args:
Locals at 0xbffff368, Previous frame's sp is 0xbffff370
Saved registers:
  ebp at 0xbffff368, eip at 0xbffff36c
(gdb) n
3.1

Breakpoint 2, main () at test2_24.c:10
10          if(x==0)
(gdb) print x
$1 = 3
(gdb) frame
#0  main () at test2_24.c:10
10          if(x==0)
(gdb) info frame
Stack level 0, frame at 0xbffff370:
eip = 0x8048482 in main (test2_24.c:10); saved eip 0xbaee36
source language c.
Arglist at 0xbffff368, args:
Locals at 0xbffff368, Previous frame's sp is 0xbffff370
Saved registers:
  ebp at 0xbffff368, eip at 0xbffff36c
(gdb) n
13          if(x<0)
(gdb) n

Breakpoint 3, main () at test2_24.c:16
16          if(x>0) {
(gdb) print x
$2 = 3
(gdb) frame
#0  main () at test2_24.c:16
16          if(x>0) {
(gdb) info locals
x = 3
(gdb) info args
No arguments.
(gdb) dsassemble if
Undefined command: "dsassemble".  Try "help".
(gdb) disassemble if
A syntax error in expression, near `if'.
(gdb) dissassemble if()
Undefined command: "dissassemble".  Try "help".
(gdb) disassemble if()
A syntax error in expression, near `if()'.
(gdb) disassemble if
A syntax error in expression, near `if'.
(gdb) disassemble main
Dump of assembler code for function main:
   0x08048444 <+0>:        push   %ebp
   0x08048445 <+1>:        mov    %esp,%ebp
   0x08048447 <+3>:        and    $0xfffffff0,%esp
   0x0804844a <+6>:        sub    $0x20,%esp
   0x0804844d <+9>:        movl   $0x0,0x1c(%esp)
   0x08048455 <+17>:        movl   $0x80485e4,(%esp)
   0x0804845c <+24>:        call   0x8048374 <puts@plt>
   0x08048461 <+29>:        movl   $0x8048644,(%esp)
   0x08048468 <+36>:        call   0x8048374 <puts@plt>
   0x0804846d <+41>:        mov    $0x8048665,%eax
   0x08048472 <+46>:        lea    0x1c(%esp),%edx
   0x08048476 <+50>:        mov    %edx,0x4(%esp)
   0x0804847a <+54>:        mov    %eax,(%esp)
   0x0804847d <+57>:        call   0x8048364 <__isoc99_scanf@plt>
   0x08048482 <+62>:        mov    0x1c(%esp),%eax
   0x08048486 <+66>:        test   %eax,%eax
   0x08048488 <+68>:        jne    0x8048496 <main+82>
   0x0804848a <+70>:        movl   $0x8048668,(%esp)
   0x08048491 <+77>:        call   0x8048374 <puts@plt>
   0x08048496 <+82>:        mov    0x1c(%esp),%eax
   0x0804849a <+86>:        test   %eax,%eax
---Type <return> to continue, or q <return> to quit---q<return>
Quit
(gdb) n

Breakpoint 4, main () at test2_24.c:17
17            while(x!=1&&x>0)
(gdb) print x
$3 = 3
(gdb) disassemble main
Dump of assembler code for function main:
   0x08048444 <+0>:        push   %ebp
   0x08048445 <+1>:        mov    %esp,%ebp
   0x08048447 <+3>:        and    $0xfffffff0,%esp
   0x0804844a <+6>:        sub    $0x20,%esp
   0x0804844d <+9>:        movl   $0x0,0x1c(%esp)
   0x08048455 <+17>:        movl   $0x80485e4,(%esp)
   0x0804845c <+24>:        call   0x8048374 <puts@plt>
   0x08048461 <+29>:        movl   $0x8048644,(%esp)
   0x08048468 <+36>:        call   0x8048374 <puts@plt>
   0x0804846d <+41>:        mov    $0x8048665,%eax
   0x08048472 <+46>:        lea    0x1c(%esp),%edx
   0x08048476 <+50>:        mov    %edx,0x4(%esp)
   0x0804847a <+54>:        mov    %eax,(%esp)
   0x0804847d <+57>:        call   0x8048364 <__isoc99_scanf@plt>
   0x08048482 <+62>:        mov    0x1c(%esp),%eax
   0x08048486 <+66>:        test   %eax,%eax
   0x08048488 <+68>:        jne    0x8048496 <main+82>
   0x0804848a <+70>:        movl   $0x8048668,(%esp)
   0x08048491 <+77>:        call   0x8048374 <puts@plt>
   0x08048496 <+82>:        mov    0x1c(%esp),%eax
   0x0804849a <+86>:        test   %eax,%eax
---Type <return> to continue, or q <return> to quit---q<return>
Quit
(gdb) n

Breakpoint 5, main () at test2_24.c:19
19                if(x%2==0)
(gdb) print
$4 = 3
(gdb) n
22                  printf("The num %d that you enter is an odd number\n",x);
(gdb) n
The num 3 that you enter is an odd number

Breakpoint 6, main () at test2_24.c:23
23                scanf("%d",&x);/*继续输入*/
(gdb) print
$5 = 3
(gdb) frame
#0  main () at test2_24.c:23
23                scanf("%d",&x);/*继续输入*/
(gdb) info f
Stack level 0, frame at 0xbffff370:
eip = 0x80484eb in main (test2_24.c:23); saved eip 0xbaee36
source language c.
Arglist at 0xbffff368, args:
Locals at 0xbffff368, Previous frame's sp is 0xbffff370
Saved registers:
  ebp at 0xbffff368, eip at 0xbffff36c
(gdb) info args
No arguments.
(gdb) info locals
x = 3
(gdb) n
17            while(x!=1&&x>0)
(gdb) n

Breakpoint 5, main () at test2_24.c:19
19                if(x%2==0)
(gdb) n
22                  printf("The num %d that you enter is an odd number\n",x);
(gdb) info locals
x = 3
(gdb) n
The num 3 that you enter is an odd number

Breakpoint 6, main () at test2_24.c:23
23                scanf("%d",&x);/*继续输入*/
(gdb) n                                                          /*此处自动进入输入语句,开始while循环*/
17            while(x!=1&&x>0)
(gdb) q
A debugging session is active.

        Inferior 1 [process 4492] will be killed.

Quit anyway? (y or n) y
[tankwei@tankwei Ce5test]$

论坛徽章:
0
发表于 2012-03-03 16:23 |显示全部楼层
哎,自己顶一下。

  我就想问问这个没按程序预先设计运行的原因。

论坛徽章:
0
发表于 2012-03-03 16:58 |显示全部楼层
17            while(x!=1&&x>0)
18              {
19                if(x%2==0)
20                  printf("The num %d that you enter is an even number\n",x);
21                else
22                  printf("The num %d that you enter is an odd number\n",x);
23                scanf("%d",&x);/*继续输入*/
24              }


以输入3.1为例
23行第一次会扫描输入流(流中为字符串"3.1")得到3,输入流里面还有".1",判断奇数
23行第二次会扫描".1" 与%d 格式不符合,不对x赋值,x保留上一次的值3,循环继续执行
判断为奇数,
。。。
如此重复。

要想3.1之类的错误输出不造成死循环,在scanf直线对x赋值0




论坛徽章:
0
发表于 2012-03-03 18:06 |显示全部楼层
回复 3# sanbiangongzi


    可是第一次输入3.1的时候,在输入语句中,浮点数3.1赋值给整形变量x,我查看了当前的局部变量,确实是3,舍去了0.1对吧,在while循环语句里面,还能检测到3.1?

论坛徽章:
0
发表于 2012-03-04 22:08 |显示全部楼层
学习了~~
回复 3# sanbiangongzi


   

论坛徽章:
0
发表于 2012-03-05 08:06 |显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
发表于 2012-03-05 08:08 |显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
发表于 2012-03-05 23:30 |显示全部楼层
回复 6# cj_gameboy


    对不起,这个输入的问题我弄错了,抱歉啊。

论坛徽章:
0
发表于 2012-03-05 23:31 |显示全部楼层
回复 3# sanbiangongzi


    对不起,这个输入的问题我弄错了,抱歉啊。{:3_194:}

论坛徽章:
0
发表于 2012-03-06 11:38 |显示全部楼层
  1. if (!scanf("%d",&x)) {
  2.      fputs("出错了\n", stderr);
  3.      exit(1);
  4. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP