免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8196 | 回复: 6
打印 上一主题 下一主题

getchar()从键盘获取输入包含了换行符? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-18 09:17 |只看该作者 |倒序浏览
本帖最后由 lylesong 于 2012-01-18 09:27 编辑

这个是书上的一个例子,是一个逆波兰式计算器,
我把这个例子拿来运行后,最开始发现一旦入栈,马上就又出栈了,后面找了很久,发现每次都会输出换行符 '\n',就会运行switch 里面的 case '\n': 语句,而那里又调用了pop()函数,所以就会导致入栈马上又出栈了,
我注释掉这一段后,在'+'这种情况下运行程序,发现可以得到正确的加法结果,但是在输出中,还是有'\n'这种情况,因为没有了这种case,所以就跳转到default情况里面了,就会导致每次输入,都会有对应default输出,这个问题是怎么回事呢?
我检查了getop()函数,实在找不到问题在哪里,希望大家能帮我分析一下,谢谢
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<ctype.h>

  4. #define MAXOP 100
  5. #define NUMBER '0'
  6. #define MAXVAL 100
  7. #define BUFSIZE 100

  8. int getop(char []);
  9. void push(double);
  10. double pop(void);
  11. int getch(void);
  12. void ungetch(int);

  13. int sp = 0;
  14. double val[MAXVAL];
  15. int bufp = 0;
  16. char buf[BUFSIZE];

  17. int main()
  18. {
  19.         int type;
  20.         double op2;
  21.         char s[MAXOP];

  22.         while((type = getop(s)) != EOF)
  23.         {
  24.                 switch(type)
  25.                 {
  26.                         case NUMBER:
  27.                                 push(atof(s));
  28.                                 printf("now the sp result is:%d\n",sp);
  29.                                 break;
  30.                         case '+':
  31.                                 push(pop() + pop());
  32.                                 printf("now the sp result is:%d\n",sp);
  33.                                 printf("now the + result is:%f\n",pop());
  34.                                 break;
  35.                         case '*':
  36.                                 push(pop() * pop());
  37.                                 printf("now the sp result is:%d\n",sp);
  38.                                 break;
  39.                         case '-':
  40.                                 op2 = pop();
  41.                                 push(pop() - op2);
  42.                                 printf("now the sp result is:%d\n",sp);
  43.                                 break;
  44.                         case '/':
  45.                                 op2 = pop();
  46.                                 if(op2 != 0.0)
  47.                                         push(pop() / op2);
  48.                                 else
  49.                                         printf("error:zero divisor\n");
  50.                                 break;
  51.                         //case '\n':
  52.                         //        printf("\t%.8g\n",pop());
  53.                 //                printf("now the sp result is:%d\n",sp);
  54.                 //                break;
  55.                         default:
  56.                                 printf("error:unknown command %s\n",s);
  57.                                 break;
  58.                         }
  59.         }
  60.         return 0;
  61. }

  62. void push(double f)
  63. {
  64.         if(sp < MAXVAL)
  65.                 val[sp++] = f;
  66.         else
  67.                 printf("error:stack full,can't push %g\n",f);
  68. }

  69. double pop(void)
  70. {
  71.         if(sp > 0)
  72.                 return val[--sp];
  73.         else
  74.         {
  75.                 printf("error:stack empty\n");
  76.                 return 0.0;
  77.         }
  78. }

  79. int getop(char s[])
  80. {
  81.         int i, c;
  82.         while((s[0] = c = getch()) == ' ' || c == '\t')
  83.                 ;
  84.         s[1] = '\0';
  85.         if(!isdigit(c) && c != '.')
  86.                 return c;
  87.         i = 0;
  88.         if(isdigit(c))
  89.                 while(isdigit(s[++i] = c = getch()))
  90.                         ;
  91.         if(c == '.')
  92.                 while(isdigit(s[++i] = c = getch()))
  93.                         ;
  94.         s[i] = '\0';
  95.         if(c != EOF)
  96.                 ungetch(c);
  97.         return NUMBER;
  98. }

  99. int getch(void)
  100. {
  101.         return (bufp > 0) ? buf[--bufp] : getchar();
  102. }

  103. void ungetch(int c)
  104. {
  105.         if(bufp >= BUFSIZE)
  106.                 printf("ungetch:too many characters\n");
  107.         else
  108.                 buf[bufp++] = c;
  109. }
复制代码
用gdb调试了一下,发现这里的运行过程是这样的,所以我还是无法判断到底哪里出了问题,
  1. (gdb) b 31
  2. Breakpoint 1 at 0x804856d: file polish.c, line 31.
  3. (gdb) run
  4. Starting program: /home/song/cprogram/polish/polish
  5. 4

  6. Breakpoint 1, main () at polish.c:32
  7. 32                                        push(atof(s));
  8. (gdb) n
  9. 33                                        printf("now the sp result is:%d\n",sp);
  10. (gdb) n
  11. now the sp result is:1
  12. 34                                        break;
  13. (gdb) n
  14. 27                while((type = getop(s)) != EOF)
  15. (gdb) n
  16. 29                        switch(type)
  17. (gdb) n
  18. 61                                        printf("error:unknown command %s\n",s);
复制代码

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
2 [报告]
发表于 2012-01-18 11:32 |只看该作者
getch()吃回车么,好像不清楚......印象中getchar() 吃的....       最好用fgets || fgetc (stdin) 来替换

   while((s[0] = c = getch()) == ' ' || c == '\t')

这句有错吗?  你确定是 ||的关系?

论坛徽章:
0
3 [报告]
发表于 2012-01-18 11:50 |只看该作者
回复 2# hanzhenlll


    这个是 K&R书上的例子,我原样写下来的,虽然可以改写,我还是想知道这个问题是咋个回事,
按理说,原书上的代码的意思应该是,
输入数字,按回车,就把这个数字压入栈中,
输入运算符号,按回车,运算相对操作数,运算结果压入栈中,
单独按回车,那么,就运行 case '\n': 的情况,输出运算结果,
现在的结果是,每次输入,在压入栈中的时候,也会得到一个不知从哪里来的 换行符'\n',
使得 while((type = getop(s)) != EOF) 再次运行,这次type == '\n' 了。
  1. Reading symbols from /home/song/cprogram/polish/polish...done.
  2. (gdb) b 31
  3. Breakpoint 1 at 0x804856d: file polish.c, line 31.
  4. (gdb) run
  5. Starting program: /home/song/cprogram/polish/polish
  6. 4
  7. /* 第一次输入数字4,后面全部自动运行了,可以看到,在等待下一个操作数输入时,while循环自动运行了一次,这次的type == '\n' */
  8. Breakpoint 1, main () at polish.c:32
  9. 32                                        push(atof(s));
  10. (gdb) n
  11. 33                                        printf("now the sp result is:%d\n",sp);
  12. (gdb)
  13. now the sp result is:1
  14. 34                                        break;
  15. (gdb)
  16. 27                while((type = getop(s)) != EOF)
  17. (gdb)
  18. 29                        switch(type)
  19. (gdb)
  20. 61                                        printf("error:unknown command %s\n",s);
  21. (gdb)
  22. error:unknown command

  23. 27                while((type = getop(s)) != EOF)
  24. (gdb)
复制代码

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
4 [报告]
发表于 2012-01-18 11:54 |只看该作者
每次调用输入输入  也就是getchar()   用一下 fflush(stdin) 清空一下标准输入...避免回车被下一个getchar()吃掉

书上怎么了,不要迷信书都是对的

论坛徽章:
0
5 [报告]
发表于 2012-01-18 12:51 |只看该作者
hanzhenlll 发表于 2012-01-18 11:54
每次调用输入输入  也就是getchar()   用一下 fflush(stdin) 清空一下标准输入...避免回车被下一个getchar( ...


额,没有用过fflush(),看了下说明,int  fflush(FILE *stream);
这个应该加在哪里合适啊,我试着修改了getch()函数,还是有原来那个错误。

108 int getch(void)
109 {
110     char result;
111     result = (bufp > 0) ? buf[--bufp] : getchar();
112     fflush(stdin);
113     return result;
114 }


我觉得这么牛逼的一本书,c语言的圣经,如果有错,也许早就被指出来放在勘误里面了,可是勘误里面没有,
前面那么多人用这个书都没遇到这个问题,我遇到了,或许不是书的问题,是我的问题?

论坛徽章:
0
6 [报告]
发表于 2012-01-18 13:08 |只看该作者
回复 4# hanzhenlll


    额,找到原因了,是我自己输入格式上的问题,
按照那个要求来,如果要计算 4+3,那么就输入  4 3 + 回车。谢谢hanzhenlll ,让我学到了一个新函数。

论坛徽章:
0
7 [报告]
发表于 2012-01-21 02:02 |只看该作者
lylesong 发表于 2012-01-18 13:08
回复 4# hanzhenlll


学新函数。还是首先要好好看手册

man 3 fflush

CONFORMING TO
       C89, C99, POSIX.1-2001, POSIX.1-2008.

       The standards do not specify the  behavior  for  input  streams.   Most
       other implementations behave the same as Linux.

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP