C语言学习 第2章 C语言与程序设计基础
第2章 C语言与程序设计基础
2.1 C语言基本符号与基本数据类型
程序是由字符组成的,每一种程序语言都规定了该语言所允许使用的字符集合。C语言使用的所有字符都是ASCII码字符集中的,它包括256个字符,每个字符都对应着一个不同的序号(码值)。
2.1.1 专用符号
常见的C语言专用符号如下:
符号 | 含义 | 符号 | 含义 |
---|---|---|---|
+ | 加法运算 | – | 自减运算 |
- | 减法运算,负号运算 | ’ | 字符常量开始或结束限定符 |
* | 乘法运算,指针运算 | " | 字符串常量开始或结束限定符 |
/ | 除法运算 | -> | 指向结构体成员运算符 |
% | 求余运算 | . | 结构体成员运算符 |
> | 大于 | ( | 参数或嵌套表达式开始标识符 |
< | 小于 | ) | 参数或嵌套表达式结束标识符 |
>= | 大于等于 | [ | 下标开始标识符 |
<= | 小于等于 | ] | 下标结束标识符 |
== | 等于 | { | 复合语句或函数体开始标识符 |
!= | 不等于 | } | 符合语句或函数体结束标识符 |
= | 赋值运算 | /* | 注释行开始标识符 |
& | 取地址运算,按位运算 | */ | 注释行结束标识符 |
&& | 逻辑与 | << | 左移运算 |
|| | 逻辑或 | >> | 右移运算 |
! | 逻辑非 | ^ | 按位异或运算 |
; | 语句分隔符 | | | 按位或运算 |
, | 参数、变量分隔符,逗号运算符 | ~ | 按位取反运算 |
++ | 自增运算 |
2.1.2 关键字
C语言关键字 | ||||
---|---|---|---|---|
auto | break | case | char | const |
continue | default | do | double | else |
enum | extern | float | for | goto |
if | int | long | register | return |
short | signed | sizeof | static | struct |
switch | typedef | union | unsigned | void |
volatile | while |
2.1.3 标识符
在程序中,常常用具有一定意义的名字来标识程序中的变量名、函数名和数组名,以便在程序中根据名字访问它,而程序中各种名字都是用标识符来表示的。C语言中关于标识符的使用规定如下:
(1)一个标识符是字母开头的字母和数字字符的一个连续序列,其中不得有空白字符,C语言特别规定下划线字符“_”也作为字母看待。
(2)标识符中同一字母的大小写是有区别的,即看做不同的字符。
(3)标识符不能与关键字同名。
2.1.4 分割符
C语言的分隔符主要有空格、逗号和分号。
C语言中单词与单词之间可以用一个或多个空格进行分隔,语句与语句之间用一个分号“;”进行分隔,逗号“,”则用于程序定义同类型变量之间、函数参数表中参数之间以及输入输出语句中各个参数之间的分隔。
2.1.5 数据类型
数
据
类
型
=
{
{
基
本
类
型
=
{
{
整
型
(
i
n
t
)
实
型
(
浮
点
型
)
=
{
{
单
精
度
型
(
f
l
o
a
t
)
双
精
度
型
(
d
o
u
b
l
e
)
字
符
型
(
c
h
a
r
)
构
造
类
型
=
{
{
数
组
类
型
枚
举
类
型
(
e
n
u
m
)
结
构
体
类
型
(
s
t
r
u
c
t
)
共
用
体
类
型
(
u
n
i
o
n
)
指
针
类
型
空
类
型
(
v
o
i
d
)
数据类型=\left\{ \begin{cases} 基本类型 =\left\{ \begin{cases} 整型(int)\\ 实型(浮点型)=\left\{ \begin{cases} 单精度型(float)\\ 双精度型(double) \end{cases} \right.\\ 字符型(char) \end{cases}\right.\\ 构造类型=\left\{ \begin{cases} 数组类型\\ 枚举类型(enum)\\ 结构体类型(struct)\\ 共用体类型(union) \end{cases} \right.\\ 指针类型\\ 空类型(void) \end{cases} \right.
数据类型=⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧基本类型=⎩⎪⎪⎪⎨⎪⎪⎪⎧⎩⎪⎪⎪⎨⎪⎪⎪⎧整型(int)实型(浮点型)={{单精度型(float)双精度型(double)字符型(char)构造类型=⎩⎪⎪⎪⎨⎪⎪⎪⎧⎩⎪⎪⎪⎨⎪⎪⎪⎧数组类型枚举类型(enum)结构体类型(struct)共用体类型(union)指针类型空类型(void)
基本类型的分类及特点
类型 | 类型标识符 | 字节 | 数值范围 |
---|---|---|---|
字符型 | char | 1 | -128~127 |
无符号字符型 | unsigned char | 1 | 0~255 |
整型 | int | 4 | -214783648~214783647 |
短整型 | short int | 2 | -32768~32767 |
长整型 | long int | 4 | -214783648~214783647 |
无符号型 | unsigned | 4 | 0~4294967295 |
无符号短整型 | unsigned short | 2 | 0~65535 |
无符号长整型 | unsigned long | 4 | 0~4294967295 |
单精度型 | float | 4 | -3.4×1038~3.4×1038 |
双精度型 | double | 8 | -3.4×10308~3.4×10308 |
长双精度型 | double | 8 | -3.4×10308~3.4×10308 |
2.2 常量
2.2.1 整型常量、实型常量及符号常量
- 整型常量
在C语言中整型常量有十进制、八进制和十六进制三种表示形式。
(1)十进制整型常量的表示与数学上的整数表示相同。十进制整型常量没有前缀,有0~9的数字组成。
(2)八进制整型常量是以0为前缀,后面跟由0~7的数字组成的八进制数。八进制数通常是无符号数。
(3)十六进制整型常量是以0x或0X为前缀,0x或0X中x或X的前面是数字0,其后跟由0~9、A~F或a~f的数字组成的十六进制数。
在程序中是根据常量的前缀来区分各种进制数的。因此,在书写常量时要避免因前缀弄错而造成结果的不正确。
整型常量中的长整型数据可用L(或l)做后缀表示。例如:
158L (十进制为158)
077L (十进制为63)
0XA5L (十进制为165)
整型常量中的无符号型数据可用U(或u)做后缀表示。例如:
358u 0x38Au 0235U 0XA5Lu 386LU - 实型常量
C语言中的实型常量只能用十进制形式表示,不能用八进制或十六进制表示。实型常量只有两种进制表示形式:小数形式和指数形式。
(1)小数形式由数字和小数点“.”组成(必须有小数点)。例如:
-1.85 .426 728. 0.345 0.0
都是十进制小数形式的实数,小数点前或后可以没有数字。
(2)指数形式由十进制数加阶码标志“e”或“E”以及阶码组成,其一般形式为:
aEn 或 aen
其中,a为十进制数,n为十进制整数(n为正数时“+”可以忽略),其值为a×10n。
以下是合法的实数:
1.234e+12 (等于1.234×1012)
3.7e-2 (等于3.7×10-2)
78E3 (等于78×103)
在阶码“e”或“E”前后必须有数字且“e”或“E”后的数字必须是整数。 - 符号常量
在程序中,可以定义一个符号来代表一个常量,这种相应的符号称为符号常量。符号常量实际上就是给值常量起一个名字。例如,用PI代表圆周率,即3.14159。
定义形式:
#define 符号常量名 常量
例如:
#define PI 3.14159
#define NUM 35
#define Name "Jin Wenjie"
注意,#define和#include一样是宏命令而不是C语言语句,故其命令行末尾不能加分号“;”。当程序被编译时,宏命令首先被编译预处理,即用符号常量名后面的常量来替换程序中所有出现的这个符号常量名。此外,符号常量一旦定义,就不能在程序中其他地方给这个符号常量再进行赋值。
2.2.2 字符常量与字符串常量
- 字符常量
用一对单引号“’’”括起来的一个字符,成为字符常量。字符常量在内存中存储的并不是字符本身,而是字符的代码,称之为ASCII码。如’a’的ASCII码是97,而’A’的ASCII码则是65。
除了以上形式的字符常量外,C语言还定义了一些特殊的字符常量,即以反斜杠字符“\”开头的字符序列,称为转义字符。转义字符是一种特殊的字符常量,即将“\”后的字符或字符序列,改变其字符原有的含义而转化为特定的含义,故称“转义”字符。例如转义字符’\n’不再表示字母“n”而作为“换行”符使用。
常用的转义字符如下表:
转义字符 | 含义 | 控制字符或字符 | ASCII代码 |
---|---|---|---|
\n | 换行,光标由当前位置移至下一行开头处 | NL(LF) | 10 |
\t | 水平位移,跳到下一个TAB位置(8个字符位置) | HT | 9 |
\b | 退格,使光标回退一个位置 | BS | 8 |
\r | 回车,光标由当前位置移至本行开头处 | CR | 13 |
\\ | 反斜杠字符“\” | \ | 92 |
’ | 单引号字符“’” | ’ | 39 |
" | 双引号字符“"” | " | 34 |
\0 | 空字符,通常作为字符串的结束标志 | NUL | 0 |
\ddd | ddd为1~3位八进制数 | ddd | |
\xhh | hh为1~2位十六进制数 | hh |
- 字符串常量
用一对双引号“""”括起来的字符序列称为字符串常量,例如,以下是合法的字符串常量:
“CHINA”
“This is a C Program.”
“1020376”
“*********”
" "
" "
“\n”
“ab”
由上例可知,字符串中可以是任意字符,包括转义字符,但字符串中出现双引号字符时则必须使用转义字符“\"”表示。
字符串常量在内存中存放时,系统仅存放双引号之间的字符序列;也即将这些字符按顺序以ASCII码值存放(包括空格符)。为了表示字符串的结束,系统自动在字符串的最后加上一个字符串结束标志,即转义字符’\0’(ASCII码值为0)。因此,长度为n个字符的字符串常量在内存中要占用n+1个字节的空间。例如,字符串“C program”的长度为9,但在内存中所占的字节数为10,其内存中的存储如下图:
再如,字符常量’A’与字符串常量"A"在内存中存储方式如下图:
字符常量与字符串常量的区别如下:
(1)定界符不同。字符常量使用单引号“’”,而字符串常量使用双引号“"”。
(2)长度不同。字符常量的长度恒定为1,而字符串常量的长度可以是0,也可以是某个整数。
(3)存储不同。字符常量存储的是字符的ASCII码值,而字符串常量除了要存储字符串中每个字符的ASCII码值外,最后还要存储字符串结束标志’\0’字符。
2.3 变量
2.3.1 整型变量
整型变量的基本类型符为int,可根据数值的范围将整型变量定义为基本整型变量、短整型变量或长整型变量:
(1)基本整型变量用int表示。
(2)短整型变量用short int表示,或用short表示。
(3)长整型变量用long int表示,或用long表示。
2.3.2 实型变量
实型数据与整型数据在内存中的存储方式完全不同,实型数据是按指数形式存放的。系统把一个实数分成小数部分和指数部分来分别存放。
实型变量分为单精度(float)、双精度(double)和长双精度(long double)三种。实型变量使用有限的内存单元进行存储的,因此存储实数的位数总是有限的。当实数表示的位数较多时,存放不下的后面那些数字将被舍去,由此会产生一些精度误差。
2.3.3 字符型变量
字符型变量用来存放字符常量,且只能存放一个字符。
2.4 运算符与表达式
2.4.1 C语言运算符的种类及功能
C语言的运算符十分丰富,应用也非常广泛,可以按运算功能和运算对象个数来进行分类。
(1)运算符按照功能分类。运算符可按其功能大致分为5类:算术运算符、关系运算符、逻辑运算符、位运算符和特殊运算符。
算术运算符 + - * / % ++ --
关系运算符 > >= < <= == !=
逻辑运算符 ! && ||
位运算符 << >> ~ | & ^
赋值运算符 = 复合赋值运算符(+= -= = /= %=)
条件运算符 ? :
逗号运算符 ,
指针运算符 &
求字节运算符 sizeof
强制类型转换运算符 (类型标识符)
分量运算符 . ->
下标运算符 [ ]
其他 如函数调用运算符()
(2)运算符按照其连接运算对象的个数分类。运算符可按其运算对象的多少氛围单目运算符、双目运算符和三目运算符。单目运算符的运算对象有1个,双目运算符两侧各有2个运算对象。
单目运算符
! ~ ++ -(取负运算) (指针运算) &(指针运算) sizeof(类型标识符)
双目运算符
+ - / % < <= > >= == != && || << >> &(位运算) | ^ ~ = 复合赋值运算符(+= -= *= /= %=)
三目运算符
? :
其它
( ) [ ] . ->
2.4.2 C语言运算符的优先级及结合性
优先级 | 运算符 | 含义 | 运算量个数 | 结合性 |
---|---|---|---|---|
1 | () [] -> . | 括号运算符 下标运算符 指定结构体成员运算符 成员运算符 | 自左至右 | |
2 | ! ~ ++、-- - (类型标识符) * & sizeof | 逻辑非运算符 按位取反运算符 自加、自减运算符 负号运算符 强制类型转换运算符 指针和地址运算符 取长度运算符 | 单目运算符 | 右结合 |
3 | *、/、% | 乘、除、求余运算符 | 双目运算符 | 自左至右 |
4 | +、- | 算数加、减运算符 | 双目运算符 | 自左至右 |
5 | <<、>> | 位左移、右移运算符 | 双目运算符 | 自左至右 |
6 | <、<=、>、>= | 关系运算符 | 双目运算符 | 自左至右 |
7 | ==、!= | 关系运算符 | 双目运算符 | 自左至右 |
8 | & | 按位与运算符 | 双目运算符 | 自左至右 |
9 | ^ | 位异或运算符 | 双目运算符 | 自左至右 |
10 | | | 位或运算符 | 双目运算符 | 自左至右 |
11 | && | 逻辑与运算符 | 双目运算符 | 自左至右 |
12 | || | 逻辑或运算符 | 双目运算符 | 自左至右 |
13 | ?: | 条件运算符 | 三目运算符 | 右结合 |
14 | =、+=、-=、*=、/=、%= <<=、>>=、&=、|=、^= | 组合算术运算符 组合位运算符 | 双目运算符 | 右结合 |
15 | , | 逗号运算符 | 自左至右 |
2.5 数据的输入/输出
数据的输入/输出是程序的基本功能,它是程序运行中与用户交互的基础。C语言没有自己的输入/输出语句,要实现数据的输入/输出功能,必须调用标准输入/输出库函数,而这些函数实在头文件“stdio.h”中定义的。因此,在使用标准输入/输出函数之前,要用预编译命令“#include”将头文件包含到源文件(程序)中。
使用预编译命令将标准输入/输出函数包含到源文件的格式如下:
#include<stdio.h>
或者:
#include "stdio.h"
2.5.1 字符输出函数
函数putchar的一般形式为:
putchar(ch);
函数putchar的作用是将一个字符输出到标准输出设备(通常指显示器)上,ch可以是一个字符变量或字符常量、整型变量或整型常量,也可以是转义字符。
例如:
char a='A';
int k=65;
putchar(a);
putchar(A);
putchar(k);
putchar(65);
putchar('\101');
都可以输出大写字母A。
2.5.2 字符输入函数
函数getchar的一般形式为:
getchar();
函数getchar的作用是从标准输入设备上(通常指键盘)读入一个字符。调用函数getchar不需要提供参数,调用该函数的返回值就是从输入设备得到字符的ASCII码值。
例如,输入并输出一个字符。
#include<stdio.h>
void main()
{
char c;
c = getchar(); /*从键盘上输入一个字符*/
putchar(c); /*将存入字符变量c中的字符输出到显示器上*/
putchar('\n'); /*输出一个换行符*/
}
2.5.3 格式输出函数
函数putchar仅能输出一个字符,当需要输出一个字符串或者是具有某种格式的数据时,就要使用格式输出函数printf了。printf的最后一个字母f即为“格式(format)”之意,也即按照用户指定的格式把数据或信息输出到标准设备显示器上。
函数printf的一般形式为:
printf("格式控制字符串",输出项列表);
其中格式控制字符串用于指定输出格式,它可以包含3类内容:
(1)普通字符:按字符原样输出。
(2)转义字符:按转义字符的含义输出。例如,’\n’表示换行,’\b’表示退格(光标回退一个字符位置)。
(3)格式字符:以%开始后更一个或几个规定的字符组成了格式字符。格式字符的作用有两项:其一是确定该格式字符在输出显示时所处的位置。其二是在格式控制字符串中按顺序出现的每个格式字符,依次对应输出项列表的每一个输出项,并且按格式字符指定的格式对输出项的值进行转换,然后取代格式字符输出在该格式字符所处的位置上。
输出项列表是由若干个用逗号分隔的输出项组成,每一个输出项可以是一个常量、变量或表达式。输出项的个数一般应与格式字符的个数相同,并且每个输出项的数据类型必须与所对应的格式字符指定的类型一致。如果输出项个数多于格式字符的个数,那么多余的输出项将不输出。
常用的格式字符功能表如下:
格式字符 | 输出(printf) | 输入(scanf) |
---|---|---|
d | 以带符号的十进制形式输出整数(正数不输出正号) | 输入有符号的十进制整数 |
o | 以无符号的八进制形式输出整数(不输出前导符0) | 输入无符号的八进制整数 |
x或X | 以无符号的十六进制形式输出整数,用x则十六进制用小写字符a~f,用X则用大写A~F | 输入无符号的十六进制整数(大小写作用一样) |
u | 以无符号的十进制形式输出整数 | 输入无符号的十进制整数 |
c | 输出一个字符 | 输入一个字符 |
s | 输出字符串 | 输入一个字符串 |
f | 以小数形式输出实数(单精度、双精度)隐含输出6位小数 | 输入实数,可以小数形式或指数形式输入 |
e或E | 以指数形式输出实数;用E时,指数部分的e用大写E | 作用与f相同 |
此外,在%和输出格式字符之间还可以插入如下的格式修饰符:
修饰符 | 说明 |
---|---|
- | 输出默认为右对齐,加“-”后改为左对齐 |
+ | 正数输出带正号 |
# | 输出八进制数时前面加数字0,输出十六进制时前面加0x |
数字 | 指定数据输出的宽度(即位数) |
.数字 | 指定小数点之后显示的位数(默认为6为小数);对于s格式,则指定输出的字符个数 |
l或L | 输出是长整型数(long)或长双精度型(long double)浮点数 |
因此,用于输出的格式字符和格式修饰符组合的一般形式为:
%[标志][数字][.数字][长度]类型
其中[]之间的是可选项。
2.5.4 格式输入函数
格式输入函数scanf的作用是从键盘输入数据,该输入数据按格式字符指定的输入格式被赋给相应的输入项地址。
函数scanf的一般形式为:
scanf("格式控制字符串",输入项地址列表);
其中,格式控制字符串用于指定输入格式,它包含下面两类内容:
(1)普通字符:要求用户必须按字符原样输入,不得做任何改变。
(2)格式字符:格式字符的书写格式和功能与printf的格式字符完全相同;只不过一个是用于输入,而另一个是用于输出。
输入项地址列表是由一个或若干个用逗号分隔的变量地址项组成的,每个变量地址项是一个在变量名前加地址运算符“&”的变量地址,也可以是由数组名表示的地址常量,或者是一个指向变量地址的指针变量。
如下:
scanf("%d,%d",&x,&y);
是一个正确的scanf语句,而:
scanf("%d,%d",x,y);
和
scanf("%d",x+y);
是一个错误的scanf语句。
函数scanf的常用输入格式字符如下表:
修饰符 | 说明 |
---|---|
l | 可用%ld、%lo、%lx来输入长整型数据,也可用%lf、%le输入double型数据 |
数字 | 指定输入数据所占的宽度(必须为整数) |
* | 赋值抑制符,即可以输入当前数据,但不传送给对应的变量(地址项) |