求救高手C语言程序问题:帮我解释一下为什么?

一,
#include"stdio.h"
main()
{
short int a=32767,b=1,c;

c=a+b;
printf("a=%d,b=%d,c=%d\n",a,b,c);

}

/*观察溢出.疑问:产生这样的结果如何解释?原理是什么?*/

二,
#include"stdio.h"
main()
{
float a=123.1234,b=123.123456,c=123.123456;
printf("a=%5f,b=%5.3f,c=%.3f\n",a,b,c);

double x;int y;float z;
printf("在键盘上输入:4.6,23,123,2.34567:");
scanf("%f,%2d,%*d,%5f",&x,&y,&z);
printf("x=%lf,y=%d,z=%f\n",x,y,z);

}

/*
疑问:当把23改为2345时,y还是23,但是c的结果不是2.345000了,是一串乱七八糟的数,不知道为什么?
交大的一本教材中有这么说明:当scanf函数用%f输入一个实数型数据时,不能指定宽度.而本例为清华大学版教材中的一个范例,却指定了宽度%5f,
到底在scanf中适用%f数据格式时,能否指定宽度? 或者说用%f时可以指定宽度,但不能指定小数部分位数,如%10.3f是错误的.
*/

三,
#include"stdio.h"
main()
{
int a;
printf("input a:");
scanf("%d",&a);
printf("a=%d\n",a);

}

/* 当float型数据赋予int型时,小数部分将丢失,而不是四舍五入.疑问:当将程序改为以下时:变量b的结果很难理解?

#include"stdio.h"
main()
{
int a,b;
printf("input a and b:");
scanf("%d%d",&a,&b);
printf("a=%d,b=%d\n",a,b);

}

在键盘上输入如:1.23 2.34
运行结果:a=1,b=-858993460

b的结果为什么是那样?

*/

四,
#include"stdio.h"
main()
{
int a,b;
printf("input a and b:");
scanf("%3d%d",&a,&b);
printf("a=%d,b=%d\n",a,b);

}

/* 为什么当输入为:12345 23 时,运行结果却为a=123,b=45 ?当scanf函数改为("%3d,%d",&a,&b),输入为12345,23 时为什么结果又是a=123,
b=-858993460 ?

把程序改为:
#include"stdio.h"
main()
{
int a,b;
printf("input a and b:");
scanf("%d%4d",&a,&b);
printf("a=%d,b=%d\n",a,b);

}
当输入1.73,12345时,运行结果为什么是:a=1,b=-858993460 ?

疑问:输入函数scanf中的附加字符中的"域宽"和"*"怎么用? 书上的解释分别是:域宽:指定输入数据所占宽度(列数),域宽为正整数;
*表示本输入项在读入后不赋给相应的变量.

*/

五,
#include"stdio.h"
main()
{ int a=5,b=6;
printf("\t%d\n\t\b%d\n",a,b);

}

/*结果为什么是那样?,\t和\b怎么解释? */
六,
#include"stdio.h"
main()
{
float a=123.1236,b=1.23,c=12334.313414;
printf("a=%g,b=%e,b=%g,c=%g\n",a,b,b,c);

}

/*%g输出格式用于自动选取%f和%e中宽度较小的一种形式,且不输出无效0 ,这里的无效0指什么,包括无效无效数字吗?
疑问:为什么a=123.124,%g总是最多只输出7位(包括小数点) */

解答:
一、上面的哥们已经回答得很好了。重新抄写一遍。非常感谢

short int为两个字节,当第一一个变量为32767时,由于short int为有符号型,故最高位0,其余全为1,加1后变为16个1,成为一个负数,两整数相加得负数,溢出。

补充,现在的机器一般都是32位的,short类型为两个字节,int为四个字节。那些古老的机器中int是2个字节。但是很少有这样的机器了。

二、问:当把23改为2345时,y还是23,但是c的结果不是2.345000了,是一串乱七八糟的数,不知道为什么?
答:这里我把你的源程序中的输入输出语句分析一下
printf("a=%5f,b=%5.3f,c=%.3f\n",a,b,c):
这里%5f意思是输出占用5列。默认小数为6位。但是你的数据的位数大于5。所以按原样输出。
%5.3f。道理类似1。但是小数就只能有3位。
%.3f。这里只没说占多少列,但是告诉了你小数位只能有3位。所以在原样的基础上去3位小数输出。

double x;int y;float z;
printf("在键盘上输入:4.6,23,123,2.34567:");
scanf("%f,%2d,%*d,%5f",&x,&y,&z);
printf("x=%lf,y=%d,z=%f\n",x,y,z);
首先,scanf()中有个错误。double类型在输入的时候要%lf而输出的时候可以%lf也可以%f。
分析scanf()语句:
%f(应改成%lf):没啥好说的。
%2d:取输出的数据宽度为2。你输入23 那么正好够。
%*d:*用来忽略一个匹配项的输入。所以123。被忽略了。
%5f:这里表明接受宽度为5列。(注意了,书上是说不能在scanf()中指明精度,但是指明宽度是正确的。)z应该得到的是2.345。但是由于你用printf()输出的时候这个函数默认有六位小数,所以就输出了2.345000。如果是整数就不会存在这种情况。

现在回答你的疑问:
scanf()是按照格式化字符串里头的格式一个一个的和你的输入去匹配,y只取2345中的23。那么y当然是23。那么45仍然存在于stdin流中。注意了,你的scanf()中有逗号,那么这个逗号和谁去匹配呢,逗号显然是不能和45去匹配的。这里就出现了错误.这个逗号是不能跳过45去和你输入的2345后面的那个逗号去匹配的。所以整个scanf()就结束。那么剩下z没匹配成功,z这个变量存储空间里头以前是什么东西,就会显示什么东西。我的编译器显示的是0。
所以我建议你不要在scanf()写有和格式化字符,空白字符无关的东西。你本来可以用空白字符来间隔scanf()中的东西 也可以 间隔你在屏幕上的输入 以达到明了清晰的目的,为什么要添一些讨厌的东西在里头呢?

问题三:
这个问题同样是scanf() 匹配的问题。
你要知道你的所有输入都被存在了stdin流中。a能得到1.23。那么.23仍然被留在了stdin流。.23是个什么东西?它显然不能和b的格式%d匹配成功。所以b就会显示出一些奇怪的数字。你输入的2.34仍然存在stdin流中,但是它没机会和b去匹配了。

问题四:
又是一个匹配和逗号的问题:
首先你输入12345 23 (这些数字都被存在了stdin流中)。那么12345和%3d匹配。a得到123 剩下的45和b的格式%d成功匹配b得到45。格式化字符串中没有任何格式需要匹配了。整个过程完毕。

下面的问题我把你的scanf()重写如下。
scanf("%d%4d",&a,&b);
printf("a=%d,b=%d\n",a,b);
你的scanf()中没有用逗号隔开,那你为什么要输入12345,23呢。加个逗号是错误的。你的输入都错了。b显示不正确就理所当然了。建议你把书上scanf()的内容好好看一下。

问题五:
\t是一个水平制表符的位置,\b是回退

问题六:
无效零指的是末尾多于的0不显示出来,因为%f默认有6为小数,如果小数为不够就会添加0;
至于为什么最多输出7位,那就是c语法里头对于%g和%f稍微有些不同的定义罢了。我想只有作者才能知道。

其实学语言,不要死扣其中的每一个细节。
比如你的问题四,scanf()中没有逗号,你却在输入的地方有逗号。这样的错误是你必须注意的。学语言,最重要的是算法,是基本的语法和编程的一些技巧。其它细节东西扣太死了,往往事半功倍。耽搁你宝贵的学习时间。因为你可以有多种选择去实现某一功能。
以上是我的一些看法。
^_^。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2008-09-07
一、short int为两个字节,当第一一个变量为32767时,由于short int为有符号型,故最高位0,其余全为1,加1后变为16个1,成为一个负数,两整数相加得负数,溢出。
相似回答