You are on page 1of 90

第二讲:

C语言编程基础框架
framework
C语言编程基础框架
framework
学习要点
 基本的数据类型(常量、变量;整型、浮点型、字符型、字符串型)
 字符的ASCII编码、转义字符
 变量的赋值、类型转换、访问限定
 变量命名规则
 格式化输入输出(scanf , printf)
 算术运算符、算术表达式
 赋值运算、复合赋值运算
 关系运算(符)、逻辑运算(符)
 一维数组简介
 常量的符号表示(const与define)
 标准库函数简介
BeihangSoft.cn
2.1 常量

常量:就是在程序中固定(不可以被程序改变)的数值。

 整数 (integer) 数字常量
……
 实数 (double, float) int main()
整数常量 {
 字符 (character) int a = 1;
double pai = 3.14
 字符串 (string): char ch = 'A';
……
本质是字符数组
printf("%d\n", a);
printf("%f\n", pai);
printf("%c\n", ch);
return 0;
}

3
BeihangSoft.cn
十进制与二进制、八进制、十六进制
 整数(integer)
 C语言中默认的表示方式是十进制: 0, 123, 45678, -234, -987, -0
 也可以指定进制
 十六进制:0xA2, 0xFF11(以数字零加字母x开头)
 八进制: 012, 034(以数字零开头)
进制 十进制Dec 八进制Oct 十六进制Hex
基本数字 0~9 0~7 0 ~9, A~F (or a~f)
基数 10 8 16
规则 逢10进1 逢8进1 逢16进1
实例 19 023 0x13

Dec 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Oct 0 01 02 03 04 05 06 07 010 011 012 013 014 015 016 017 020 021 022
Hex 0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF 0x10 0x11 0x12
BeihangSoft.cn
实数(浮点数)
 实数(浮点数)(单精度 float, 双精度 double)
 一般的表示方法  科学计数法
-0.016 -1.6E-2 // 表示-1.6*10-2
.28 // 表示小数0.28 2.8E-1 // 表示0.28
1233.6 1.2336e3 // 表示1233.6
8000. // 表示小数8000.0 8e3 // 表示小数8000.0
 实数与整数在计算机中的表示和保存方式不同,数
值表示的范围和精度也不相同,计算时的方法也不
……
int main()
相同。
{
 没有小数部分的实数看上去跟整数相同(数值相同, int a = 1;
但实际上不同,如8e3为8000.0而不是8000)。 double PAI = 3.14;
 默认(缺省)的实数类型是double,要表示float类 float pai = 3.14f;
型(比double表示的范围和精度小),在数据后面 char ch = 'A';
……
加后缀f或F,如:-1.6E-2f,.28F,1233.6f
BeihangSoft.cn
字符常量
 字符常量:用一对单引号括起来字符称为字符常量,如:'A',
'b', '?', ...
一个字符常量的值是该字符在机器中的字符集,通常是ASCII字符集
(American Standard Code for Information Interchange)中的编码值(但
某些IBM大型机用EBCDIC码),是一个整数值,如:'A' 的值为65,
'b' 的值为98,'?' 的值为63
……
int main()
{
int a = 1;
char ch = 'A';
……
printf("%d\n", a);
printf("%c\n", ch);
return 0;
}
6
BeihangSoft.cn
字符常量
 表示数字的字符与数字是不一样的,如 '0' int x = '0';
的ASCII编码是0x30,或十进制的 48,而 printf("%d\n", x);
不是数字0(两者差值为48) 如下四个输出结果相同
 字符实际上是一个小整数(字符的ASCII int a = 'a';
编码,0~127) printf("%c\n", a);
 数字字符 0~9(即'0' ~ '9'),字母a~z, a = 97;
A~Z之间的所有字符都是连续编码的 printf("%c\n", a);
 字符常量可像其它整数一样参与数值运算, a = '\x61';
如: printf("%c\n", a);
'5' 的编码等于 '0'+5,即 0x35; 'a'+2 等
a = '\141';
于 'c' ; '8' - '0' 等于 8 printf("%c\n", a);

printf("%d\n", a);
// 上一条语句输出什么
7
BeihangSoft.cn
ASCII编码表(PPT看不清楚,看书!)
ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符

0 NUL 32 (space) 64 @ 96 、
1 33 ! 65 A 97 a
2 34 ” 66 B 98 b
3 35 # 67 C 99 c
4 36 $ 68 D 100 d
5 37 % 69 E 101 e
6 38 & 70 F 102 f
7 39 , 71 G 103 g
8 40 ( 72 H 104 h
9 41 ) 73 I 105 i
10 \n 42 * 74 J 106 j
11 43 + 75 K 107 k
12 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 46 . 78 N 110 n
15 47 / 79 O 111 o
16 48 0 80 P 112 p
17 49 1 81 Q 113 q
18 50 2 82 R 114 r
19 51 3 83 X 115 s
20 52 4 84 T 116 t
21 53 5 85 U 117 u
22 54 6 86 V 118 v
23 55 7 87 W 119 w
24 56 8 88 X 120 x
25 57 9 89 Y 121 y
26 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 60 < 92 / 124 |
29 61 = 93 ] 125 }
30 62 > 94 ^ 126 ~
31 63 ? 8 95 — 127 DEL
BeihangSoft.cn
转义字符
 在C语言中,还有一类特殊的字符常量,称为转义字符
常量,如:'\0', '\n', '\t', ...
 也可用Hex或Oct来表示字符,分别为 '\xhh' 和 '\ooo' 形
式,如 'a', '\x61', '\141' 都表示字符 a
转义字符及其含义
转义字符 含义 转义字符 含义
\n 换行 \t 水平制表
\v 垂直制表 \b 退格
\r 回车 \f 换页
<
\a 响铃 \\ 反斜线
\' 单引号 \" 双引号
\ddd 3位8进制数代表的字符 9 \xhh 2位16进制数代表的字符
BeihangSoft.cn
转义字符实例
【例c2-1.c】图形输出! 💡💡 编程提示
• ‘\117’代表字符‘O’,117是八进制
#include <stdio.h> 数,不能写前导0
int main( ) • ‘\x29’代表字符‘)’,x29是十六进制
{ 数,不能写前导0且x为小写
printf(" * * * * *\n"
• 转义字符中只能使用小写字母
" * *\n"
• 每个转义字符只能看作一个字符
" * OO \117\117 *\n"
"* *\n" • 表示单引号、反斜杠、双引号和
"* *\n" 反斜杠时,须使用转义字符表示。
"* ___ *\n"
" * (___\x29 >>>>>>>>>>>\"Hi All\"\n"
" * *\n"
" * * * * *\n");
return 0;
}
10
BeihangSoft.cn
字符串常量
 字符串常量:用一对双引号括起来的字符串,如 "hello\n"
 注意:所有字符串均以 '\0' 结束(编码值为 0 的字符,是
不可见的字符,即存在但看不见),因此, "x" 和 'x' 不
同,字符串末尾的 '\0' 由编译程序自动添加。
 字符串中可以有转义字符,如:
printf("Welcome \n to \nBeijing!\n");
输出:
printf("\"This is \x61 string\"\n");
Welcome
输出:
to
"This is a string"
Beijing!

11
BeihangSoft.cn
2.2 变量

与常量相对应,常用的变量基本类型有:

数据类型 关键字

 整数(integer) int、long …

 实数(double, float) float、double

 字符(character) char

 字符串(string) char型数组

12
BeihangSoft.cn
2.2 变量
【例c2-2.c】a+b回顾。
// file: c1-2.c 变量定义
 int: 变量类型(整型,通常32
#include <stdio.h> 位)(还可以定义其他类型,
如 float, double, char…)
 int a, b, sum: 定义了三个整型
int main()
变量,名字分别为 a, b, sum,
{ 称为变量名。
int a, b, sum;  变量名命名规则(后文介绍)
 定义多个变量时,用逗号分开。
scanf("%d %d", &a, &b); 也可以分开定义,如
sum = a + b; int a;
printf("%d + %d = %d\n", a, b, sum); int b;
int sum;

return 0;
} 13
BeihangSoft.cn
变量命名规则
【例c2-2.c】a+b回顾。
// file: c1-2.c  int a, b, sum: 定义了三个整型
变量,名字分别为 a, b, sum,
称为变量名。
#include <stdio.h>
 变量名命名规则:变量的名字
必须是合法的标识(zhi, 4声)符
int main() (identifier)。一个标识符是
{ 由字母(或_)开头,由字母、
int a, b, sum; 数字和下划线组成的字符串。
 系统保留的关键字不能作为标
scanf("%d %d", &a, &b); 识符,如main, int, return 等。
sum = a + b;  标识符在C语言中可作为变量
名、常量名、函数名、参数
printf("%d + %d = %d\n", a, b, sum); (parameter)名、类型名、枚举
(enumeration)名和标号(label)
return 0; 等。
} 14
BeihangSoft.cn
下面哪些是非法的标识符?

Beijing beijing C_Programming


a8673 8a673 _1024
sin(25) num x6 b.3 sum*co
#stdudent a[1]
xMin topLeft numOfStdudent
x_min top_left num_of_stdudent
 C语言区分大小写,因此变量名 Beijing 和 beijing 不一样。
 变量名通常由表示特定含义的英语单词组成,几个单词(或其缩写)由下
划线或单词首字母大写连接在一起。用什么风格,取决于个人喜好。但习
惯上不混合使用。
15
BeihangSoft.cn
变量命名法
 遵循一致的命名约定会对提高代码的可用性起到重大作用
 使得许多开发人员使用同一框架成为可能
 统一的命名规范,帮助你在阅读代码的时候快速跟踪代码逻辑

匈牙利命名法
 之所以叫做匈牙利命名法时为了纪念匈牙利籍的Microsoft程序员
Charles Simonyi
 在变量名前面加上相应的小写字母的符号标识作为前缀,标识出
变量的作用域、类型等。

int i_num;
char c_name;
double d_averScore;

16
BeihangSoft.cn
变量命名法
 遵循一致的命名约定会对提高代码的可用性起到重大作用
 使得许多开发人员使用同一框架成为可能
 统一的命名规范,帮助你在阅读代码的时候快速跟踪代码逻辑
骆驼命名法和下划线法
 混合使用大小写字母来构成变量和函数的名字。
 近年来越来越流行了,在许多新的函数库和Microsoft Windows这样
的环境中,它使用得当相多。
 下划线法是C出现后开始流行起来的,在许多旧的程序和UNIX这样的
环境中,它的使用非常普遍。
骆驼式 下划线
double stuScore; double stu_score;
printEmployeePaychecks(); print_employee_paychecks();
名字中的每一个逻辑断点都 名字中的每一个逻辑断点
有一个大写字母来标记 都有一个下划线来标记
17
BeihangSoft.cn
变量命名法
 遵循一致的命名约定会对提高代码的可用性起到重大作用
 使得许多开发人员使用同一框架成为可能
 统一的命名规范,帮助你在阅读代码的时候快速跟踪代码逻辑
帕斯卡(pascal)命名法
 帕斯卡命名法与骆驼命名法类似。只不过骆驼命名法是首字
母小写,而帕斯卡命名法是首字母大写。
不建议!
 在C#中,以帕斯卡命名法和
骆驼命名法居多。 double stuScore;
💡💡 编程提示int stu_num;
变量命名时:
double StuScore; • 风格同一性
int StuNum; • 最小化长度&&最大化信息量原则
• 避免过于相似
• 避免在不同级别的作用域中重名
18
BeihangSoft.cn
C语言保留的关键字

关键字(keyword):已经被系统使用的标识符,具有预先定义好的
特殊意义,不能作为变量名、函数名及标号等使用。
int auto goto if
float static return else
char extern break while
short register continue for
long do
unsigned switch
double case
struct default
union
void define, undef, include, ifdef, ifndef, endif,
enum
typedef 及line,虽不是关键字,但是最好把它
sizeof 们看作关键字,它们主要用于C预处理
const 程序中。
volatile
signed
19
BeihangSoft.cn
基本的数据类型及其能表示的范围
数据类型 一般 32 位操作系统 16 位操作系统
(如 UNIX, W32) (如 DOS)
int 整型 32 16
short (int) 短整型 16 16
long (int) 长整型 32 32
unsigned (int) 无符号整型 32 16
float 单精度浮点型 32 32
double 双精度浮点型 64 64
char 字符型 8 8
1. 在C语言中,数据是有范围的;如对于32位int,其数值范围为
-2,147,483,648 ~ 2,147,483,647 ( -232-1 ~ 232-1-1 )
2. 在不同的系统平台,同一数据类型(如int)范围可能不同。
一般来说,不同的系统(如Windows, Linux),相同数据类型长度可能有差异。但
有个原则是:短整型(short)不能长于普通整型(int);长整型(long)不能短于普通整
型(int)。
3. 浮点数使用标准数据格式(IEEE-754),float的有效数字大约相当于十进制的7
位,表示范围约-3.4*1038 ~ 3.4*1038,能表示的绝对值最小数约为10-44.85;double能
表示的范围和精度更大。浮点数的表示是近似值,如显示的是1.0,计算机中实际
可能是0.99999999… ,也可能是1.0000001… 。
20
BeihangSoft.cn
c1-2.c :a+b回顾
【例c2-2.c】a+b回顾。
#include <stdio.h>

int main() 💡💡 编程提示


{ • 时刻注意变量的数据范围
int a, b, sum; 是否满足题目或实际需求。

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


思考
哪种数据类型可以解决,为什么?
sum = a + b;

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


分别输入十亿和二十亿
return 0;
1000000000
} 2000000000
21 看看结果怎么样。为什么?
21
BeihangSoft.cn
变量的赋值和类型转换
#include <stdio.h>  变量定义后才能使用。
int main( )  赋值运算符 ' = ' : 表示把运算
{ 符右边的值(常量、变量、或
表达式,如b=a+5)赋给左边。
int a, b;
 赋值运算从右往左结合。如
double d;
b = a = 55;

a = 55;  赋值时左右两边类型不一致?
b = a; // b = a = 55;
d = 123.456;

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


printf("d = %f\n", d);

return 0;
}
变量的赋值和类型转换
#include <stdio.h>
#include <stdio.h> int main( )
int main( ) {
{ int a, b;
int a, b; double d;
double d;
a = 55;
a = 55; b = a; // b = a = 55;
b = a; // b = a = 55; d = 123.456;
d = 123.456;
a = d; 赋值时左右两边
printf("a = %d, b = %d\n", a, b); d = a; 类型不一致?
printf("d = %f\n", d);
output? printf("a = %d, b = %d\n", a, b);
return 0; printf("d = %f\n", d);
} a = 55, b = 55
d = 123.456000 output?
return 0;
} a = 123, b = 55
d = 123.000000
BeihangSoft.cn
变量的初始化
#include <stdio.h>
 变量定义的时候即赋
int main( )
值,赋值的内容可以
{
是常量、变量(已经
int a, b;
赋值了)、表达式
double d; (有具体的返回值)
short s = 0;
int a1 = 55, b1 = a1;  当局部变量定义时没
int day_seconds = 24*60*60; 有赋值时,变量的值
是随机的
const double pi = 3.141592653589;
output:
printf("a = %d\na1 = %d\n", a, a1);
a = 4200656 这里a的值是
return 0;
a1 = 55 不可信的!
} 24
BeihangSoft.cn
*类型限定符const
#include <stdio.h>
const可以放在任何
int main( )
变量定义之前,说
{
明变量是只读的
short s = 0;
(不能修改的),
int a = 55, b = a;
这样的变量又称为
int day_seconds = 24*60*60;
常量变量(仍然是
变量,有变量的属
const double pi = 3.141592653589;
性,相当于常量,
但不是常量)。
......
pi = 0.618; // 代码中增加这样一行?
......

return 0;
} 25
BeihangSoft.cn
2.3 数据输入输出简介
 数据的 I/O (Input/Output) 并不是C语言
的组成部分。 int a;
 标准库函数提供相应的 I/O 操作,常用的 double x;
是两个函数: scanf( ), printf( ) scanf("%d", &a);
scanf("%lf", &x);
 标准输入函数:scanf, 其函数原型为
int scanf(char *format, …); 【例 scanf("%d %d", &a, &b); 】
转换控制字符 输入形式 对应参数类型 输入实例 备注
%d 十进制整数形式 int +123
%x 十六进制整数形式 int 8C
%c 一个字符 char x
%s 一个字符串(以空格分隔) 字符数组或字符指针 hello123 yes yes不会被输入
%f 小数形式 float -1.23
%lf 小数形式 double -1.23

26
BeihangSoft.cn
数据输入输出
 标准输入函数:scanf, 其函数原型为
int scanf(char *format, …); 【例 scanf("%d %d", &a, &b); 】
 format格式控制串是一字符串,其 …
中的转换控制字符(以%开始)决 int x, y, z, i;
定了其他参数(输入数据)的个数
和输入格式。 i = scanf("%d %d,%d", &x, &y, &z);
 其它字符要必须原样输入。scanf
会跳过输入数据中的空格符、制表 printf("%d\n", i); printf("%d\n", x);
符、换行符等空格符,从与该字段 printf("%d\n", y); printf("%d\n", z);
说明项匹配的数据起始点开始读入 …
数据并进行规定格式的转换。
I/O?
 scanf( )函数返回成功赋值的数据项 5
数,读到文件末尾而没有数据时返 5 6,7 567 6,7
回 EOF ( -1 )。 3 2 3
5 5 5
6 6 6
7 4200704 7
27
BeihangSoft.cn
数据输入输出--评测机的输入原理说明
 scanf( )函数返回成功赋值的数据项数,读到文件末尾而没有数据时返回
EOF ( -1 )。

【例c2-2.c】a+b回顾。 #include <stdio.h>

单组数据输入: int main()


输入:一行,分别为整数 a 和 b(空格分开)。 {
int a, b;
输出:一个数,表示a+b的值。
int sum;

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


输入样例:
sum = a + b;
12
printf("%d \n", sum);
输出样例:
3 return 0;
思考 }
多组数据计算,该怎么办?
28
BeihangSoft.cn
数据输入输出--评测机的输入原理说明
scanf( )函数返回成功赋值的数据项数,读到文件末尾而没有数据时返回
EOF ( -1 )。
// c2-3aplusb-M.c
【例c2-3.c】a+b进阶。多次计算! #include <stdio.h>
多组数据输入:
int main()
输入:多组数据,每组一行,分别为整数 {
a 和 b(空格分开)。 int a, b;
int sum;
输出:对每行输入,输出为一个数,表示 while(scanf("%d%d", &a,&b)!=EOF)
该输入行的和。 {
sum = a + b;
输入样例: printf("%d\n",sum);
IDE下运行时,多组数据
12 输入结束按键 ctrl+Z。
34 }
或,输入重定向命令 ……
输出样例: return 0;
3 }
7 29
BeihangSoft.cn
数据输入输出--评测机的输入原理说明
多组数据项,读到文件末尾而没有数据时返回 EOF ( -1 )。(输入重定向指令)
// c2-3aplusb-M.c
#include <stdio.h>
int main(){
int a, b; int sum;
while(scanf("%d%d", &a,&b) != EOF) {
sum = a + b;
printf("%d\n", sum);

}
return 0;
}

30
BeihangSoft.cn
类型转换与输出类型格式
scanf( )函数返回成功赋值的数据项数,读到文件末尾而没有数据时返回
EOF ( -1 )。
// c2-3aplusb-M.c
【例c2-3.c】a+b进阶。多次计算! #include <stdio.h>
多组数据输入
int main()
输入:多组数据,每组一行,分别为整 {
数 a 和 b(空格分开)。 int a, b;
int sum;
输出:对每行输入,输出为一个数,表 while(scanf("%d%d", &a,&b)!=EOF)
示该输入行的和。 {
sum = a + b;
输入样例: 思考 printf("%d\n",sum);
12 不改变a和b的类型,
34 还要扩展求和的范围, }
输出样例: 该怎么办? return 0;
3 }
7 31
BeihangSoft.cn
类型转换与输出类型格式
 scanf( )函数返回成功赋值的数据项数,读到文件末尾而没有数据时返回
EOF ( -1 )。
#include <stdio.h>
【例c2-3.c】a+b进阶。多次计算!
int main()
多组数据输入
{
输入:多组数据,每组一行,分别为整数 a
和 b(空格分开)。
int a, b;
long long sum;
输出:对每行输入,输出为一个数,表示该 while(scanf("%d%d", &a,&b)!=EOF)
输入行的和。 {
sum = (long long) a + b;
输入样例: printf("%lld\n",sum);
12
1000000000 }
2000000000 return 0;
输出样例: }
3
3000000000
32
BeihangSoft.cn
数据输入输出

 标准输出函数:printf, 其函数原型为
int printf(char *format, …); 【例 printf("%d\n%d\n", a, b); 】
转换控制字符 输出形式 对应参数类型 输入实例 备注
%d 有符号的十进制整数形式 int 123
%x 十六进制整数形式 int 8C
%c 一个字符 char, int x
%s 一个字符串(以空格分隔) 字 符 数 组 或 字 hello123 yes "…"中的…被输出
符指针
%f 小数形式 double -1.23 没有特定的float输出
%e 小数形式(科学计数表示) double -1.23e-3 0.00123

在控制字符前还可以加数字,如:
%-4d :输出最小域宽为4个字符的整数,左对齐(右边如有富裕补空格)。
%6.2f :输出最小域宽为6个字符的浮点数,并且小数点占两位。
BeihangSoft.cn
数据输入输出实例

输出域宽和
屏幕输出?
实际输出长度

double y = 3.14159265;
printf("%6.2f", y);
3.14
域宽为六个字符,输出数据若小于输
出域宽,则右对齐输出,其它部分填
空格;若输出数据长度多于给定域宽
,则按实际数据输出。
34
BeihangSoft.cn
数据输入输出常见问题
 如何同时输出多个数据?
int x=2;
int y=3; 输出结果: 2 + 3 = 5
printf("%d + %d = %d\n", x, y, x+y);

 如何同时输入多个数据? 输入多个数据时,
用空格 或回车换行
分隔,但在格式字
int n; 符串中不用给出空
格或回车换行符。
float r;
scanf("%d%f ", &n, &r );
5
5 6.6 6.6
35
BeihangSoft.cn
数据输入输出常见问题 必须原样
输入非转换
字符
float r;
输入例子:
scanf("r=%f", &r ); r=3.14
(必须原样输入r=,然后3.14,
数字将被读入到变量 r中)
double r;
💡💡 编程提示
scanf("%f", &r ); • 输入分隔符包含其它字
符时,应给出足够提示
scanf("%lf", &r ); 以确保正确输入。
• 熟记常用数据类型的格
式字符。
36
BeihangSoft.cn
数据输入输出常见问题

【例c2-2.c】a+b回顾。
输入格式控制串中含有空白
#include <stdio.h> 字符(如空格、\n或\t)

int main()
{ 回车换行后无法
int a, b; 读入数据!!!
int sum; 最后不要有 \n !
(先记住就好了)
scanf("%d%d\n", &a, &b);
//scanf("%d%d", &a, &b);
sum = a + b; 💡💡 编程提示
printf("%d \n", sum);
• scanf中不使用\n。
return 0;
}
37
BeihangSoft.cn
数据输入输出小结
 标准输入函数:scanf, 其函数原型为
int scanf(char *format, …); 【例 scanf("%d %d", &a, &b); 】
 标准输出函数:printf, 其函数原型为
int printf(char *format, …); 【例 printf("%d\n%d\n", a, b); 】
 scanf( )和printf( ) 都有返回值,但printf返回值通常舍弃不用。
 一个有用的输入返回值利用情况:while ( scanf(…) == ?) {…}


int x, y, z, i; I/O?
5 6,7 567
i = scanf("%d %d,%d", &x, &y, &z); 3 2
5 5
printf("%d\n", i); printf("%d\n", x); 6 6
printf("%d\n", y); printf("%d\n", z); 7 4200704

38
BeihangSoft.cn
2.4 算术表达式与算术运算符
 算术表达式(arithmetic expression):由操作符和操作数构成
的具有计算结果的表达式
 操作数 (operand): 数字常量 或 变量

 操作符 (operator): + - * / … int a, b;


 例如:1 + 2, s + 3, a * b
float sum;
scanf("%d%d", &a, &b);
sum = a / b;

 算术表达式的结果是有数据类型的,由其操作数的类型决定。
如果操作数类型不同,则需要类型转换。例如:
 1.0 + 1 (1自动转变为1.0,结果为2.0,double型)

 2 / 3 (2和3均为int型,结果也为int型,值为0)
 2.0f / 3 (3自动转变为3.0f,结果为0.666667f,float型)

 2 / 3 * 1.0 = ?

39
BeihangSoft.cn
2.4 算术表达式与算术运算符
【例c2-4.c】求圆的面积和周长。 常见算术运算符

// to calculate the circle's area and perimeter C操作 算术运算符 代数表达式 C表达式
#include <stdio.h> 加 + b+8 b+8
const double PI = 3.141592653589; 减 - f-h f-h
int main() 乘 * ab a*b
{ 除 / a/b 或 a÷b a/b
double radius, area, perimeter; 求模 % r mod s r%s

scanf("%lf", &radius);  二元运算符的概念:运算符取两个操作数


(常量、变量;表达式、函数;括号等),
area = PI * radius * radius; 如:a * (b+c)
perimeter = 2 * radius * PI;  直线形式的输入:C/C++编译器中不接受
代数符号,如 a+b+c ,应该表达为
printf("Radius = %6.2f\n", radius); (a+b+c)/3
3
printf("Area = %6.2f\n", area);
printf("Perimeter = %6.2f\n", perimeter);  运算符优先级:z = p * r % q + w / x – y;
1  括号的使用(“多余”的括号有时并不多
return 0; Radius = 1.00 余!),如:
} Area = 3.14 d = (a * (b + c)) + (c * (d + e));
Perimeter = 6.28
BeihangSoft.cn
算术运算实例:求圆的面积和周长(漂亮的输出格式)
// c2-4a_circle
#include <stdio.h>
const double PI = 3.141592653589;
int main()
{
double radius, area, perimeter;

scanf("%lf", &radius);

area = PI * radius * radius;


perimeter = 2 * radius * PI;

printf("Radius = %6.2f\n", radius);


printf("Area = %6.2f\n", area);
printf("Perimeter = %6.2f\n\n", perimeter);

printf("Radius = %6.2f\n", radius);


printf("Area = %6.2f\n", area);
printf("Perimeter = %6.2f\n\n", perimeter);

printf(" Radius = %6.2f\n", radius);


printf(" Area = %6.2f\n", area);
printf("Perimeter = %6.2f\n\n", perimeter);

printf("%12s = %6.2f\n", "Radius", radius);


printf("%12s = %6.2f\n", "area", area);
printf("%12s = %6.2f\n\n", "perimeter", perimeter);

printf("%-12s = %6.2f\n", "Radius", radius);


printf("%-12s = %6.2f\n", "area", area);
printf("%-12s = %6.2f\n", "perimeter", perimeter);

return 0;
} 41
BeihangSoft.cn
算术运算实例:求某天是星期几
【例c2-5.c】已知某月x日是星期y,该月有n天,求下一个月的
k日是星期几?
// file: c2-5-1_weekday.c
#include <stdio.h> 题目分析:
int main()
{ 用0~6表示周日至周六,则下一
short x, y, n, k, m;
个月的k日是星期几m可表示为
/* we choose 2019/3/5, Tuesday*/
x = 5; y = 2; n = 31; m = (n -x +k +y)%7
printf("day of next month: ");
scanf("%d", &k);

m = (n -x +k +y)%7;

printf("the weekday is: %d\n", m);

return 0;
} 42
BeihangSoft.cn
算术运算实例:一元二次方程求根
【例c2-6.c】已知一元二次方程 ax2 + bx +c = 0 的系数a, b, c,
求方程的根?
题目分析:根据求根公式 //// file: c2-6_solve_equation.c
#include <stdio.h>
#include <math.h>

int main()
math.h :标准头文件,其中定义了 {
若干(数学)标准库函数。 double a = 1, b = 6, c = 5, r1, r2;

double sqrt(double )标准库函数 r1 = (-b + sqrt(b*b - 4*a*c)) / (2*a);


math.h中定义的求开方函数。 r2 = (-b - sqrt(b*b - 4*a*c)) / (2*a);

printf("r1: %f, r2: %f\n", r1, r2);


思考
b2 - 4ac < 0 时,该程序无法求解? return 0;
}

43
BeihangSoft.cn
算术表达式与算术运算符 --自增和自减运算符
 C提供自增++(变量递增1)运算,用于取代赋值运算,如 a = a + 1 (或 a += 1)
 同样也提供自减--(变量递减1)运算
 自增++和自减--运算符可放在变量的前面也可放在变量后面
运算符 名称 示例表达式 说明
++ 前置自增 ++a 将a加1,然后在a出现的表达式中使用新值
++ 后置自增 a++ 在a出现的表达式中使用当前值,然后将a加1
-- 前置自减 --a 将a减1,然后在a出现的表达式中使用新值
-- 后置自减 a-- 在a出现的表达式中使用当前值,然后将a减1
int main() 注意:在单独一条语句中,前置自
{ 增(减)与后置自增(减)是相同
自增和自减运算 int i = 1, j = 2 的,但在表达式中两者有差别。如
通常在循环语句 int m = 5 , n = 6; a++;  ++a;  a = a + 1;
中控制条件变量 int u, v, x, y;
的改变。 u = i++; // u is ?, i is ? c = a++; c = ++a;
v = ++j; // v is ?, j is ?  
while(i <= n){ c = a; a = a + 1;
x = m--; // x is ?, m is ?
…… a = a + 1; c = a;
y = --n; // y is ?, n is ?
i++;
...
} } 44
BeihangSoft.cn
复合赋值运算符
 对一个变量的值在其原有值基础上修改时,赋值运算符可以缩写成赋
值表达式,如
a += 5 等价于 a = a + 5 , x *= y + 5 等价于 x = x * (y + 5)
 其它二元运算符均可写成类似的形式,即
(v) = (v) op (expression) 可写为 (v) op= (expression)
赋值运算符 示例表达式 说明 赋值 使用赋值运算符可
假设:int c = 3, d = 5, e = 4, f = 6, g = 12; 以使程序员更快地
+= c += 7 c=c+7 10赋值给c 编写程序(精炼程
-= d -= 4 d=d-4 1 赋值给d 序),也可以使编
*= e *= 5 e=e*5 20赋值给e 译器更快地编译程
/= f /=3 f=f/3 2 赋值给f 序(提高编译效
%= g %=9 g=g%9 3赋值给g 率)。

 赋值运算符: += , -=, /= , %= , *= , >>= , <<= , &= , ^= , |=


 注意:y *= n+1; 等价于 y = y*(n+1); 而不是y = y*n+1;
45
BeihangSoft.cn
算术表达式与算术运算符小结
常见算术运算符 复合赋值运算符
C操作 算术运算符 代数式 C表达式 赋值运算符 示例表达式 说明
加 + b+8 b+8 += c += 7 c=c+7
减 - f-h f-h -= d -= 4 d=d-4
乘 * ab a*b *= e *= 5 e=e*5
除 / a/b 或 a÷b a/b /= f /=3 f=f/3
求模 % r mod s r%s %= g %=9 g=g%9

自增和自减运算符
运算符 名称 示例表达式 说明
++ 前置自增 ++a 将a加1,然后在a出现的表达式中使用新值
++ 后置自增 a++ 在a出现的表达式中使用当前值,然后将a加1
-- 前置自减 --a 将a减1,然后在a出现的表达式中使用新值
-- 后置自减 a-- 在a出现的表达式中使用当前值,然后将a减1

46
BeihangSoft.cn
2.5 类型转换
…  各个输出分别是什么?
char c = '1'; // '1' is 49, or 0x31
int a = 1, b = 8; double d = 1;
 C语言类型转换通常是自动的---
unsigned u;
a = c;
隐式(自动)类型转换
printf("%d\n", a); 1. 字符与整数:可以用整数的地
a = 60 + 4*50 - 3/2.0; 方就可以用字符。整数转换成
printf("%d\n", a); 字符时,超出8位就将高位丢掉。
d = (3+2)*(7-2)/4; 2. 浮点数与整数
printf("%f\n", d); 输出
c = a;
printf("%d\n", c);
3. 无符号整数:普通整数(int)
d = (double) (b/5);
和无符号整数(unsigned)混
printf("%f\n", d);
d = (double) (b)/5; 合使用,则普通整数转换成无
printf("%f\n", d); 符号整数。

47
BeihangSoft.cn
类型转换(续)
…  C语言类型转换通常是自动的--- 隐
char c = '1'; // '1' is 49, or 0x31 式(自动)类型转换
int a = 1, b = 8; double d = 1;
4. 算术转换:如果一个运算符,有不
a = c;
同类型的运算对象,那么“较低”
printf("%d\n", a); 类型会自动转换成“较高”类型。
a = 60 + 4*50 - 3/2.0; 输出
printf("%d\n", a);
d = (3+2)*(7-2)/4;
printf("%f\n", d);
c = a;
printf("%d\n", c);

d = (double) (b/5);
printf("%f\n", d);
d = (double) (b)/5; 5. 赋值号右边表达式的类型会自动转
printf("%f\n", d); 换为赋值号左边变量类型。

48
BeihangSoft.cn
基本类型数据的“高低”层次关系

Data types
long double
double
float
unsigned long int (synonymous with unsigned long)
long int (synonymous with long)
unsigned int (synonymous with unsigned)
int
unsigned short int (synonymous with unsigned short)
short int (synonymous with short)
unsigned char
char

当发生由“较高精度类型数据” 转换到“较低精度类型
数据” 时,大多数编译器会产生一个警告,因为发生了
可能的精度损失
49
BeihangSoft.cn
类型转换:强制类型转换
…  强制类型转换(cast)
char c = '1'; // '1' is 49, or 0x31 --- 显式类型转换
int a = 1, b = 8; double d = 1;
#include <stdio.h>
a = c; const double DELTA=1e-9;
printf("%d\n", a); int main( )
a = 60 + 4*50 - 3/2.0; { int x,y;
printf("%d\n", a); double f=0.0006;
d = (3+2)*(7-2)/4;
printf("%f\n", d); x=(int)(f*10000);
c = a; 输出 printf("%d\n", x);
输出?
5
printf("%d\n", c);
y=(int)((f+DELTA)*10000);
printf("%d\n", y);
6
d = (double) (b/5);
printf("%f\n", d); return 0;
d = (double) (b)/5;
printf("%f\n", d);
} ?

50
BeihangSoft.cn
类型转换(续)
 强制类型转换常用来进行浮点数的整数和小数分离

int int_part;
double x = 2018.321, decimal_part;
int_part = (int) x; // 获取x的整数部分
decimal_part = x – (int) x; // 获取x的小数部分

 强制类型转换可抑制编译系统在精度损失时发出告
警信息(我就是要这样做,请不要提醒我!)。
 【 *例2-7】时钟指针
讨论题
51
BeihangSoft.cn
类型转换的注意事项
 混合类型表达式中的升 …
char c = '1'; // '1' is 49, or 0x31
级规则 int a = 1, b = 8; double d = 1;

混合类型表达式中的每 a = c;
个值的类型会升级为此 printf("%d\n", a);
a = c + 4*50 - 3/2.0;
表达式中的“最高”类 printf("%d\n", a);
型(实际上创建了此表 d = (3+2)*(7-2)/4;
printf("%f\n", d);
达式中每个值的临时值 c = a;
并用于表达式中,原来 printf("%d\n", c);

的值不变) d = (double) (b/5);


printf("%f\n", d);
d = (double) (b)/5;
printf("%f\n", d);
52

BeihangSoft.cn
例:c1-8.c成绩平均分(续)
输入:
【例c2-7.c】输入多个 #include <stdio.h> 31
成绩(有效成绩0~100, int main(){ 42
输入-1结束),求平 int score = 0, n = 0; 51
均分(保留小数点后 float sum = 0.; 62
-1
两位)。
scanf("%d", &score); 输出:
186.00/4 = 46.50
while(score != -1) {
隐式(自动)类型转换 sum += score; // sum = sum + score;
n++;
scanf("%d", &score);
💡💡 编程提示 }
修改程序时,若变量类 if(n > 0)
型有变,注意对应输入 printf("%.2f/%d = %.2f", sum, n, sum/n);
输出的修改。 return 0;
} 53
BeihangSoft.cn
2.6 关系运算符与逻辑运算符
if(expression)是
 程序中对不同分支的执行取决于给定的
一个选择语句。 条件

 C语言中的条件由逻辑表达式来描述。
if(score >= 80 && score < 90)
逻辑表达式可以是一个关系表达式(由
printf("成绩:良"); 关系运算符描述),也可以是由逻辑运
算符连接起来的多个关系表达式
…  表达式产生确定的值,结果为0或1 (非0)
例:设 int x = 1;
 关系运算符:>, <, >=, <=, ==, != ?
(5 >= 3) || ( x == 5)
 逻辑运算符:与 &&, 或 ||, 非 ! (2 == 3) && ( x >= 7) ?

&& A || A
T F T F
A T F
T T F T T T
B B
F F F F T F !A F T

电路的串并联? 开关切换?
54
BeihangSoft.cn
关系运算符与逻辑运算符

 关系运算符:>, <, >=, <=, ==, != 注意:1. 在C89中,没有定


义Bool(布尔)类型,它用
 逻辑运算符:与 && , 或 || , 非 ! 非0值表示真(True),用0
表示假(False),都占4字
节。因此,在C中,任何一
例:设 int x = 1;
个表达式都可作为条件。
(x == 5) || (5 >= 3) 值为 1(该1占4字节) 2. C编译器在给出逻辑运算
结果时,以数值1代表真,
(2 == 3) && ( x >= 7) 值为 0(该0占4字节) 以数值0代表假。

A && B 若A为0(假),则B不必求值,结果一定为0(假)。
A || B 若A为非0(真),则B不必求值,结果一定为非0(真)。

如上逻辑表达式的这一重要性质也称为“短路求值”,在程序设计中经常会用到。
如在输入数据进行处理时,经常用如下的表达式:
char c;
if( ( ( c = getchar( ) ) != EOF) && (c >= 'a') && (c <= 'z') ) {…}

55
BeihangSoft.cn
逻辑表达式实例

 判断整型变量n的值为一个0到10之间的值:
(0 <= n && n <= 10) 注意:不能写为 (0 <= n <= 10)
不能得到预期结果
(该表达式是一个合法的逻辑表达式,测
试一下其值为多少?)
int n = 2; printf("%d", 0 <= n <= 10);
 判断字符变量c是字母:
((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))

 判断某年是平年还是闰年(闰年为能被4整除但不能
被100整除,或能被400整除):
(( y%4 == 0) && (y%100 != 0 )) || (y%400 == 0)

56
BeihangSoft.cn
实际应用中逻辑表达式
【例c2-8.c】输入一个三位整数x,判断x是否为水仙花数,如果是,则输出该
数是水仙花数。(水仙花数:一个三位数,其各位数字的立方之和等于该数,
如153是水仙花数,因为 153 = 13 + 53 +33)。
// c3-2_daffodil_number.c
#include <stdio.h>

int main()
{ 第一次运行程序,IO为:
short x, a, b, c;
Input a three-bits-integer: 123
printf("Input a three-bits-integer: "); 123 is not a daffodil number
scanf("%d", &x);

a = x/100; b = (x%100)/10; c = x%10;


第二次运行程序,IO为:
if(x == a*a*a + b*b*b + c*c*c){
printf("%d is a daffodil number\n", x); Input a three-bits-integer: 153
return 0; 153 is a daffodil number
}

printf("%d is not a daffodil number\n", x);


return 0;
}
BeihangSoft.cn
实际应用中逻辑表达式
【例c2-9.c】名次预测 有人在赛前预测A~F六名选手在比赛中会按顺序分
获第1名到第6名,如果他在这一预测中刚好猜对了三人的名次,则输出他
是一个正常的人(不是小笨,也不是天才)。
// c3-3_guess_ranking.c 运行程序,IO为:
#include <stdio.h>
The actual ranking of sporters :
A: 1
int main()
{ B: 2
int a, b, c, d, e, f; C: 5
D: 4
printf("The actual ranking of sporters :\n"); E: 6
printf("A: "); scanf("%d", &a); F: 3
printf("B: "); scanf("%d", &b); Got it! U r a normal person.
printf("C: "); scanf("%d", &c);
printf("D: "); scanf("%d", &d); 这里充分利用了逻辑表达式的真值等于1这个特点。如
printf("E: "); scanf("%d", &e); 果用穷举(枚举)方法,逐一枚举上述预测中只有3项
printf("F: "); scanf("%d", &f); 正确的所有可能组合,则逻辑表达式应为:
( (a == 1) && (b == 2) && (c == 3) &&
if( (a == 1) + (b == 2) + (c == 3) + (d != 4) && (e != 5) && (f != 6) ) ||
(d == 4) + (e == 5) + (f == 6) == 3 )
( (a == 1) && (b == 2) && (c != 3) &&
printf("Got it! U r a normal person.\n");
(d == 4) && (e != 5) && (f != 6) ) ||
return 0; (…) || (…) || …
} 这里由或连接起来“与表达式”有 =20项,复杂!
BeihangSoft.cn
实际应用中逻辑表达式
【例c2-9.c】名次预测 有人在赛前预测A~F六名选手在比赛中会按顺序分
获第1名到第6名,如果他在这一预测中刚好猜对了三人的名次,则输出他
是一个正常的人(不是小笨,也不是天才)。
扩展问题:
1. 猜对了4人,是个一个正常的人。程序怎么写?
2. 输入每个选手的实际名次,根据猜对的个数,分别判断
幸运指数(蒙力指数)。如
输入:
134562
123456
输出:
*
******

59
BeihangSoft.cn
实际应用中逻辑表达式
 自然语言描述的条件转换为逻辑表达式通常不唯一,如:
 a不大于b: (a <= b) , 也可以为 !(a >b)
 a不等于b: (a != b) , 也可以为 !(a == b)
 x不大于a且不大于不b:
x <= a && x <= b
也可以为 !(x > a) && !(x > b)
还可以为 !( (x > a) || (x > b) )
(德.摩根定理,亦称反演律)

60
BeihangSoft.cn
*2.7 运算符的优先级
一些基本的优先级规则:
 先乘除(模),后加减
 关系运算优于逻辑运算
 括号优先
 ……

x = a - b * c;

if(score >= 80 && score < 90)


{ …… }
提示:善用小括号 ( )
char c;
if( ( ( c = getchar( ) ) != EOF) && (c >= 'a') && (c <= 'z') ) {…}

61
BeihangSoft.cn
*2.7 运算符的优先级(有些还没有学过)
优先级 运算符 名称或含义 使用形式 结合方向 说明
后置++ 后置自增运算符 变量名++
后置-- 后置自减运算符 变量名--
[] 数组下标 数组名[整型表达式]
1 () 圆括号 (表达式)/函数名(形参表) 左到右

. 成员选择(对象) 对象.成员名
-> 成员选择(指针) 对象指针->成员名
- 负号运算符 -表达式 单目运算符
(类型) 强制类型转换 (数据类型)表达式
前置++ 前置自增运算符 ++变量名 单目运算符
前置-- 前置自减运算符 --变量名 单目运算符

2 * 取值运算符 *指针表达式 右到左 单目运算符


& 取地址运算符 &左值表达式 单目运算符
! 逻辑非运算符 !表达式 单目运算符
~ 按位取反运算符 ~表达式 单目运算符
sizeof 长度运算符 sizeof 表达式/sizeof(类型)

/ 除 表达式/表达式 双目运算符

3 * 乘 表达式*表达式 左到右 双目运算符


% 余数(取模) 整型表达式%整型表达式 双目运算符
BeihangSoft.cn
*运算符的优先级(有些还没有学过)
优先级 运算符 名称或含义 使用形式 结合方向 说明
+ 加 表达式+表达式 双目运算符
4 左到右
- 减 表达式-表达式 双目运算符
<< 左移 表达式<<表达式 双目运算符
5 左到右
>> 右移 表达式>>表达式 双目运算符
> 大于 表达式>表达式 双目运算符
>= 大于等于 表达式>=表达式 双目运算符
6 左到右
< 小于 表达式<表达式 双目运算符
<= 小于等于 表达式<=表达式 双目运算符
== 等于 表达式==表达式 双目运算符
7 左到右
!= 不等于 表达式!= 表达式 双目运算符
8 & 按位与 整型表达式&整型表达式 左到右 双目运算符

9 ^ 按位异或 整型表达式^整型表达式 左到右 双目运算符

10 | 按位或 整型表达式|整型表达式 左到右 双目运算符


11 && 逻辑与 表达式&&表达式 左到右 双目运算符
12 || 逻辑或 表达式||表达式 左到右 双目运算符
13 ?: 条件运算符 表达式1? 表达式2: 表达式3 右到左 三目运算符

63
BeihangSoft.cn
*运算符的优先级(有些还没有学过)
优先级 运算符 名称或含义 使用形式 结合方向 说明
= 赋值运算符 变量=表达式
/= 除后赋值 变量/=表达式
*= 乘后赋值 变量*=表达式
%= 取模后赋值 变量%=表达式
+= 加后赋值 变量+=表达式
14 -= 减后赋值 变量-=表达式 右到左
<<= 左移后赋值 变量<<=表达式
>>= 右移后赋值 变量>>=表达式
&= 按位与后赋值 变量&=表达式
^= 按位异或后赋值 变量^=表达式
|= 按位或后赋值 变量|=表达式
15 , 逗号运算符 表达式,表达式,… 左到右 从左向右顺序运算

这么多!怎么记忆?

1. 读一遍,能记住多少就记多少。
2. 使用的时候,按常识和感觉,相信自己的直觉。
3. 加括号。
4. 不理它,天天坚持编程(模仿书上的例程),很快,不知为何,就都会了。
64
BeihangSoft.cn
*运算符的优先级(有些还没有学过)
 优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最
低的优先级
 相同优先级中,按结合顺序计算。大多数运算是从左至右计算,只有三个
优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符
 基本的优先级需要记住:
 指针最优。单目运算优于双目运算,如正负号。

 先乘除(模),后加减。

 逻辑运算最后计算。

 很多优先级是比较显然的。记住一些常用运算的优先级。记不住怎么办?
提示:善用小括号 ( )

char c;
if( ( ( c = getchar( ) ) != EOF) && (c >= 'a') && (c <= 'z') ) {…}

65
2.8 一维数组简介
int i=0, a[12];

while(i<12)
int a[12]; {
表示定义一个包含12 个整数值的数组,名字为a。 a[i] = (i+1)*(i+1);
i++;
 数组名的命名规则与其他变量名相同。
}
 数组元素的标号从 0 开始(注意:不是 1)。
 数组中第一个元素称为数组元素0 (zeroth element),这样,数组a中
的元素:
第1个元素为a[0];第2个元素为a[1]; …… ;第 i 个元素为a[i-1]。
 要引用数组中的特定位置或元素,就要指定数组中的特定位置或元素
的位置号(position number)。
 方括号中位置号称为下标(subscript),下标应为整数或整型表达式。
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a[10] a[11]
BeihangSoft.cn
一维数组初始化与数组访问
 每一个数组元素的赋值和访问与单个变量一样
 数组赋值的一些方法
注意:不要将循环条件写为i<=6。这是
int a[6] = {1, 3, 5, -2, -4, 6};
初学者常犯的错误。
int b[6] = {1, 3};
int e[6]; int i=0, a[6];
 程序执行中进行赋值和访问
while(i<6){
 每一个数组元素的访问与单个变量一样
a[i] = (i+1)*(i+1);
 可以跟变量一样,定义不同类型的数组 i++;
int a[10]; }
double b[12]; i=0;
char c[128]; while(i<6)
…… { printf("%d\n", a[i]); i++; }
67
BeihangSoft.cn
应用实例:成绩平均分( 与c1-8.c进行对比分析)
【例c2-11.c】输入多人(少于200人)成绩(有效成绩0~100,输入-1结束),
求平均分(保留小数点后两位)并输出大于平均分的成绩。
#include <stdio.h> 输入:
int main() 76
if(n > 0) {
{ 82
ave = (float)sum/n;
int sum = 0, score[200]; 61
printf("%d/%d = %.2f\n",
float ave; 92
sum, n, ave);
int n = 0, i = 0 ; 50
while(i<n) {
-1
if((float)score[i]>ave)
scanf("%d", &score[0]); 输出:
printf("%d : %d\n",
361/5 = 72.20
i+1, score[i]); 1 : 76
while(score[n] != -1) {
i++; 2 : 82
sum += score[n];
} 4 : 92
n++;
}
scanf("%d", &score[n]);
return 0;
}
}
68
BeihangSoft.cn
应用实例:温度转换
【例c2-12.c】求摄氏温度℃转换为华氏温度℉(F = C*9/5 + 32)
数组的下标i和数组元素值CtoF[i]构成
#include <stdio.h> 了一个2列102行的表格(含表头)。 输出结果:
#define N 101 i是摄氏温度, CtoF[i]是华氏温度。 0 C = 32 F
1 C = 33 F
int main() i (℃) CtoF[i] (℉)
2 C = 35 F
{ 0 32 3 C = 37 F
int i=0, CtoF[N];
1 33 4 C = 39 F
… … 5 C = 41 F
while( i<N ) { 6 C = 42 F
CtoF[i] = i*9/5 + 32; 7 C = 44 F
printf("%3d C = %3d F\n", i, CtoF[i]); 8 C = 46 F
i++; 9 C = 48 F
10 C = 50 F
}
11 C = 51 F
return 0;

}
69
BeihangSoft.cn
2.9 常量的符号表示方法
 宏定义、const限定符【*】、枚举常量(后面再学)
 #define是编译预处理中的宏定义,定义一个符号和它所代表的字符串,编
译时这一符号被替换为该字符串。(EOF 就是 stdio.h 中定义的常量)
#include <stdio.h>
#define PI 3.14159
#define SEC_HOUR (60*60)
#define SEC_DAY (SEC_HOUR*24)
#define SUCCEED "test, Succeed!\n"

const double dPI = 3.141592653589;

int main()
{
int sec_oneweek = 7*SEC_DAY;
printf("Oneweek has %d seconds.\n\n", sec_oneweek);
 使用常量定义的好处:
double radius=1, area, perimeter;
area = PI * radius * radius;
 可提高程序的可
perimeter = 2 * radius * PI;
printf("Radius = %-6.2f, Area = %-6.2f, Perimeter = %-6.2f\n\n", radius, area, perimeter); 读性
radius=2;
area = dPI * radius * radius;
 程序的可移植性
perimeter = 2 * radius * dPI;
printf("Radius = %-12.6f, Area = %-12.6f, Perimeter = %-12.6f\n\n", radius, area, perimeter); 更好
printf(SUCCEED);
return 0;
 可维护性更好
}
70
BeihangSoft.cn
【**】const与#define
…  #define:宏定义,C的一种编译预处理指
#define arraySize 10 令。
// const int arraySize = 10;  在C语言源程序中允许用一个标识符来表
… 示一个字符串,称为“宏”。被定义为
int main() “宏”的标识符称为“宏名”。在编译
{ 预处理时,对程序中所有出现的“宏
int i=0, j=0, s[arraySize]; 名”,都用宏定义中的字符串去代换,
这称为“宏代换”或“宏展开”。宏定
whiel(i<arraySize)
义是由源程序中的宏定义命令完成的。
{ …… }
宏代换是由预处理程序自动完成的。
whiel(i<arraySize)  宏定义是纯粹的文字替换,不进行类型
{ …… } 检查。( 常见错误,#define PI 3.14; )
 带参数的宏,如
return 0;
} #define max(a, b) ((a) > (b) ? (a) : (b))

71
BeihangSoft.cn
【**】const与#define
…  const 定义的常数是变量,也带类型,存在
#define arraySize 10 于程序的数据段,并在堆栈中分配了空间。
// const int arraySize = 10; const常量是一个Run-Time的概念,它在程
序中确确实实地存在着,并可以被利用、

传递。const常量有数据类型。编译器可以
int main()
{ 对const常量进行类型的安全检查。
int i=0, j=0, s[arraySize];  #define 定义只是用来做文本的替换,当程
序进行编译的时候,编译器首先会将
whiel(i<arraySize) #define PI 3.14 以后所有代码中的 PI 全部
{ …… } 换成3.14,然后再进行编译,是在编译期预
处理阶段做的单纯文本替换
whiel(i<arraySize)
 网上查询,进一步学习 const与#define
{ …… }

return 0;
}
72
BeihangSoft.cn
2.10 标准库函数简介

标准输入/输出(Input/Output, I/O)
# include <stdio.h>
int main( )  标准输入(stdin, standard input)
{ 通常指键盘
int a, b, sum;  标准输出(stdout, standard output)
通常指屏幕显示器
scanf("%d%d", &a, &b);
在Windows等图形界面的操作系
sum = a+b; 统中,在控制台(console)编程
模式下,输入、输出信息一般
printf("sum = %d\n", sum); 被显示在一个窗口中,该窗口
称为控制台窗口。
return 0;
}
73
BeihangSoft.cn
标准库函数简介

#include <stdio.h>
 C语言的编译系统以标准库函 #include <math.h>
数的方式实现了大量常用的功 int main()
能。 {
 标准函数的函数原型在相应的 double a=3, b=4, c;
标准库头文件( *.h)中说明;
函数的定义以目标码的形式保 c = sqrt(a+b);
存在函数库中(用户使用时, printf("%.2f\n", c);
用#include 引用相应的.h文件, return 0;
编译时以编译选项的方式指明 }
需要链接的库函数)。
💡💡 编程提示
多多使用标准库函数。不必
“事无巨细”、“事必躬亲”。
74
BeihangSoft.cn
**标准库函数: I/O (include <stdio.h>)
 常用的I/O函数(主要文本的 I/O)(参阅Page94-95,表5-2 ~ 5-4)
函数原型 功能说明 备注
int getchar() 返回从标准输入文件中读入的一个字符 读到文件尾时返回EOF

int putchar(int c) 向标准输出文件中写入一个字符 函数出错时返回EOF


当读到文件尾部或函数出
从标准输入文件中读入的一行字符,并
char *gets(char *buf) 错时返回NULL,否则返回
将其保存在buf所指向的存储区
存储区buf
从指定文件中读入的一行不超过n-1个 当读到文件尾部或函数出
char *fgets(char *buf,
字符的字符串,并将其保存在buf所指 错时返回NULL,否则返回
int n,FILE *fp)
向的存储区 存储区buf
向标准输出文件中写入的一行字符,并
int puts(const char *string) 将字符末尾处的结束符'\0'替换成换行 函数出错时返回EOF
符'\n'
根据format中的格式规定从标准输入文 当读到文件尾部或函数出
int scanf(const char *format
件中读入数据,并保存到由argument指 错时返回EOF,否则返回
[,argument]...)
定的存储单元中 读入数据的个数
int printf(const char 根据format中的格式规定将argument指 返回输出的字符数,函数
*format [,argument]...) 定的数据写入标准输出文件中
75
出错时返回负值
BeihangSoft.cn
**标准库函数: 其他常用函数
 常用数学计算 ( include <math.h> )(参数和返回类
型都是double)
函数原型 函数功能 函数原型 函数功能
反正弦函数,x以弧
double sqrt(double x); x的平方根 double asin(double x);
度为单位
正弦函数,x以弧度为 反余弦函数,x以弧
double sin(double x); double acos(double x);
单位 度为单位
余弦函数,x以弧度为
double cos(double x); double log(double x); x的自然对数
单位
正切函数,x以弧度为
double tan(double x); double log10(double x); x的常用对数
单位
反正弦函数,返回值以
double atan(double x); double exp(double x); 指数函数ex
弧度为单位
反正弦函数,返回值以
double atan2(double
弧度为单位,根据x和y double fabs(double x); x的绝对值
y,double x);
的符号确定象限
76
BeihangSoft.cn
**标准库函数:数学库函数实例
【例c2-13.c】利用数学库函数计算 2 的 x 次方(x为整数)。

#include <stdio.h>
#include <math.h>

int main()
{
int x;
for( x = 1; x<=32; x++ ) // 还没有学for,先不理它!
printf("2^%d = %.0f\n", x, pow(2, x));
return 0;
}

77
BeihangSoft.cn
**标准库函数: 其他常用函数

 通用数据处理 ( include <stdlib.h> )


求整数绝对值、随机数、快速排序等
函数原型 函数功能 函数原型 函数功能

int abs(int n); n的绝对值 int rand(); 生成伪随机数

将s转换为double类型 void srand(unsigned


double atof(char *s); 设置随机数的种子
的数 int s);

int atoi(char *s); 将s转换为int类型的数 void exit(int status); 终止程序运行

void qsort(void
void *bsearch(void
以二分查找的方式在排 *base,size_t
*key,void *base,size_t 以快速排序方式对
序数组base中查找元素 num,size_t width,int
num,size_t width,int 数组base进行排序
key (*f)(void *e1, void
(*f)(void *e1, void *e2));
*e2));

78
BeihangSoft.cn
**标准库函数: 字符判断 (include <ctype.h>)
 字符类型判断函数(参阅P97,表5-5 ~ 5-6 ,并试着编写一些试用程序)
函数原型 函数功能 函数原型 函数功能
c是否是可打印字符
int isalnum(int c) c是否是字母或数字 int isprint(int c)
(0x20~0x7e)
c是否是符号,可打印但
int isalpha(int c) c是否是字母(a~z,A~Z) int ispunct(int c)
非字母数字
c是否是控制符 c是否是空白符
int iscntrl(int c) int isspace(int c)
(0x00~0xlf,0x7f) (0x09~0x0D,0x20)
int isdigital(int c) c是否是数字 int isupper(int c) c是否是大写字母(A~Z)
c是否是可打印字符(空格 c是否是16进制数字
int isgraph(int c) int isxdigit(int c)
除外) (0~9,a~f,A~F)
int islower(int c) c是否是小写字母(a~z)
isdigit() 0~9
isxdigit()
A~F,a~f
isgraph() isalpha()
isupper() A~Z
isprint() isalnum() islowwe() a~z
isdigit() 0~9
ispunct() !@#$%^&*()_-+=|\{}:;"'<>?/~`
空格符(' ',0x20)
isspace() 空格符(0x20),换页符('\f'),换行符('\n'),回车符('\r'),水平制表符('\t'),垂直制表符('\v')
iscntrl() 控制字符(0x00~0x1f,0x7f)
79
BeihangSoft.cn
**标准库函数: 字符串处理 (include <string.h>)

 字符串处理跟数组密切相关。

函数原型 函数功能 函数原型 函数功能

char *strcat(char *dst, int strcmp(char *s1, char


将src追加到dst之后 比较字符串s1和s2
char *src) *s2)

char *strncat(char *dst, 将src中的前n个字符追加 int strncmp(char *s1,char 比较字符串s1和s2的


char *src,size_t n) 到dst之后 *s2,size_t n) 前n个字符

char *strcpy(char *dst, char *strchr(char *str,int 在str中查找c首次出


将src复制到dst中
char *src) c) 现的位置

char *strncpy(char *dst, 将src中的前n个字符复制 char *strrchr(char *str, 在str中查找c最后一


char *src,size_t n) 到dst中 int c) 次出现的位置

char *strstr(char *str, 在str中查找s1首次出


size_t strlen(char *str) 返回字符串str的长度
char *s1) 现的位置

80
BeihangSoft.cn
*C89的标准库头文件

头文件 宏及函数的功能类别 头文件 宏及函数的功能类别

assert.h 运行时的断言检查 signal.h 事件信号处理

ctype.h 字符类型和映射 stdarg.h 变长参数表处理

errno.h 错误信息及处理 stddef.h 公用的宏和类型

float.h 对浮点数的限制 stdio.h 数据输入输出

limits.h 编译系统实现时的限制 stdlib.h 不属于其它类别的常用函数

locale.h 建立与修改本地环境 string.h 字符串处理

math.h 数学函数库 time.h 日期和时间

setjmp.h 非局部跳转

81
BeihangSoft.cn
*标准库函数小结
 复用:C标准库提供了丰富的函数集合,程序员直接调用这些函数可以
完成许多操作,而不必事事从原始的代码开始编起(继承前人的优秀成
果,减少软件开发工作量)。
 封装:不关心别人的程序(函数)的实现细节,了解接口即可。
 数学计算( #include <math.h> ) : pow(a,b), sin(x), sqrt(x), ..
 标准I/O ( #include <stdio.h> ) : scanf, printf, putchar, …
 字符串操作、系统资源访问、时间处理、错误检查、…

Computer 工欲善其事,
Company 必先利其器

常用标准库函数及头文
件参见附录E。或联机
手册。
82
BeihangSoft.cn
本讲小结
 了解C语言的基本数据类型,取值范围
 理解ASCII编码规则和使用方法
 熟练掌握变量的应用:变量的定义(命名规则并区分关键字) 、赋值、
使用
 熟练掌握+、-、*、/、%、++、--等的使用方法和计算表达式的值
 熟练掌握赋值运算、复合赋值运算
 熟练掌握关系运算、逻辑运算
 熟练掌握类型转换的规则及使用方法
 熟练掌握scanf、printf函数的功能与使用方法
 了解常量的符号表示形式、const与define的区别
 简单掌握一维数组的使用方法
 简单掌握库函数的使用方法

83
BeihangSoft.cn
第二讲 作业
 看书
 习题:all
 预习后面章节
 上机实践题
 把本课件和书上的所有例程输入计算机,运行并观察、分
析与体会输出结果。
 编程练习课后习题内容。

84
BeihangSoft.cn
课堂作业
【例c2-quiz1.c】对右侧程 #include <stdio.h>
序,以下输入的输出什么?
int main()
{
思考
int x, y, z, i;
输入1:4 5 6
i = scanf("%d %d,%d",&x, &y, &z);
输入2:4 5,6
printf("%d\n", i);
输入3:4.2 5.7,8.2
printf("%d\n", x);
输入4:5 a,6
printf("%d\n", y);
printf("%d\n", z);
return 0;
}
85
BeihangSoft.cn
课堂作业
【例c2-quiz2.c】 #include <stdio.h>
#include <math.h>
对右侧程序,会 #define PI 3.1415926
输出什么? int main()
{
int x = 4;
double angle = 45;

printf("\"Hell\x6f\"\12");

printf("%.2f^2 = %.2f\n", sqrt((double)x), (double)x);

printf("2^%d = %.2f\n", x, pow(2, x));

printf("sin(%.2f)=%.2f\n", angle, sin(angle*PI/180));

return 0;
} 86
课堂作业 #include <stdio.h>
int main() {
char c = '1'; /* '1' is 49, or 0x31*/
int a = 1, b = 8;
【例c2-quiz3.c】对右侧 double d = 1;
程序,会输出什么? a = c;
printf("%d\n", a);
a = 60 + 4*50 - 3/2.0;
printf("%d\n", a);
d = (3+2)*(7-2)/4;
printf("%f\n", d);
c = a;
printf("%d\n", c);

d = (double) (b/5);
printf("%f\n", d);
d = (double) (b)/5;
printf("%f\n", d);
return 0;
}
87
BeihangSoft.cn
本讲再补充:优秀程序员的编程习惯
// to calculate the circle's area and perimeter
优秀程序员应具备的一些素质
#include <stdio.h>
const double PI = 3.141592653589;  使用TAB (table) 键缩进或空格
int main()
{  { } 对齐
double radius, area, perimeter;
 有合适的空行和空格
scanf("%lf", &radius);

area = PI * radius * radius;


💡💡 编程提示
perimeter = 2 * radius * PI; • 现在的许多开发环境、编辑软
件都支持自动缩进:根据用户
printf("Radius = %6.2f\n", radius); 代码的输入,智能判断应该缩
printf("Area = %6.2f\n", area);
进还是反缩进,替用户完成调
printf("Perimeter = %6.2f\n", perimeter);
整缩进的工作。
return 0; • code blocks有自动整理格式功
} 能,在代码框里点右键,按
Format use Astyle。
88
BeihangSoft.cn
本讲再补充:优秀程序员的编程习惯
// to calculate the circle's area and perimeter
优秀程序员应具备的一些素质
#include <stdio.h>
const double PI = 3.141592653589;  使用有意义的变量名、文件名
int main()
{  不使用无意义的缩写
double radius, area, perimeter;
 习惯用小写字母,C/C++区分大
scanf("%lf", &radius);
小写
area = PI * radius * radius;
perimeter = 2 * radius * PI;
💡💡 编程提示
printf("Radius = %6.2f\n", radius); 使用命名法:
printf("Area = %6.2f\n", area);
printf("Perimeter = %6.2f\n", perimeter); • 匈牙利命名法
• 骆驼命名法和下划线法
return 0;
}
• 帕斯卡(pascal)命名法

89
BeihangSoft.cn
本讲再补充:优秀程序员的编程习惯
// to calculate the circle's area and perimeter
优秀程序员应具备的一些素质
#include <stdio.h>
const double PI = 3.141592653589;  有足够的注释
int main()
{
double radius, area, perimeter;
💡💡 编程提示
scanf("%lf", &radius);

area = PI * radius * radius; 代码千万行,


perimeter = 2 * radius * PI;

printf("Radius = %6.2f\n", radius);


注释第一行。
printf("Area = %6.2f\n", area);
printf("Perimeter = %6.2f\n", perimeter); 命名不规范,
return 0;
} 老师两行泪 。
90

You might also like