第三章 简单的C程序设计


§3.1 C语句概述 §3.2 程序的三种基本结构
§3.3 赋值语句 §3.4 数据输出
§3.5 数据输入 §3.6 程序举例

 

§3.1 C语句概述

C程序结构如图:

一个C程序可以由多个源程序文件构成,Turbo C用“工程文件”(prj:Project)来描述该程序由那些源程序文件构成。所有这些源程序文件经过分别编译后形成各自的目标文件,经连接程序LINK后形成一个EXE文件。

一个源程序文件由若干函数和“预编译命令”构成。

函数包括数据定义部分(变量定义)和执行部分,执行部分是C语言语句,完成对数据的操作。

C语句有以下五类:

1、控制语句,完成程序流程控制。

if()~else~ 条件语句
for()~ 循环语句
while()~ 循环语句
do~while() 循环语句
continue 结束本次循环语句
break 中止switch或循环语句
switch 多分支选择语句
goto 转向语句
return 从函数返回语句
()表示条件,~表示内嵌的语句。

2、函数调用语句。例、

printf("This is a C statement.");/* 该语句调用函数printf() */

3、表达式语句:在表达式后面加分号构成。例:

a = 3 /* 后面无分号,是表达式 */

a = 3;/* 后面有分号,是语句 */

i++; /* 语句 */

4、空语句:仅包含一个分号的语句,例、

5、复合语句:由大括号{ }括起来的语句序列。例、

{  
  z = x + y;
  t = z / 100;
  printf("%f",t);
}  

注:C语言允许一行写多个语句,也允许一个语句写多行。


§3.2 程序的三种基本结构

结构化程序设计方法:在程序设计中,使用结构清晰、便于阅读的程序结构。

有三种程序的基本结构:

1、顺序结构。

2、选择结构:根据条件p选择执行程序的某部分,但无论选择哪部分,程序均将汇集到同一个出口。

3、循环结构:两种。

(1)当型循环结构。当条件p成立(“真”)时,反复执行A操作,直到p为“假”时才停止循环。

特点:①先判条件,若条件满足,则执行A。

②在第一次判别条件时,若条件不满足,则A一次也不执行。

(2)直到型循环结构。先执行A操作,再判别条件p是否为“假”,若为“假”,再执行A,如此反复,直到p为“真”为止。

特点:①先执行A再判条件,若条件满足再执行A。

②A至少被执行一次。

选择结构可以派生出“多分支选择结构”:根据k的值(k1、k2、...、kn)不同而执行A1、A2、...、An之一。

三种基本结构可以处理任何复杂的问题。例如,下图的程序结构可以分解为顺序结构(A和B)及当型循环结构(B)。

使用循环结构时,在进入循环前,应设置初始条件。同时,在循环过程中,应修改条件,以便程序退出循环。如果不修改条件或错误修改,可能导致程序不能退出循环,即进入“死循环”。


§3.3 赋值语句

① C语言中的“=”作为赋值运算符,不是“等于”。

② 赋值语句和赋值表达式是不同的概念,赋值表达式使C语言非常灵活。

例、

if ((a = b) > 0) t = a;

if ((a = b;) > 0) t = a;


§3.4 数据输出

putchar()、printf():输出到终端(系统标准输出设备stdout,指显示器)。

C语言不提供输入输出语句,输入输出由开发系统提供的函数实现,函数的原型(函数名、返回值类型、形式参数)在文件stdio.h中定义,因此,使用输入输出函数时,应在源程序的开头使用如下语句:

#include "stdio.h"

#include是一个预编译命令。

stdio.h放在程序的开头,因此称为“头文件”;又由于使用#include(包含)命令,又称为“包含文件”。

开发系统提供很多函数,它们的原型在不同的头文件中定义,因此,在程序开头,总是包含需要的头文件。

最常用的头文件:

头文件名 作用
stdio.h 定义输入输出函数
string.h 定义字符串操作函数
math.h 定义sin、cos等数学函数

3.4.1 putchar()函数

作用:向终端输出一个字符。

用法:putchar(c); /* c是字符变量或整型变量 */

[例3.1]

#include "stdio.h"
main()
{ char a,b,c;
  a = 'B'; b = 'O'; c = 'Y';
  putchar(a); putchar(b); putchar(c);
}  

程序输出:BOY

注意:若没有#include "stdio.h",出现错误信息(T1.C是程序文件名):

Linker Error: Undefined symbol '_putchar' in module T1.C

表示putchar符号(函数名前加下划线)未定义,因为开发系统不知道putchar()的原型。

程序中有了#include "stdio.h"后,开发系统把程序中出现的putchar()与stdio.h中的定义进行比较,它们是相同的,从而开发系统知道了putchar()的定义(原型)。

例、

putchar('\n'); 输出换行符
putchar('\101'); 输出字符'A'(八进制101=65=0x41)
putchar('\''); 输出单引号'
putchar('\015'); 输出回车(八进制015=13=0x0D)

 

3.4.2 printf()函数

作用:格式化输出任意数据列表.

一、 printf()的一般格式

printf(格式控制,输出列表);

例、

int i = 3;
double f = 4.56;
printf("i = %d, f = %f\n", i,f);

printf()是函数,“格式控制”和“输出列表”是其参数。可以表示为:

printf(参数1,参数2,参数3,....,参数n);

其中“参数1”表示“格式控制”;其余参数表示“输出列表”。

二、格式字符

1、d格式符:按十进制格式输出。

%d 输出数字长度为变量数值的实际长度
%md 输出m位(不足补空格,大于m位时按实际长度输出)
%ld,%mld l(小写字母L)表示输出“长整型”数据
%0md,%0mld 0(数字0)表示位数不足m时补0

注:%后面的m(位数控制)、0(位数不足补0)对于其他格式符也适用。

例、(□表示空格)

int i = 123;
long j = 123456;
printf("%d□5d□05d,□ld□8ld□08ld",i,i,i,j,j,j);

123□□□123□00123,□123456□□□123456□00123456

2、o(字母)格式符:按八进制格式输出。(不会出现负数格式)

3、x格式符:按十六进制格式输出。(不会出现负数格式)

4、u格式符:用于输出unsigned类型数据。

[例3.2]

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

b=-2,177776,fffe,65534

5、c格式符:以字符形式输出。例、

char c;
printf("%c",c);

一个整数,若其值在0~255范围内,也可以用字符形式输出,在输出前,将该整数转换为对应的ASCII字符。反之,一个字符数据也可以用整数形式输出。

[例3.3]

main()
{ char c = 'a';
  int i = 97;
  printf("%c,%d\n",c,c);
  printf("%c,%d\n",i,i);
}  
运行结果为:

 

a,97

 

a,97

6、s格式符:以字符串格式输出。

%s 例、printf("%s","CHINA");
%ms m指定宽度(不足时左补空格,大于时按实际宽度输出)
%-ms 左对齐,不足m时右补空格
%m.ns 输出占m个字符位置,其中字符数最多n个,左补空格
%-m.ns 同上,右补空格

7、f格式符:按实数格式输出。

%f 按实数格式输出,整数部分按实际位数输出,6位小数
%m.nf 总位数m(含小数点),其中n位小数
%-m.nf 同上,左对齐

[例3.5]

main()
{ float x, y;
  x = 111111.111; y = 222222.222;
  printf("%f", x+y);
}  
程序输出:
  333333.328152(实数运算中误差不可避免)

[例3.6]

main()
{ double x,y; double x2,y2;
  x = 1111111111111.111111111;y = 2222222222222.222222222;
  x2= 1111111111111.111; y2= 2222222222222.222;
  printf("%f %f", x+y, x2+y2); /* 13位整数,9位小数 */
}  
程序输出:
  3333333333333.333010 3333333333333.333010(相同)

从[例3.6]和[例3.7]可以看出:

(1)实数运算中误差不可避免。

(2)double(例3.7)比float(例3.6)精度高。

(3)float实数(单精度)的有效位数是7位,double实数(双精度)的有效位数是16位,超过有效位数的输出和输入均无意义。

[例3.7]

main()
{  
  float f = 123.456;
  printf("%f□□%10f□□%10.2f□□%.2f□□%-10.2f",f,f,f,f,f);
}  
输出结果:
  123.455994□□123.455994□□□□□□123.46□□123.46□□123.46

8、e格式符:以指数形式输出实数。

%e 输出13位,其中:1位整数,1位小数点,6位小数,5位指数(含字符e和指数的符号)
%m.ne  
%-m.ne  

9、g格式符:根据数值大小,自动选择f或e格式输出。

三、使用注意

%是printf()的格式说明符,若要直接输出字符%,在格式控制中使用两个连续的%。

例、

printf("%f%%", 1.0/3)

输出:0.333333%。


§3.5 数据输入

getchar()、scanf():从系统标准输入设备stdin(一般指键盘)输入数据。

3.5.1 getchar()函数

作用 从stdin输入一个字符 同时有回显
形式 int getchar(void) 无参数,返回输入的字符
原型定义 stdio.h  

Turbo C 热键帮助(context-sensitive help):

光标移动到需帮助的文本上,按Ctrl+F1键。

[例3.8]

#include "stdio.h"
main()
{ char c;
  c = getchar();
  putchar(c);
}  

运行时,若从键盘输入字符'a',屏幕显示为:

a↙

a

 

3.5.2 scanf()函数

一、一般格式

作用 按规定格式输入 "地址列表"是输入信息存放地址的列表,一般是变量地址。返回值等于成功输入的项数
形式 int scanf(格式控制,地址列表)
原型定义 stdio.h

[例3.9]

#include "stdio.h" (只有printf和scanf函数可以不要头文件)
main()
{ int a,b,c;
  scanf("%d%d%d",&a,&b,&c);
  printf("%d,%d,%d\n",a,b,c);
}  

运行时按如下方式输入三个值:

3□4□5↙ (输入a,b,c的值)

3,4,5 (printf输出的a,b,c的值)

(1) &a、&b、&c中的&是地址运算符,分别获得这三个变量的内存地址。

(2) "%d%d%d"是按十进值格式输入三个数值。输入时,在两个数据之间可以用一个或多个空格、tab键、回车键分隔。

以下是合法输入方式:

① 3□□4□□□□5↙

② 3↙

4□5↙

③ 3(tab键)4↙

5↙

二、格式说明

与printf()的格式控制类似。

格式字符 说明
d 用于输入十进制数
o(字母) 用于输入八进制数
x 用于输入十六进制数
c 用于输入单个字符
s 用于输入字符串(非空格开始,空格结束,字符串变量以'\0'结尾)
f 用于输入实数(小数或指数均可)
e 与f相同(可与f互换)
格式的附加说明符
字符 说明
l(字母)

用于长整型数(%ld、%lo、%lx)或double型实数(%lf、%le)

h 用于短整型数(%hd、%ho、%hx)
域宽(一个正整数) 指定输入所占列宽
* 表示对应输入量不赋给一个变量

说明:

1、scanf()中不使用%u说明符。对unsigned型数据,以%d、%o、%x格式输入。

2、可以指定输入数据的列数,系统自动按它截取所需数据。例、

scanf("%3d%3d",&a,&b);
输入 123456↙
系统自动将123赋给a,456赋给b。

3、*格式用于跳过一个数据域,例、

scanf("%2d□%*3d□%2d",&a,&b);
输入:12□345□67↙
12→a,345被跳过,67→b。

*主要用于利用现有数据时,跳过某些数据项。

4、输入实数不能规定精度,如、

scanf("%7.2f",&a);

三、使用scanf()函数的注意事项

1、sacnf()中的变量必须使用地址。

  int a, b;

scanf("%d,%d",a,b);
scanf("%d,%d",&a,&b);

2、scanf()的“格式控制中”,可以使用其它字符,但在输入时必须输入这些相同的字符。

例、

scanf("%d,%d",&a,&b);
输入: 3,4 ↙(逗号与"%d,%d"中的逗号对应)

例、

scanf("%d□□%d",&a,&b);
输入:3□□4 ↙(两个或以上空格)

例、

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 ↙(a=,b=,c=及逗号与格式控制相对应)

3、在用"%c"输入时,空格和“转义字符”均作为有效字符。

例、

scanf("%c%c%c",&c1,&c2,&c3);
输入:a□b□c↙
结果:a→c1,□→c2,b→c3 (其余被丢弃)

4、输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。

① 遇空格、“回车”、“跳格”键。

② 遇宽度结束。

③ 遇非法输入。

 


§3.6 程序举例

[例3.10] 输入三角形的三边长,计算其面积。

设三边长a、b、c,面积area的算法是:

求平方根函数sqrt()在math.h中定义。

#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\n",a,b,c);
  printf("area = %7.2f\n",area);
}  
运行情况如下:
  3,4,6↙
  a= 3.00, b= 4.00, c=6.00
  area = 5.33

注意

1、程序设计必须先设计算法、画出框图。

2、设计反应物理量的程序变量。

3、注意使用头文件。(Ctrl+F1的帮助信息中指出了头文件名)。

4、对于实用的程序,必须检查用户(使用程序的人)输入数据的有效性,如本例中,检查输入的边长是否大于零(不能为负或零)。但本程序仅是示例性的,未作数据有效性检查。


[例3.11] 从键盘输入一个大写字母,要求用小写字母输出。

算法:c2(小写字母) = c1(大写字母) + 32

大写字母 A B C .... Z
ASCII(十六进制) 0x41 0x42 0x43    
ASCII(十进制) 65 66 67    
小写字母 a b c .... z
ASCII(十六进制) 0x61 0x62 0x63    
ASCII(十进制) 97 98 99    

程序:

#include "stdio.h"
main()
{  
  char c1,c2;
  c1 = getchar();
  printf("%c,%d\n",c1,c1);
  c2 = c1 + 32;
  printf("%c,%d\n",c2,c2);
}  

[例3.12] 求方程的根。a、b、c由键盘输入,

算法:

程序:

#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);
}  

 


本章要求

1、程序的三种基本结构及其特点。

2、数据输入、输出函数及其格式控制。

3、熟悉Turbo C环境的使用。头文件。帮助系统的使用(Ctrl+F1)。