QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 740|回复: 3

由一个小程序引发的几个gcc编程和调试问题

[复制链接]
发表于 2004-7-21 20:39:43 | 显示全部楼层 |阅读模式
前次发贴,以下程序编译不能通过,后经lanche指点,才知是犯了两个低级错误 ,改后就能顺利编译了。但是程序本身还有bug.现发帖以供大家讨论学习(比较长,请耐心看下去)。源程序如下:
////////////////////////////////////////////////
//compute.c:简单计算器
////////////////////////////////////////////////
#include<stdio.h>
//#include<string.h>
//#include<stdlib.h>
  
double sum(double a,double b);
double subtract(double a,double b);
double multiply(double a,double b);
double divide(double a,double b);
double remainder(double a,double b);
  
int main(void)
{
   int choice;
   double a,b;
   double (*func)();
   while(1)
  {
   printf("\n*****************************************");//输入提示询息
   printf("\n1.sum");
   printf("\n2.subtract");
   printf("\n3.multiply");
   printf("\n4.divide");
   printf("\n5.remainder");
   printf("\nInput a choice(any other key to exit):");
   
//fflush(stdin);
   choice=getc(stdin)-'0';
//choice=getchar()-'0';
//choice=getche();
   
   switch(choice)
  {
     case 1:
         func=sum;
         break;
     case 2:
         func=subtract;
         break;
     case 3:
         func=multiply;
         break;
     case 4:
         func=divide;
         break;
     case 5:
         func=remainder;
     default:
         return;
  }
  printf("\n\nPlease input a:");
  scanf("%lf",&a);
  printf("Pleast input b:");
  scanf("%lf",&b);
  printf("\nThe result is:%lf.\n",(*func)(a,b));
//fflush(stdin);
//choice=0;
}
  
return 0;
  
}
  
double sum(double a,double b)
{
   return a+b;
}
  
double subtract(double a,double b)
{
   return a-b;
}
  
double multiply(double a,double b)
{
   return a*b;
}
  
double divide(double a,double b)
{
   return a/b;
}
  
double remainder(double a,double b)
{
  return (int)a%(int)b;
}

该程序运行后,第一次运算很正常。但是第一次运算结束后,就直接退出了程序,根本没有进行第二次运算选择的机会 。运行如下:
[chenye@chenye chenye]$ ./compute2(注:compute2是可执行文件名)
  
*****************************************
1.sum
2.subtract
3.multiply
4.divide
5.remainder
Input a choice(any other key to exit):1(注意这里:能进行第一次运算选择)
  
  
Please input a:2
Pleast input b:3
  
The result is:5.000000.
  
*****************************************
1.sum
2.subtract
3.multiply
4.divide
5.remainder
Input a choice(any other key to exit):[chenye@chenye chenye]$(看:自动退出程序了)

我的分析如下:
1.getc(stdin)或getchar() (两者作用一样)都是从输入缓冲队列中取下一个字符。而当延第一次进行运算方式选择后,随后输入回车。然后又输入2(a的值),3(b的值),所以在第二次进行输入运算选择时,输入缓冲队列其实并不为空,所以getc(stdin)或getchar()自动从输入缓冲队列中取数值,而不必等待用户的输入。这样,choice的值自然不是1至5了,所以程序自动退出。
2.根据以上分析,我在choice=getc(stdin)-'0';语句前加了一句fflush(stdin); ,目的是清空输入缓冲队列,使getc(stdin)必须等待用户输入,可是结果和没加fflush(stdin)一样。
   这个问题我一直没想通,为什么fflush(stdin)没有把输入缓冲区清空呢?
3.我在第一次运算方式选择时输入12,这时发现运算方式为1(即加法运算),可是a的值已自动被赋为2.这是不是说明:scanf和getc(或getchar)一样,其实都是从输入缓冲队列中取值,如果输入缓冲队列不为空,有数值,则scanf不会等待用户输入,而是直接从输入缓冲队列中取值。运行结果如下:
[chenye@chenye chenye]$ ./compute2
  
*****************************************
1.sum
2.subtract
3.multiply
4.divide
5.remainder
Input a choice(any other key to exit):12(注意:我在这步输入12)
  
  
Please input aleast input b:3(这里a不是用户输入)
  
The result is:5.000000.(可见a的值为2,运算方式为1即加法)
  
*****************************************
1.sum
2.subtract
3.multiply
4.divide
5.remainder
Input a choice(any other key to exit):[chenye@chenye chenye]$


4.我用gdb调试,在 choice=getc(stdin)-'0';句设置了一个断点,并观察choice的值,发现在进行第二次运算方式选择时,choice的值总是为-38(这也难怪会自动退出程序了)。我觉得应该为-35,因为我在输入数字后总是输入回车,而回车的ascii值为13,所以choice=13-'0'=-35.为什么是-38呢?

5.在用gdb进行单步调试时,我发现了一个怪现象。在调至printf("\n\nPlease input a:");  scanf("%lf",&a);  printf("Pleast input b:");  scanf("%lf",&b);时,执行printf语句后并不立即输出Please input a:,而是在执行完scanf("%lf",&a);语句后才输出Please input a:。这是为什么?
运行情况如下:
53        printf("\n\nPlease input a:");
(gdb)
     //为什么不是在这里输出Please input a:呢?
  
54        scanf("%lf",&a);
(gdb)
Please input a

顺便问一下,各位在linux编程及调试大都用什么工具?
发表于 2004-7-22 13:42:43 | 显示全部楼层
顺便问一下,各位在linux编程及调试大都用什么工具?

我:gcc vi make gdb
回复

使用道具 举报

发表于 2004-7-22 14:20:27 | 显示全部楼层
2.根据以上分析,我在choice=getc(stdin)-'0';语句前加了一句fflush(stdin); ,目的是清空输入缓冲队列,使getc(stdin)必须等待用户输入,可是结果和没加fflush(stdin)一样。
这个问题我一直没想通,为什么fflush(stdin)没有把输入缓冲区清空呢?

会不会是缓冲区为空的话他就返回 NULL 或 0x00 ??
回复

使用道具 举报

 楼主| 发表于 2004-7-22 22:24:40 | 显示全部楼层
会不会是缓冲区为空的话他就返回 NULL 或 0x00 ??
[/quote]
应该不会吧,因为进行第一次运算方式选择时输入缓冲队列也为空呀,可这时程序提示用户输入选择
回复

使用道具 举报

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

本版积分规则

GMT+8, 2024-11-7 21:08 , Processed in 0.064790 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表