第四章 最简单的 C程序设计
4,1 C语句概述
? C语言的语句用来向计算系统发出操作指令 。 一个语
句经编译后产生若干条机器指令 。
? 程序应该包括数据描述 ( 由数据定义部分来实现 ) 和
数据操作 ( 由语句来实现 ) 。
数据描述主要定义数据结构 ( 用数据类型型表示 )
和数据初值 。 数据操作的任务是对已提供的数据进行
加工 。
C 程序结构
源程序文件1
预编译命令
说明部分 执行部分(语句)
函数1 函数 n
源程序文件1 源程序文件n
C程序
C语句可以分为以下五类,
1,控制语句, 完成一定的控制功能, C只有 9种控制语句,
? ① if( )~ else~ (条件语句 )
? ② for ( ) ~ ( 转向语句 )
? ③ while( )~ (循环语句 )
? ④ do~ while ( ) (循环语句 )
? ⑤ continue ( 结束本次循环语句 )
? ⑥ break (中止执行 switch或循环语句 )
? ⑦ switch (多分支选择语句 )
? ⑧ goto (转向语句 )
? ⑨ return ( 从函数返回语句 )
其中:括号 ( ) 表示其中是一个条件, ~表示内嵌的语句 。
? 2.函数调用语句 。
由一次 函数调用 加一个 分号 构成一个语句,例如,
printf(, this is a C statement., );
c=max(a,b);
? 3.表达式语句 。 由一个表达式构成一个语句。
最典型的是:由赋值表达式构成一个赋值语句。
a=3 赋值表达式
a=3; 赋值语句。
i=i十 1 是表达式,不是语句)
i= i+ l; (是语句)
x+y+z; (是语句 )
说明:一个语句必须在最后出现分号,分号是语句中
不可缺少的一部分。
? 4.空语句 。下面是一个空语句,;
? 5,可以用 { }把一些语句括起来成为 复合语句,如下面是一个
复合语句。
{ a=3;
b=4;
c=a+b;
}
注意,复合语句中最后一个语句中最后的分号不能忽略不写 ;
? C语言允许一行写几个语句,也允许一个语句拆开写
在几行上,书写格式无固定要求 。
a=6; b=10; c=a+b; ___同一行
4,2 赋值语句
赋值语句 是由 赋值表达式 加上一个 分号 构成 。
注意,C语言中的赋值号, =”作为赋值运算符;
正确写法:赋值表达式
? if (( a= b) > 0) t= a;
错误写法:赋值语句
? if (( a= b;) > 0) t= a;
4.3 C语言中的输入输出
? C语言本身不提供输入输出语句 ;
输入和输出操作是由函数来实现的 。 在 C的标准函数
库中 (stdio.h)提供了一些输入输出函数, 例如,
printf函数和 scanf函数 。
? printf与 scanf为函数名称, 非关键字
? #include <stdio.h> 语句的含义
预处理命令, 调用标准函数库 (包括输入输出功能 )
? putchar(参数 )字符输出
? 功能:把一字节代码写入标准输出文件(显示
器)
? 参数,int型
? 返回值:正常时为写入的代码值,
出错时为 EOF(即 -1),int型。
? getchar()字符输入
?功能:从标准输入文件(键盘)读入一字节代码
?参数:无
?返回值:正常时为读到的代码值,出错时
或遇结束( Ctrl+z)为 EOF(即 -1),int型。
4.4 字符数据的输入输出
4.4.1 putchar函数(字符输出函数 )
? 使用方法,putchar( c) ;
? 注意事项,使用前要加入以下语句,
# include,stdio.h”
( 使用 printf和 scanf函数时不需要添加 。 )
? 也可以输出其它转义字符,如,
? putchar( ’ \ 101’) (输出字符 ’ A’)
? putchar( ’ \’’) (输出单引号字符 ’ )
? putchar(’\ 015’) (使输出回车,不换行)
例 1
4.4.2 getchar函数(字符输入函数)
? 此函数的作用是从终端 ( 或系统隐含指定的输入设备 ) 输入一个字
符, getchar函数没有参数 。
? 函数的值就是从输入设备得到的字符 。 例如,
[ 例 4,2] # include,stdio.h”
main()
{ char c;
c= getchar();
putchar( c) ;
}
? 在运行时, 如果从键盘输入字符 a;
? a ( 输入 ‘ a?后, 按, 回车, 键, 字符才送到内存 )
? a ( 输出变量 c的值 ’ a?)
? Printf(“%c”,getchar())
? Putchar(getchar());
4.5 格式输入与输出
? printf格式输出
printf(格式控制,输出表 )
格式控制字符 p81
? scanf格式输入
scanf(格式控制,地址表 )
4.5.1 printf函数(格式输出函数)
? 作用:向终端 ( 或系统隐含指定的输出设备 ) 输出
若干个任意类型的数据 ( putchar只能输出字符, 而且
只能是一个字符, 而 printf可以输出多个数据, 且为任
意类型 ) 。
? 一, 一般格式,printf( 格式控制, 输出表列 )
?, 格式控制, 是用双引号括起来的字符串, 也称, 转
换控制字符串,, 它包括两种信息,
? 1,格式说明, 由, %,, 和格式字符组成, 如 % d,%
f等 。 它的作用是将输出的数据转换为指定的格式输出 。
格式说明总是由, %, 字符开始的 。
? 2,普通字符,即需要原样输出的字符 。
printf(”a=% d b=% d”,a,b);
printf(”a+b=% d,a-b=%,, a+b,a-b);
格式说明 输出表列
假设 a,b值分别为 3,4,则输出为
a=3 b=4
a+b=7,a-b=-1
? 由于 printf是函数,因此,,格式控制, 字符串和
,输出表列, 实际上都是函数的参数 。可以表示为
printf(参数 1,参数 2,参数 3,……,参数 n)
printf函数的功能是将参数 2~参数 n,按参数 1给定的格式输出。
? 二, 格式字符
? 1,d格式符 。 用来输出十进制整数 。 有以下几种用法,
? ( 1) % d,按整型数据的实际长度输出 。
? ( 2) % md,m为指定的输出字段的宽度 。 如果数据的位数小于 m,
则 左端补以空格, 若大于 m,则按实际位数输出, 如
printf (, % 4d,% 4d”,a,b)
若 a= 123,d=12345,则输出结果为, 123,12345
? ( 3) % ld,输出长整型数据 。 如
1ong a=135790;
printf(, % ld,a) ; ----正确
printf(“%d”,a); ---错误
Printf(“%8ld”,a),输出为
135790
8列
? 一个 int型数据可以用 % d或 % ld格式输出 。
? 2,O格式符, 以 8进制数形式输出整数 。 由于是将内存单元中的
各位的值 ( 0或 1) 按八进制形式输出,因此输出的数值不带符号,
即 将符号位也一起作为八进制数的一部分 输出 。 例如, -1在内存
单元中 ( 以补码形式存放 ) 如下,
a=-1 11 11 11 11 11 11 11 11
int a= -1
printf(, % d,% o”,a,a) ;
输出为
- 1,177777
不会输出带负号的八进制整数 。 对长整数 ( 1ong型 ) 可以用, %
1o。, 格式输出 。 同样可以指定字段宽度, 如 printf(, % 8o”,a)
输出数据为 177777。
? 3·x格式符, 以 16进制数形式输出整数, 同样不会出现负的十
六进制数 。 例如,
int a=一 1;
printf(, % x,% 0,% d”,a,a,a) ;
输出结果为
ffff,177777,-1
同样可以用, % lx”输出长整型数, 也可指定宽度, 如, % 12x”
? 4,u格式符, 用来输出 unsigned型数据, 即无符号数, 以十
进制形式输出 。
一个有符号整数 ( int型 ) 也可以用 % u格式输出;反之, 一个
unsigned型数据也可以用 % d格式输出 。 按相互赋值的规则处理
( 见第二章 2.9) 。 unsigned型数据也可用 % o或 % x格式输出 。
? 【 例 4,2」
? #include <stdio.h>
? void main()
? { unsigned int a=65535;
? int b=-2;
? printf(, a=%d,%o,%x,%u\n”,a,a,a,a) ;
? printf(, a=%d,%o,%x,%u\n”,b,b,b,b) ;
? }
? 运行结果为,
? a=一 1,177777,ffff,65535 11 11 11 11 11 11 11 11
? b=一 2,177776,fffe,65534 11 11 11 11 11 11 11 10
? 5,c格式符, 用来输出一个字符 。 如,
? char c= ’ a’; prinft(, % c”,c) ;
? 输出字符 ‘ a’
? 一个整数, 只要它的值在 0~ 255范围内, 也可以用字符形式输
出, 在输出前, 将该整数转换成相应的 ASCII字符;反之, 一个字
符数据也可以用整数形式输出 。
「 例 4,3】
main()
{ char c=?a?; int i=97;
printf(, c%, % d\n”,c,c) ;
printf(, % c,% d\n”,i,i) ;
}
运行结果为,a,97
a,97
也可以指定输出字数宽度, 如果有 printf(, % 3c”,c)
则输出,” a”,即 c变量输出占 3列, 前 2列补空格 。
? 6,s格式符, 用来输出一个字符串 。 有几种用法,
? (1) % s,例如, printf(, %s”,”CHINA”)
? ( 2) % ms,输出的字符串占 m列, 如字符串本身长度大于 m,则突破 m
的限制, 将字符串全部输出 。 若串长小于 m,则左补空格 。
? ( 3) % -ms,如果串长小于 m,则在 m列范围内, 字符串向左靠, 右补
空格 。
? ( 4) % m.ns,输出占 m列, 但只取字符串中左端 n个字符 。 这 n个字符
输出在 m列的右侧, 左补空格 。
? ( 5) % -m.ns,其中 m,n含义同上, n个字符输出在 m列范围的左侧,
右补空格 。 如果 n> m,则 m自动取 n值即保证 n个字符正常输出 。
[例 4,4]
? main()
? { printf(”%3s,%7.2s,%.4s,%-5.3s\n”,
?, CHINA”,” CHINA”,” CHINA”,”CHINA”) ; }
? 输出如下,CHINA,CH,CHIN,CHI
? 其中第三个输出项, 格式说明为, %,4s”,即只指定了 n,没指定 m,自
动使 m= n=4,故占 4列 。
? 7,f格式符, 以小数形式输出实数, 有以下几种用法,
? ( 1) % f,不指定字段宽度, 由系统自动指定, 使整数部
分全部如数输出, 并输出 6位小数 。
【 例 4.5】
main()
{ float x,y;
x= 111111,111; y= 222222,222;
printf(, % f,x十 y) ; }
运行结果,
333333,328125
注意, 只有前 7位数字是有效数字。
? 「例 4,6」
? main()
? { double x,y;
? x=111111111111,11111111;
? y= 2222222222222.22222222;
? printf(, % f”,x十 y);
? }
? 输出结果为
? 3333333333333.328125
? 双精度数也可用% f格式输出,它的有效位数一般为 16位,给出
小数6位。
? 可以看到最后 3位小数(超过 16位)是无意义的。
? ( 2) % m.nf指定输出的数据共占 m列, 其中有 n位小数 。 如果数
值长度小于 m,则左端补空格 。
? ( 3) % 一 m.nf基本相同, 只是使输出的数值向左端靠, 右端补
空格 。
? 【 例 4,7]
? main()
? {
? floatf f=123,456;
? printf(, %f,%10f,%10.2f,%.2f,%-10.2f\n”,f,f,f,f,f);
? }
? 输出结果如下,
? 123.455994,123.455994,123.46,123,46,123.46,f的值
应为 123,456,但输出为 123,455994,这是由于实数在内存中
的存储误差引起的
? 8.e格式符, 以指数形式输出实数 。 可用以下形式,
? ( 1) % e不指定输出数据所占的宽度和数字部分小
数位数, 由系统自动指定给出 6(5)位小数, 指数部分
占 5(4)位 ( 如 e+002,e+02), 其中, e”占一位, 指
数符号占一位, 指数占 3(2)位 。 数值按标准化指数形
式输出 ( 即小数点前必须有而且只有一位非零数字 ) 。
例如
? printf(, %e”,123.456) ;
? 输出,1.234560e+ 002,(1.23456e+02)。 也就是说用
% e格式输出的实数共占 13(11)列宽度 。
? ( 2) % m.ne和% -m.ne m,n和, -”字符含义与前相同。此处
n指 数据的小数位数 。若 f= 123.456,则
? printf(”%e,%10e,%10.2e,%.2e,%-2.3e,”,f,f,f,f,f) ;
? 输出如下,
? 1.23456e+02,1.23456e+02,1.23e+ 02,1.23e+ 02,1.23e十 02
? 第二个输出项按% 10e输出,即只指定了 m=10,未指定 n,凡未指定 n,自
动使 n=6,整个数据长 11列,超过给定的 10列,乃突破 10列的限制,按实际
长度输出。
? 第三个数据共占 10列,小数部分占 2列。
? 第四个数据按字“%,2e”格式输出,只指定 n= 2,未指定 m,自动使 m等
于数据应占的长度,今为 8列。
? 第五个数据应占 10列,数值只有 8列,由于是“% -10.2e”,数值向左靠,
右补二个空格。
? 9,g格式符, 用来输出实数, 它根据数值的大小, 自
动选 f格式或 e格式 ( 选择输出时占宽度较小的一种 ),
且不输出无意义的零 。
? 例如, 若,f=123.456,则
? printf(, %f,%e,%g”,f,f,f) ;
? 输出如下,
? 123.456001,1.23456e+02,123.456
? 用 % f格式输出占 10列, 用 % e格式输出占 11列, 用
% g格式时, 自动从上面两种格式中选择短者 ( 今为
% f格式为短 ), 故占 7列, 且按 %f格式用小数形式输
出, 最后三个小数位, 0”为无意义的 0,不输出, % g
格式用得较少 。
? 以上的 9种格式符归纳如下,
? 格式字符 说 明
? d 以带符号的十进制形式输出整数 ( 正数不输出符号 ) 。
? o 以 8进制无符号形式输出整数 ( 不输出前导符 0) 。
? x 以 16进制无符号形式输出整数 ( 不输出前导符 0x) 。
? u 以无符号 10进制形式输出整数
? c 以字符形式输出, 只输出一个字符 。
? s 输出字符串 。
? f 以小数形式输出单, 双精度数, 隐含输出 6位小数 。
? e 以标准指数形式输出单, 双精度数, 数字部分小数位
数为 6位 。
? g 选用 % f或 % e格式中输出宽度较短的一种格式, 不输出
无意义的 0。
? 在格式说明中,在%和上述格式字符间可以插入以下几种附加
符号。
? 表 4,2附加格式说明字符
? 字符 说 明
? l——用于长整型整型,可加在格式符 d o x.u前面。
? m(代表一个正整数 )——数据最小宽度。
?,n(代表一个正整数)) ——对实数,表示输出 n位小数;对字
符串,表示截取的字符个数。
? - ——输出的数字或字符在域内向左靠。
? 用 printf函数输出时, 应注意数据类型应与上述格式说明匹配,
否则将会出现错误 。
? 在使用 printf函数时, 注意事项,
? 1,有些系统要求格式字符要用小写字母, 如 % d不能写成
% D。
? 2,可以在 printf函数中的, 格式控制, 字符串内包含第二
章中的, 转义字符,, 如, \n”,,\t”,,\b”,,\r”、
,\f”,,\ 377”等 。
? 3,上面介绍的 d,o,,x,c,s,f,e,g等字符, 如用在, %, 后
面就作为格式符号 。 一个格式说明以, %, 开头, 以上述 9个格
式字符之一为结束, 中间可以插入附加格式字符 ( 也称修饰
符 ) 。 例如,
? printf(“c=%cf=%fs=%s”,c,f,s);
? 第一个格式说明为, % c”而不包括其后的 f,第二个格式说明为
,% f,不包括其后的 s,第三个格式说明为 % s。 其它的字符为
原样输出的普通字符 。
? 4.如果想输出字符, %,,则应该在, 格式控制, 字符串中用
连续两个%表示,如
printf(, % f%%,, 1,0/ 3);
输出 0.333333%
? 5.不同的系统在实现格式输出时,输出结果可能会有一些小
的差别,例如用% e格式符输出实数时,有些系统输出的指数部
分为 4位(如 e十 02)而不是 5位( e+ 002),前面的数字部分为 5
位小数而不是 6位等等。
4.5.2 scanf函数 ( 格式输入函数 )
? getchar函数只能用来输入一个字符, 用 scanf函数可以用来输入任
何类型的多个数据 。
? 一, 一般形式
? scanf( 格式控制, 地址表列 )
?, 格式控制, 的含义同 printf函数,, 地址表列, 是由若干个地
址组成的表列, 可以是变量的地址, 或字符串的首地址 。
? 例 4,9
? main( )
? { int a,b,c;
? scanf(, %d%d%d”,&a,&b,&c) ; /*按照 a,b,c在内存的地址将
a,b,c的值存进去 */
? printf(“%d,%d,%d\n”,a,b,c) ;
? }
? scanf(, %d%d%d”,&a,&b,&c)
? 运行时按以下方式输入 a,b,c的值,
? 3 4 5 (输入 a,b,c的值)
? 3,4,5 (输出 a,b,c的值)
? &a,&b,&c中的, &”是地址运算符,&a指 a在内存中的地址,
? 合法输入,
? 方法一 > 3 4 5 ----数据之间用空格或 TAB键
? 方法二 > 3 ----输入一个后用回车
? 4
? 5
? 用, %d%d%d”格式输入时,不能用逗号 (可用空格 )作两个数据间
的分隔符,如下面输入不合法,
? 3,4,5 ? scanf(, %d,%d,%d”,&a,&b,&c)
? 二、格式说明
? 和 printf函数中的格式说明相似,以%开始,以一个格式字符结
束,中间可以插入附加的字符。表 4-3说明字符(修饰符)的含义。
? scanf格式字符
? d 用来输入十进制整数。
? o 用来输入八进制整数。
? x 用来输入十六进制整数。
? c 用来输入单个字符。
? s 用来输入字符串,将字符串送到一个字符数
组中,在输入时以非空白字符开始,以第一个空白
字符结束。字符串以串结束标志, \ 0”作为其最后
一个字符。
? f 用来输入实数,可以用小数形式或指数形式
输入。
? e 与 f作用相同,e与 f可以互相替换。
附加的格式说明字符
? l 用于输入长整型数据(可用% ld,% lo,% lr),以及 double
型数据(用% lf或% 1e)。
? h 用于输入短整型数据(可用% hd,% hO,% hx)。
? m 域宽(为一正整数)指定输入数据所占宽度(列数)。
? * 表示本输入项在读人后不赋给相应的变量。
? 说明,
? 1.标准 c在 scanf中不使用% u说明符,对 unsigned型数据,以% d
或% o、% x互格式输入。
? 2·可以指定输入数据所占列数,系统自动按它截取所需数据。如
? scanf(, % 3d% 3d”,&a,&b) ;
? 输入 123456
? 系统自动将 123赋给 a,456赋给 b。也可用于字符型
? scanf(, % 3c”,&ch) ;
? 输入 3个字符,把第一个字符赋给 ch,例如输入 abc,ch得到字
符 ’ a?。
? 3.%后的, *” 附加说明符,用来表示跳过它相应的数据。例如
? scanf(, % 2d% *3d% 2d\ n”,&a,&b) ;
? 如果输入如下信息,
? 12 345 67
? 将 12赋给 a,67赋给 b.第二个数据, 345”被跳过不赋给任何变量。
在利用现成的一批数据时,有时不需要其中某些数据,可用此法, 跳
过, 它们。
? 4,输入数据时不能规定精度,例如
? scanf(, %7.2f”,&a);
? 是不合法的,不能企图输入 1234567而使 a的值为 12345.67。
? 三,scanf函数的执行中应注意的问题
? 1,scanf函数中的, 格式控制, 后面应当是变量地址,而不应是变
量名。
? 例如,如果 a,b为整型变量,则
? scanf(, % d,% d”,a,b);
? 2.如果在, 格式控制, 字符串中除了格式说明以外
还有其它字符,则在输入数据时应输入与这些字符相
同的字符。例如
? scanf(“% d,% d”,&a,&b);
? 输入形式,3,4
? 如果是 scanf(, %d %d”,&a,&b);
? 输入时两个数据间应空二个或更多的空格字符。
? scanf(, % d:% d:% d”,&h,&m,&s) ;
? 输入形式,12,23,36
? scanf(, a=%d,b=%d,c=%d”,&a,&b,&c);
? 输入应为,a=12,b= 24,c= 36
? 3.在用, % c”格式输入字符时,空格字符和, 转义字符, 都作为
有效字符输入,
? scanf(, % c% c% c”,&c1,& c2,& c3) ;
? 如输入 a b c
? 字符 ’ a?送给 c1,字符 ‘ ’ 送给 c2,字符 ’ b?送给 c3,因为% c只
要求读人一个字符,后面不需要用空格作为两个字符的间隔,因
此 ‘ ’ 作为下一个字符送给 c2。
? 4.在输入数据时,遇以下情况时该数据认为结束,
? ①遇空格,或按, 回车, 或, 跳格, ( TAB)键。
? ②遇宽度结束,如, % 3d”,只取 3列。
? ③遇非法输入。如 scanf(, % d% c% f”,&a,&b,&c);
? 若输入, 1234al23o.26
? 1234 ->a
? ?a? ->b
? 123 ->c
4,6 程序举例
? 「 例 4,10」 输入三角形的三边长, 求三角形面积 。
? 为简单起见, 设输入的三边长山\ c能构成三角形 。
? 程序如下,/* page 86 example3.10 */
? #include "math.h"
? main()
? {
? float a,b,c,s,area;
? scanf("%f,%f,%f",&a,&b,&c);
? s=1.0/2*(a+b+c);
? area=sqrt(s*(s-a)*(s-b)*(s-c));
? printf("a=%7.2f,b=%7.2f,c=%7.2f,s=%7.2f\n",a,b,c,s);
? printf("area=%7.2f\n",area);
? }
? 运行情况如下,3,4,6
? 「 例 4,11」 从键盘输入一个大写字母, 要求改用小写字母输出 。
程序如下,
? #include "stdio.h"
? main()
? {
? char c1,c2;
? c1=getchar();
? printf("%c,%d\n",c1,c1);
? c2=c1+32;
? printf("%c,%d\n",c2,c2);
? }
? 运行情况下,
? A
? A,65
? a.97
? 【 例 4,12」 求 ax2+ bx+ c=0方程的根 。 a,b,c由键盘输
入, 设 b2一 4ac> 0。 程序如下,
? #include "math.h"
? main()
? {
? float a,b,c,disc,x1,x2,p,q;
? scanf("a=%f,b=%f,c=%f",&a,&b,&c);
? disc=b*b-4*a*c;
? p=-b/(2*a);q=sqrt(disc)/(2*a);
? x1=p+q;x2=p-q;
? printf("\n\nx1=%5.2f\nx2=%5.2f\n",x1,x2);
? }
? 运行情况如下, a=1,b=3,c= 2
? 程序中用了预处理命令# inc1ude,math.h”,表示要用数
学库函数 。