C程序设计速读笔记
数据的表型形式
常量
程序运行时,其值不能被改变的量称为常量。
-
常量类型
-
整型常量 如:1000、0、-162
-
实型常量
- 十进制小数形式 如:12.02、0.13、-13.15
- 指数形式 如:12.34e3(12.34*10³)、0.15E-3(0.15*10-³)
-
字符常量
-
普通字符 单撇号括起来的一个字符。
-
转义字符 以字符
\
开头的字符序列常见转义字符 输出结果 \n 换行 \t 将光标移到一下Tab键位置 '&" 输出单撇号&双撇号 详尽转义字符以及
\ascii码
表格 书本P40
-
-
字符串常量
用双撇号将若干个字符括起来。如:“boy”、“123”
单撇号内只能包含一个字符,双撇号内可以包含一个字符串
-
符号常量
用
#define
指令,指定用一个符号名称代表一个常量。如#define PI 3.1416 //注意没有分号
在需要改变程序中多出用到的同一个常量时,能做到“一改全改”
-
变量
变量必须先定义、后使用。
- 常变量
常变量存在期间其值不能改变。
-
常变量定义
在定义变量时,前面加一个关键字
const
。如:const int a=3;
数据类型(常见)
-
整型数据
-
基本整型(int)
基本整型为整数。如100、10、0、-10
基本整型定义:
int b;
-
长整型(long int)
长整型和基本整型都是整数。区别在于长整型可存储范围比基本整型大。
长整型定义:
long int b;
整型数据默认都是带有符号的(正负号),可在定义整型数据时前加
unsigned
定义无符号整型数据类型(只有正值) -
-
字符型数据
-
字符与字符代码
ASCII字符集内全部都是字符,包含字母、数字、标点、转义等等字符。
每一个字符都有对应的ASCII整数。
-
字符变量
字符变量用
char
定义。如:char a='?';
字符变量实际上是一个字节的整型变量,也就是对应的ASCII整数。因此也可选择输出十进制整数。如:
printf("&d\t%s\n",c,c)//省略定义字符变量 c='?'
-
-
浮点型数据
浮点型数据就是具有小数点的实数。
-
单精度浮点型(
float
)float型数据定义:
float a;
-
双精度浮点型(double)
相比于单精度浮点型可记录的小数位数更多。
double型数据定义:
double a;
-
运算符与表达式
基本算术运算符
运算符 | 含义 | 举例 | 结果 |
---|---|---|---|
+ | 正号 | +a | a的值 |
- | 负号 | -a | a的算术负值 |
* | 乘法 | a*b | a和b的乘积 |
/ | 除法 | a/b | a除以b的商 |
% | 求余 | a%b | a除以b的余数 |
+ | 加法 | a+b | a和b的和 |
- | 减法 | a-b | a和b的差 |
自增自减运算符
自增(++)、自减(–)运算符作用是使变量的值加1或减1。
i++
、i--
:先使i
的值加(减)1,在调用i
++i
、--i
:先调用i
,在使i
的值加(减)1
不同类型数据间的混合运算
+ - * /
运算两个数中有一个数为float
或double
,结果为double
int
与float
或double
运算,结果为double
- 字符(
char
)型与整形数据运算,就是把字符的ASCII码与整形数据进行运算
强制类型转换运算符
利用强制类型转换运算符将一个表达式转换成所需类型。如:(double)a
一般形式为(类型名)(表达式)
在强制类型转换时,得到一个所需类型的中间数据,而原来变量的类型未变化。例如
a=(int)x;//a为int x为float
,其中的x依然为原值float型。
C语句
赋值语句
-
赋值运算符
赋值符号
=
就是赋值运算符。如:a=3//省略定义a为int
-
复合的赋值运算符
在赋值符前加上其他运算符构成复合的运算符。
常见符合运算符有
+=
、-=
、*=
、/=
(定义与python复合运算符相同) -
赋值表达式
赋值运算符将一个变量和一个表达式连接起来的式子称为“赋值表达式”,一般形式为:
变量 赋值运算符 表达式
。如:a=3*5;
-
赋值过程类型转换
- 浮点型赋给整型变量:先对浮点数取整(舍弃小数),然后赋给整型变量。
- 整型数据赋给浮点型变量:数值不变,但以浮点数形式存储在变量中。
- double型赋给float型:只取6~7位有效数字
- 字符型赋给整型:将ASCII码赋给整型变量
数据输入和输出
-
使用
printf
函数输出数据一般格式为
printf("格式控制",输出表列);
如:printf("%s\n",a);//char a="hello"
- "格式控制"是用
""
括起来的一个字符串,包括两个信息:- 格式声明。格式声明由
%
和格式字符组成。如:%d
、&f
等。作用是将输出的数据转换为指定的格式后输出。 - 普通字符。普通字符即需要在输出是原样输出的字符。
- 格式声明。格式声明由
- 输出表列是程序需要输出的一些数据、可以是常量、变量、表达式等。
- "格式控制"是用
-
格式字符
-
d格式符
%d
在输出时,按十进制整型数据的实际长度输出,正数的符号不输出。可以在格式声明中指定输出数据的域宽(所占的列数)。如:
%5d
输出长整型数据:
%ld
; -
c格式符
%s
用来输出一个字符。也可以指定域宽。
-
s格式符
%s
用来输出一个字符串。
-
f格式符
用来输出实数(各种浮点数),以小数形式输出。
-
基本型float,用
%f
实数整数部分全部输出,小数部分输出6位
-
指定数据宽度和小数位数
%m.nf
指定输出数据占m列,其中包含n位小数,采取四舍五入原则处理。
-
输出数据向左对齐
%-m.nf
当数据长度不超过m时,数据向左靠,右端补空格。
输出双精度浮点数据:
%lf
-
-
e格式符
用格式声明
%e
指定以指数形式输出实数。其中e也可以写成E。 -
其他格式符
-
o格式符
以八进制整数形式输出
-
x格式符
以16进制整数形式输出
-
-
-
用
scanf
函数输入数据-
一般形式:
scanf(格式控制,地址表列)
,其中格式控制与printf
相同,地址表列是由若干个地址组成的表列。如:scanf("%s",&a)//省略定义a为字符型
-
格式声明:输入数据时需要符合的字符串格式。
-
如果在格式控制字符串除了格式声明之外还有其他字符,则在输入数据时在对应的位置上也应输入与这些字符相同的字符。如:
scanf("a=%s",&a)
,应输入a="c code"
,则变量a的值才为"c code",若缺失会产生不可思议的结果。 -
地址表列不是变量名组成的列表,而是变量对应的地址。即应该填入
&a
,而非a
-
若输入空格回车Tab键等等与数据类型不相符合的非法字符,则认为该数据结束
-
字符输入和输出函数
-
putchar
输出一个字符#include<stdio.h> int main() { char a='A'; putchar(a);//填入字符变量名 putchar('\n');//也可填入输出单个的字符 return 0; }
-
getchar
输入一个字符#include<stdio.h> int main() { char a; a=getchar();//字符变量承接输入字符 return 0; }
选择结构设计
if语句实现选择结构
- 一般形式
if (表达式) 语句1;
(没有else子句)if (表达式) 语句1; else 语句2;
(有else子句)if (表达式) 语句1; else if (表达式2) 语句2;else if(表达式3) 语句3;else 语句n;
(在else部分嵌套n层if语句)
关系运算符和关系表达式
-
六种关系运算符
关系运算符 描述 优先级 < 小于 高 <= 小于等于 高 > 大于 高 >= 大于等于 高 == 等于 低 != 不等于 低 -
关系表达式
-
用关系表达式将两个数值或数值表达式连接起来的式子。如:
a<b
-
关系表达式的值为一个逻辑值(真、假)。其中
真
用1
代表,假
用0
代表
-
逻辑运算符与逻辑表达式
-
逻辑运算符
运算符 含义 举例 说明 && and a&&b a和b皆为真,则结果为真 || or a||b a和b两者若有真,则结果为真 ! not !a 若a为真,则结果为假 -
逻辑表达式
-
逻辑表达式的值应该是一个逻辑量“真”或“假”,分别用数值“1”和“0”代表;
-
表达式自左向右求解。
-
条件运算符和条件表达式
if(a>b) max=a;else max=b;
这个选择结构可以改写为条件表达式max=(a>b)?a:b
。
-
一般形式为:
表达式1?表达式2:表达式3
-
?
、:
为条件运算符。两者必须组合使用 -
max(a>b)?a:b
为条件表达式。如果(a>b)?
条件为真,值等于a,否则值等于b
选择结构嵌套
-
if语句嵌套
if() //嵌套if_1 if() 语句1 else() 语句2 else() //嵌套if_2 if() 语句3 else() 语句4
使用花括号
{}
来确定配对关系 -
switch
语句实现多分支选择结构#include<stdio.h> int main() { char grade; scanf("%c",&grade); printf("Your score:"); switch(grade) { case'a':printf("100~85\n");break; case'b':printf("84~60\n");break; case'c':printf("59~0\n");break; default:printf("enter data error!\n");//以上不符合则执行这项 } return 0; }
-
一般形式为:
switch(表达式) { case 常量1:语句1 //确保常量之间各不相同 case 常量2:语句2 default: 语句n+1 //处理无匹配情况,可选添加该项 }
-
多个
case
可以共用一个语句switch(表达式) { case 常量1: //注意无; case 常量2:语句2 default: 语句n+1 }
-
-
循环结构设计
while语句
#includ<stdio.h>
int main()
{
int i=1,sum=0;
while(i<100)
{
sum+=1;
i++;
}
printf("sum=%d\n",sum);
return 0;
}
-
一般形式:
while(表达式)语句
。表达式被称为循环条件表达式;语句被称为循环体。只要循环条件表达式为真,就执行循环体语句。
do···while 语句
int i=1;//设置初始值i=1
do//循环开始
{
printf("%d",i++);//循环体
}
while(i<100);//循环条件表达式
执行do
的循环体语句,然后在while
循环条件表达式检查i
的值,判断是否继续循环(先无条件执行循环体,之后判断循环条件)
-
一般形式:
do 语句 while(表达式)
for语句
for(i=0;i<100;i++)//控制循环次数
printf("%d",i);//执行循环体
-
一般形式:
for(表达式1;表达式2;表达式3) 语句
- 表达式1:设置初始条件,只执行一次。数量没有要求。
- 表达式2:循环条件表达式
- 表达式3:循环的调整,例如循环变量的增值,于每次执行完循环体后才执行
也可归结为以下形式:
for(循环变量赋初值;循环条件;循环变量增值) 语句
表达式123均可在一定条件下省略,但必须保留分割的
;
当表达式中含有多个小表达式,用
,
分隔 -
for循环可以与while循环无条件转换
循环嵌套
-
while
内层循环while() { ··· while() { ··· } }
-
do···while
内层循环do { ··· do { ··· } while(···) } while(···)
-
for
内层循环for(;;) { ··· for(;;) { ··· } }
-
while
、do···while
循环while() { ··· do{···} while(···); }
-
for
、while
循环for(;;) { ··· while(){···} }
-
do···while
、for
循环do{ ··· for(;;){···} } while();
改变循环执行状态
-
break
语句提前终止循环,将流程跳到循环体之外,接着执行循环体下面语句
-
continue
语句提前结束本次循环,接着执行下一次循环
数组
一维数组
#include<stdio.h>
int main()
{
int i;
int f[20]={1,1};//定义数组前两元素初始值
for(i=2;i<20;i++)
{
f[i]=f[i-2]+f[i-1];
}
for(i=0;i<20;i++)
{
if(i%5==0) printf('\n');//控制每输出5个数后换行
printf("%12d",f[i]);
}
printf('\n');
return 0;
}
-
定义一维数组
一般形式为:
类型符 数组名[常量表达式]
。如:int a[10]
-
引用一维数组元素
数组名 [下标]
其中下标也可以用常量表达式表示 -
一维数组初始化
- 在定义数组是对全部数组元素赋予初始值。如:
int a[3]={1,2,3};
- 只给数组中的一部分元素赋值。如:
int a[10]={1,2,3,4};
- 给数组每一个元素赋予同一个值。如:
int a[10]={0};
- 不指定数组长度。如:
int a[]={1,2,3,4,5}//不指定数组长度定义时,必须给数组全部元素赋值
- 在定义数组是对全部数组元素赋予初始值。如:
二维数组
#include<stdio.h>
int main()
{
int a[2][3]={1,2,3,4,5,6};
int b[3][2]=,i,j;
printf("array a:\n");
for(i=0;i<=1;i++)//提取a的行
{
for(j=0;j<=2;j++)//提取a的列
{
printf("%5d",a[i][j]);
b[j][i]=a[i][j];//赋值给b数组
}
printf("\n");
}
printf("array b:\n");
for(i=0;i<=2;i++)
{
for(j=0;j<=1;j++)
{
printf("%5d",b[i][j]);
}
printf("\n")
}
}
-
二维数组定义
一般形式为
类型说明符 数组名[常量表达式][常量表达式]
。如:float a[20][20];
-
引用二维数组元素
引用形式为
数字名 [下标][下标]
-
二维数组初始化
- 分行给二维数组赋值。如:
int a[2][3]={{1,2,3},{4,5,6}};
- 可以将所有数据写在一个花括号内,按数组元素在内存中的排列顺序对个元素赋值。如:
int a[2][3]={1,2,3,4,5,6};
- 对部分元素赋值。如:
int a[2][3]={[1],[4]};
- 如果对全部元素赋值可省略维度,但不可缺失维度长度。如:
int a[][3]={1,2,3,4,5,6};
- 分行给二维数组赋值。如:
字符数组
-
定义字符数组
char a[10];
-
字符数组初始化
-
定义时依次全部赋值。
char a[2]={'h','i'};
定义时赋值个数小于数组长度,其与元素自动定位空字符
\0
-
不指定字符数组长度。如:
char a[]={'h','i'};
也等价于char a[]="hi";
、char a[]={"hi"};
-
二维字符数组定义与初始化与上相同
-
-
引用字符数组元素
一般形式:
字符数组名 [下标]
。可以引用字符数组中的一个元素,得到一个字符。 -
字符串、字符数组定义结束标志
以字符
\0
作为结束标志。用字符数组存储字符串常量会自动加一个
\0
作为结束符 -
在使用
scanf
函数输入多个字符串,则应该输入时以空格分隔 -
处理字符串的函数
-
puts
输出字符串- 一般形式为
puts(字符数组)
。如:puts(str); //char str[]="china"
puts
输出时将字符串结束标志/0
转换成\n
- 一般形式为
-
gets
输入字符串- 一般形式为
gets(字符数组)
。如:gets(str); //chat str[10]
- 一般形式为
-
strcat
链接字符串-
一般形式为
strcat(字符数组1,字符数组2)
。如:new_str=strcat(str_1,str_2); //将str_2链接到str_1后面
务必确保
str_1
有足够的数组长度容纳str_2
``
-
-
strcpy
复制整体字符串-
一般形式
strcpy(字符数组1,字符数组2)
。如:strcpy(str1,str2) //将str_2复制到str_1
确保
str_1
有足够的数组长度
-
-
strncpy
复制前N个字符串- 一般形式
strncpy(str_1,str_2,2)
- 一般形式
-
strcmp
字符串比较- 一般形式
strcmp(字符串1,字符串2)
- 返回值
- 字符串1=字符串2,函数值为0
- 字符串1>字符串2,函数值为正整数
- 字符串1<字符串2,函数值为负整数
- 一般形式
-
strlen
测量字符串长度- 一般形式
strlen(字符数组)
- 一般形式
-
strlwr
转换为小写- 一般形式
strlwr(字符串)
- 一般形式
-
strupr
转换为大写- 一般形式
strupr(字符串)
- 一般形式
-
模块化程序设计
函数
-
定义函数
-
定义无参函数
类型名 函数名() { 函数体 }
或
类型名 函数名(void) { 函数体 }
-
定义有参函数
类型名 函数名(形参表列) { 函数体 }
-
定义空函数
类型名 函数名() {}
-
-
调用函数
- 一般形式为
函数名 (实参表列)
。如:print_star(); //调用无参函数
、c=max(a,b); //调用有参函数
- 一般形式为
-
函数调用时数据传递
-
形参和实参
在定义函数函数名后括号内的变量名为
形式参数
调用函数填在函数名后括号内的变量为
实际参数
-
-
函数的返回值
- 函数的返回值是通过函数中的
return
语句获得 - 函数返回值需要与函数定义时类型相对应(函数类型决定返回值的类型)
- 函数的返回值是通过函数中的
-
函数递归
#include<stdio.h> int main() { int fac(int n);//fac函数声明 int n,y; printf("input an interger number:"); scanf("%d",&n); y=fac(n); printf("%d!=%d\n",n,y); return 0; } int fac(int n) { int f; if(n<0) printf("n<0,data error!"); else if(n==0||n==1) f=1; else f=fac(n-1)*n; return f; }
-
一维数组名作为函数参数
#include<stdio.h> int main() { float average(float array[10]); float score[10],aver; int i; printf("input 10 scores:\n"); for(i=o;i<10;i++) { scanf("%f",&score[i]); } printf("\n"); aver=average(socre); printf("average score is %5.2f\n",aver); return 0; } float average(float array[10]) { int i; float aver,sum=array[0]; for(i=0;i<10;i++) { sum+=array[i]; } aver=sum/10; return aver; }
- 形参数组可不指定长度,在定义数组时在数组名后面跟一个
[]
- 在定义
average
函数时,声明形参数组大小为10,实际上指定大小是不起作用的。C语言会将实参数组首元素地址传给形参数组名,两者具有统一地址,同一存储单元
- 形参数组可不指定长度,在定义数组时在数组名后面跟一个
-
多维数组名作为函数参数
#include<stdio.h> int main() { int max_value(int array[][4]); int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; printf("Max value is %d\n",max_value(a)); return 0; } int max_value(int array[][4]) { int i,j,max; max=array[0][0]; for(i=0;i<3;i++) { for(j=0;j<4;j++) if(array[i][j]>max)max=array[i][j]; } return max; }
-
内部函数
一个函数只能被本文件中其他函数所调用,为内部函数。
-
外部函数
调用外部函数,在头信息中加上
#include"filename"
相当于include<math.h>
,同时声明函数时加上extern
,即extern int fun(int a,int b);
file1.cpp
#include<stdio.h> #include"file2.cpp" //导入外部文件 int main() { extern void show(); show(); return 0; }
file2.cpp
#include<stdio.h> void show() { printf("hello, world\n"); }
局部变量、全局变量
-
局部变量
- 只有在本函数范围有效
- 在函数开头定义
- 在函数内的复合语句内定义(复合语句eg:嵌套循环中的一环)
- 在函数外部定义
-
存储类别
-
自动变量(auto变量)
在调用函数时,系统分配存储空间,在函数结束时自动释放存储空间
int f(int a) { auto int b,c=3; }
实际上
auto
通常省略,则暗指为“自动存储类别” -
静态局部变量(static局部变量)
在函数调用结束后不消失,继续保存其值,需要用
static
声明#include<stdio.h> int main() { int f(int); int a=2,i; for(i=0;i<3;i++) { printf("%d\n",f(a)); } return 0; } int f(int a) { int b=0; static int c=3;//不会重新定义c为3,而是保持c其值 b+=1;c+=1; return (a+b+c); }
-
- 只有在本函数范围有效
-
全局变量
-
在函数之外定义的变量,有效范围从定义变量处到本源文件结束
-
存储类别
-
使用关键字
extern
对变量作外部变量声明,将变量作用域扩展到此位置#include<stdio.h> int main() { int max(); extern int A,B,C; printf("Please enter three interger numbers:\n"); scanf("%d%d%d",&A,&B,&C); printf("max is %d\n",max()); return 0; } int A,B,C; int max() { int m; m=A>B?A:B; return m; }
-
-
-
如果全局变量与局部变量同名,在函数范围内全局变量被局部变量屏蔽,相当于全局变量不存在
指针
-
地址指向变量单元,地址形象化称为指针。
-
直接用变量名访问,称为直接访问;通过地址访问变量,称为间接访问
-
专门存储地址(指针)的变量为指针变量,其值为地址(指针)
- 指针变量
-
定义指针变量:一般形式为
类型名 *指针变量名
。- 指针变量的基类型用来指定此指针变量可以指向的变量的类型
*
表示该变量是指针型变量,但是存储地址的是指针变量名
- 一个变量的指针含义包括两个方面,一是以存储单元编号表示的纯地址,一是它指向的存储单元的数据类型
-
引用指针变量
&
取址运算符;*
指针运算符;- 给指针变量赋值:
p=&a; //把a的地址赋给指针变量p
- 引用指针变量指向的变量:
printf("%d\n",*p); //输出指针变量对应的值
- 引用指针变量的值:
printf("%o",p);
- 给指针变量赋值:
-
指针变量作为函数参数
#include<stdio.h> int main() { void swap(int *p1;int *p2); int a,b; int *pointer_1,*pointer_2; printf("please enter a and b:"); scanf("%d,%d",&a,&b); pointer_1=&a;pointer_2=&b; if(a<b) swap(pointer_1,poiter_2); printf("max=%d,min=%d\n",a,b); return 0; } void swap(int *p1,int *p2) { int temp; temp=*p1; *p1=*p2;*p2=temp;//交换p1,p2 }
-
通过指针引用数组
-
定义指针执行数组
int a[10]; int *p; p=&a[0];//把a[0]元素地址指向指针变量 /*指向语句也可这样写 p=a; 将a数组首元素地址指向指针变量*/
-
引用数组指针运算
在指针已指向一个数组元素时,可以进行以下运算:加减一个整数,自加自减运算。
指针运算加减一个整数,反应为指向上一个或下一个元素的地址
-
通过指针引用数组元素
#include<stdio.h> int main() { int a[10]; int *p,i; printf("please enter 10 interger numbers:"); for(i=0;i<10;i++) scanf("%d",&a[i]); for(p=a;p<(a+10);p++) printf("%d",*p); return 0; }
通过指针引用多维数组
表现形式 | 含义 | 值 |
---|---|---|
a | 二维数组名,指向一维数组a[0],即0行起始地址 | 2000 |
a[0]、*(a+0)、*a | 0行0列元素位置 | 2000 |
a+1、&a[1] | 1行起始位置 | 2016 |
a[1]、*(a+1) | 1行0列元素a[1][0]的地址 | 2016 |
a[1]+2、*(a+1)+2、&a[1][2] | 1行2列元素a[1][2]的地址 | 2024 |
*(a[1]+2)、*(*(a+1)+2)、a[1][2] | 1行2列元素a[1][2]的值 | 值为13 |
#include<stdio.h>
int main()
{
void average(float *p,int n);
void search(float (*p)[4],int n);
float score[3][4]={69,44,87,97,75,66,85,77,64};
average(*score,12);
search(score,2);
return 0;
}
void average(float *p,int a)
{
float *p_end;
float sum=0,aver;
p_end=p+n-1;
for(;p<=p_end;p++)
{
sum+=(*p);
}
aver=sum/n;
printf("average=%5.2f\n",aver);
}
void search(float (*p)[4],int n)
{
int i;
printf("the score of no.%d are:\n",n);
for(i=0;i<4;i++)
printf("%5.2f",*(*(p+n)+i));
printf("\n");
}
| 二维数组名,指向一维数组a[0],即0行起始地址 | 2000 |
| a[0]、(a+0)、*a | 0行0列元素位置 | 2000 |
| a+1、&a[1] | 1行起始位置 | 2016 |
| a[1]、(a+1) | 1行0列元素a[1][0]的地址 | 2016 |
| a[1]+2、*(a+1)+2、&a[1][2] | 1行2列元素a[1][2]的地址 | 2024 |
| *(a[1]+2)、*(*(a+1)+2)、a[1][2] | 1行2列元素a[1][2]的值 | 值为13 |
#include<stdio.h>
int main()
{
void average(float *p,int n);
void search(float (*p)[4],int n);
float score[3][4]={69,44,87,97,75,66,85,77,64};
average(*score,12);
search(score,2);
return 0;
}
void average(float *p,int a)
{
float *p_end;
float sum=0,aver;
p_end=p+n-1;
for(;p<=p_end;p++)
{
sum+=(*p);
}
aver=sum/n;
printf("average=%5.2f\n",aver);
}
void search(float (*p)[4],int n)
{
int i;
printf("the score of no.%d are:\n",n);
for(i=0;i<4;i++)
printf("%5.2f",*(*(p+n)+i));
printf("\n");
}