导图社区 C 语言编程知识总结
C 编程知识总结,C语言是一种通用的、过程式的计算机编程语言,支持结构化编程、词汇变量作用域和递归等功能。
编辑于2023-12-29 17:10:38在资料分析中,平均数问题频繁出现,是考试的重点考察内容。该模板全面且系统地梳理了平均数问题的各个考点,为考生构建起清晰的知识体系。现期平均数是基础考点,模板中不仅给出了其公式定义“平均数 = 总数/个数”,还详细列举了常见的考察形式,如直接求平均数、求总数、求个数,同时提供了速算技巧——截位直除,帮助考生快速准确地得出答案。基期平均数的讲解同样细致,明确公式定义后,指出其速算技巧类似于基期比重的计算,让考生能够触类旁通,提高解题效率。两期平均数比较是考生容易出错的地方,模板通过清晰的升降判断规则“a > b 上升,a < b 下降”,帮助考生准确判断平均数的变化趋势,避免失误。平均数增长率和平均数增长量这两个考点也有深入剖析。借助EdrawMind制作的这一思维导图模板,考生可以在备考过程中快速梳理知识点,查漏补缺,加深对平均数问题考点的理解和记忆。在考试时,能够迅速调用相关知识,运用速算技巧,提高答题速度和准确率。它是考生提升资料分析成绩、实现考试突破的得力助手,助力考生在竞争激烈的考试中脱颖而出。
大学计划和规划,大学四年,是人生中一个充满无限可能与挑战的宝贵阶段。为即将或正在经历这一阶段的学子们提供一份详尽而实用的指南,帮助大家从入学之初就树立明确的目标,制定合理的计划,逐步构建起扎实的专业知识体系。
经济学基础(2025中级经济师),涵盖广泛的经济学基础知识,内容结构清晰,分为多个部分或章节,针对考试的重点和难点,进行有针对性的学习和练习,提高解题能力和应试技巧。
社区模板帮助中心,点此进入>>
在资料分析中,平均数问题频繁出现,是考试的重点考察内容。该模板全面且系统地梳理了平均数问题的各个考点,为考生构建起清晰的知识体系。现期平均数是基础考点,模板中不仅给出了其公式定义“平均数 = 总数/个数”,还详细列举了常见的考察形式,如直接求平均数、求总数、求个数,同时提供了速算技巧——截位直除,帮助考生快速准确地得出答案。基期平均数的讲解同样细致,明确公式定义后,指出其速算技巧类似于基期比重的计算,让考生能够触类旁通,提高解题效率。两期平均数比较是考生容易出错的地方,模板通过清晰的升降判断规则“a > b 上升,a < b 下降”,帮助考生准确判断平均数的变化趋势,避免失误。平均数增长率和平均数增长量这两个考点也有深入剖析。借助EdrawMind制作的这一思维导图模板,考生可以在备考过程中快速梳理知识点,查漏补缺,加深对平均数问题考点的理解和记忆。在考试时,能够迅速调用相关知识,运用速算技巧,提高答题速度和准确率。它是考生提升资料分析成绩、实现考试突破的得力助手,助力考生在竞争激烈的考试中脱颖而出。
大学计划和规划,大学四年,是人生中一个充满无限可能与挑战的宝贵阶段。为即将或正在经历这一阶段的学子们提供一份详尽而实用的指南,帮助大家从入学之初就树立明确的目标,制定合理的计划,逐步构建起扎实的专业知识体系。
经济学基础(2025中级经济师),涵盖广泛的经济学基础知识,内容结构清晰,分为多个部分或章节,针对考试的重点和难点,进行有针对性的学习和练习,提高解题能力和应试技巧。
C艹
C/C艹概述
C简介
程序框架
int main()
定义变量
输入已知
求解处理
输出结果
暂停程序运行
system("pause"); return 0;
特点
C/C艹程序是由一个或多个函数构成的
一个函数中有且只能有一个main函数
不管有多少个函数,程序总是从main函数开始执行
一行内可写多条语句,一条语句可以分行
每条语句末尾有;
区分大小写
基本语法成分
基本符号
运算符
标识符
被定义的变量
字母 数字 下划线 组成
以字母或下划线开头
关键字不能作标识符
习惯上变量名小写,符号常量大写
编译预处理
编写源程序.cpp
预处理.cpp
替换变量,加入源文件
编译.obj
语法错误检查
连接
执行.exe
逻辑错误
修改源程序代码应该打开扩展名为.sln的文件
功能
文件包含
形式
#include<文件名>
从系统指定的文件夹中找
#include"文件名"
从项目文件夹中找,再到系统指定的文件夹中找
编译时将头文件的内容插入到原文件(.cpp)中
一条文件包含命令只能包含一个文件
命令不是语句,句末不用加分号;
宏定义
#define 标识符 常量
e.g.
#define FALSE 0
#define TRUE 1
#define PI 3.14
#define EPS 1.0e-6
符号常量一般大写
行末不加分号
不能对符号常量赋值
条件编译
基本数据类型,运算符和表达式
数据类型
作用
决定存储空间
决定取值范围
决定所能参与的运算
分类
基本类型
整型(int)
实型
单精度(float)
7位有效
双精度(double)
15位有效
字符型(char)
布尔型(bool)
空类型(void)
指针
构造类型
数组
结构型(struct)
共用体(union)
枚举(enum)
类(class)
数据的输入和输出
输入
代码
cin>>变量1>>变量2>>……>>变量n;
cin>>a>>b;
数据之间需用空格、TAB或回车分隔
>>后只能是变量,不能是常量或表达式
输出
代码
cout<<表达式1<<表达式2……<<表达式n;
cout<<c<<' '<<"abcd"<<endl;
空格
'1个空格':字符常量
"多个空格"字符串常量
各表达式可以是任意类型
格式控制符
endl
输出换行符
cout<<1123<<endl<<123;
123 123
dec
十进制整数
cout<<dec<<123;
123
hex
十六进制整数
cout<<hex<<123;
7b
oct
八进制表示整数
cout<<oct<<123;
173
setw(int n)
设置数据输出宽度
cout<<'a'<<setw(4)<<'b';
a b(中间有三个空格)
#include <iomainip>
setfill(int n)
设置填充字符
cout<<setfill('*')<<setw(6)<<123;
***123
setprecision(int n)
设置浮点数输出的有效数字位数
cout<<<setprecision(5)<<123.456;
123.46
变量和常量
变量
定义方式
数据类型 变量名
int a,b;
获取值
输入语句
cin>>a;
赋值语句
a=3;
初始化
数据类型 变量名=表达式;
数据类型 变量名(表达式);
int k=3,m=3,n(3);
C艹变量应用
给变量起一个别名
数据类型&引用名=已定义变量
int a=3,&b=a;
常量
整型常量
实型常量
十进制小数形式
如 1.25 .1 17.
指数形式
由尾数 指数符号e(E)及指数构成,其中指数必须为十进制整数
如 +1.25e-5 -1e10
字符常量
普通字符
用' '括起的一个字符
存储为ASCII码 1字节
转义字符
\n
换行
\b
退格
\t
跳到下一个输出区(8位一个输出区)
\r
光标回到本行行首
\\
字符\
\"
字符"
\'
字符'
\ddd
1-3位八进制所代表的字符,如 \101 表示 A
\xdd
1-2位十六进制数所代表的字符,如 \x42 表示 B
字符串常量
' ' 括起的字符序列
结尾自动添加 \0 (字符串结束符号)
符号常量
以标识符形式出现的常量,用来定义某字母指代一个数
写法
#define 标识符 常量值
const 数据类型 标识符=常量值
习惯上符号常量大写,变量名小写
符号常量本质上是常量,具有常量值不可以改变的性质
运算符和表达式
运算符
算术运算
种类
%
取余
++
自增
--
自减
优先级
从高到低
++ -- + -
+ - 表示正负
* / %
+ -
表示加减
说明
/ 当两个操作数为整数时,商也为整数
1/2 输出 0
1.0/2 输出 0.5
%要求两个操作数都为整型
自增自减
用法
++i --i
在使用i之前,先把 i 值加减1
i++ i--
在使用i之后,把 i 值加减1
自增自减的结合性从右到左
只能应用于变量,不能应用于常量和表达式
目数越少,优先级越高
关系运算
运算符
==
等于
!=
不等于
<
<=
运算结果:真 (1) 假(0)
逻辑运算
运算符
逻辑非
!
!A
逻辑与
&&
A&&B
逻辑或
||
A||B
e.g.
x>=0 && x<100
特点
按真值表输出 0 1
运算数可以为任何类型,通常为关系表达式
所有非0数当作 真 处理,即当作 1 参与运算
并非所有逻辑运算都被执行
运算过程中只有表达式的值可以唯一确定即停止运算
赋值运算
简单赋值运算
=
变量 = 表达式
复合赋值运算
将左边变量与右边表达式值的和 (差,积,商,余数等) 送入左边变量
+= -= *= /= %=
左端只能是变量 (数组元素),不能为表达式或常量
自动将右端类型转化为左端类型
结合性自右向左
a=b=c=1 等价于 a=(b=(c=1))
条件运算
形式
e1?e2:e3
含义
e1若非0,则取e2的值,否则取e3的值
右结合性
e.g.
max=(x>y)?x:y
逗号运算
形式
e1,e2,e3……
从左向右依次计算每个表达式的值,整个表达式的值为最右边表达式的值
将多个表达式连成一个表达式
e.g.
c=(a=10,b=20,a+b)
得到c=30
类型转换运算
隐式转换
强制转换
写法
类型名(表达式)
(类型名)表达式
内部函数,
取地址,
语句结构
顺序结构
空语句
复合语句
形式
{ [变量定义] 语句组 }
注:变量局部有效
用途
用 { } 将多条语句组成一个整体
语法上只允许一条语句,但功能需要多条语句完成
内部定义用于复合语句内部使用的变量
选择结构
if语句
单分支
形式
if (表达式) 语句
( ) 后不加 : ;
含义
条件为真(非0),则执行语句,否则跳过该语句
语句只能是一条
双分支
形式
if (表达式) 语句1; else 语句2;
含义
条件为真(非0),则执行语句1,否则执行语句2
语句只能是一条
多分支
形式
if (表达式1) 语句1; else if (表达式2) 语句2 …… else if (表达式n) 语句n; else 语句n+1;
执行
任意一个表达式为真,则执行其后紧跟的一条语句并跳过所有其他语句;若所有表达式皆假,则执行语句n+1
嵌套形式
形式
if (表达式1) if (表达式11) 语句11; else 语句12; else if (表达式21) 语句21; else 语句22;
注意 ;
说明
else始终与其上面最近的没有其他else配对的if语句配对
可以用 { } 标注不同嵌套层级
switch语句
形式
switch (表达式/变量) { case 常量表达式1 : 语句组1 ; [ break ; ] case 常量表达式2 : 语句组2 ; [ break ; ] …… case 常量表达式n : 语句组n ; [ break ; ] [default : 语句组n+1]
注意
switch后表达式类型必须为整型或字符型
case后的常量表达式必须可一一列举,不能是取值范围
前一个case语句没有break时,遍历之后的语句直到遇到break时退出switch语句
多个常量表达式可共用一组语句
执行
若表达式与case中常量表达式相等,则执行该常量表达式之后的语句
若没有与之匹配的表达式,则执行default后面的语句
循环结构
while语句
形式
while (循环条件) 循环体语句;
括号后不能有 ;
执行
如果表达式结果为真,则执行循环体语句后再回到条件判断, 直到条件为假跳出循环。
循环体语句只能是一条,但可以为复合语句
while(!e);
子主题1
do while语句
形式
do 语句; while (表达式) ;
执行
先执行语句后判断条件是否为真,为真则继续循环,直到条件为假则跳出循环
循环语句只能是一条
不同于while语句,表达式结束的 () 后有 ;
for语句
形式
for(循环变量赋初值表达式 ; 循环条件表达式 ; 循环变量变化情况表达式 ) 循环体语句
注意
同while语句一样,是先判断后执行的循环
循环体语句只能是一条
表达式结束的括号后没有 ;
三个表达式都可以省略,但分号不能省略
表达式1只在开始之前执行一次
表达式1可放在for语句之前
表达式2和表达式3可放于循环体中
辅助控制语句
break语句
用于switch语句,跳出最近一层switch结构
用于循环语句,强制跳出循环体,提前终止循环
一般与if一同使用
continue语句
结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断
只能用于循环语句,一般与if语句一起使用
与break语句不同,不是退出本层循环,仅仅结束本次循环
数组
一维数组
定义
形式
数据类型 数组名[整型常量表达式]
E.g int s[5]
注
下标从0开始,到n-1结束
数组名是常量,表示数组在内存中的首地址
数组长度应该为整型常量表达式,不能是变量
初始化
给所有元素赋值
形式
int a[5]={0,2,4,6,8}
全部初值给出,可省略长度
给部分元素赋初值
形式
int a[10]={0,2,4,6,8}
花括号内的值赋给a[0]~a[4],a[5]~a[9]自动赋为0
引用
形式
数组名[下标]
操作
输入
for(j=0;j<N;j++) cin>>a[j];
产生0-100的N个数据
for(i=0;i<N;i++) a[i]=rand()%101;
求和
sum=0; for(i=0;i<N;i++) sum+=a[i];
求最大元素
max=a[0]; for(i=1;i<N;i++) if(a[i]>max) max=a[i];
求最大元素下标
imax=0; for(i=1;i<N;i++) if(a[i]>a[imax]) imax=i;
将最大元素放在开头
imax=0; for(i=1;i<N;i++) if(a[i]>a[imax]) imax=i; if(imax!0) { t=a[0]; a[0]=a[imax]; a[imax]=t; }
插入数据x(顺序
for(i=0;i<N;i++) if(x<a[i]) break; for(j=N;j>=i;j--) a[j+1]=a[j]; a[i]=x;
删除数据x
for(i=0;i<N;i++) if(x==a[i]) break; for(j=i;j<N-1;j++) a[j]=a[j+1];
二分法查找元素x的下标(顺序
min=0,max=N-1; while(min<=max) { mid=min+(max-min)/2; if(x==a[mid]) break; else if(x<a[mid]) max=mid-1; else min=mid+1; } cout<<mid;
排序算法(顺序
选择法
for(n=a[0];n<N;n++) for(j=0;j<N;j++) if(a[j]>=a[n]) t=a[n],a[n]=a[j],a[j]=t;
冒泡法
for(n=0;n<N;n++) for(i=0;i<N-n-1;i++) if(a[i]>a[i+1]) t=a[i],a[i]=a[i+1],a[i+1]=t;
二维数组
定义
数据类型 数组名[常量表达式1][常量表达式2]
初始化
按内存排列顺序赋初值
int a[2][3]={1,2,3,4,5,6}
第一维列数可省略
按行赋值
int a[2][3]={{1,2,3},{4,5,6}
按行给部分元素赋值
int a[3][4]={{1,2},{0,5,6},{0,0,5}}
省略的元素赋 0
字符串
字符数组
可存放
若干个字符
字符串
初始化
逐个字符赋初值
char s[3]={'T',' ','a'} ;
s 不是字符串
用字符串为字符数组初始化
char s[10]={"I am fine"};
char s[10]= "I am fine" ;
'\0'系统自动添加
字符串数组初始化
对二维数组以字符串形式初始化
char a[4][8]={"COBOL","FORTRAN","C/C++"} ;
用两个下标表示数组中的一个字符
字符数组的输入/输出
逐字
char s1[10]; for(i=0;i<10;i++) cin>>s1[i];
一定要输够10个字符
s1中是字符,不是字符串,输入必须逐元素进行
字符串
输入
gets_s(数组符号)
如 gets_s(s)
输出
puts(s)
头文件:stdio.h
字符串处理
strlen(str)
字符串长度(不包括'\0')
strlwr(str)
将字符串中的大写字母转化为小写字母
strupr(str)
将字符串中的小写字母转化为大写字母
strcpy(str1,str2)
将str2所指字符串存入str1
strcat(str1,str2)
将字符串str2的内容连接在str1内容的后面
strcmp(str1,str2)
逐个字母比较str1和str2,若str1较小输出-1,相等输出0,str1较大输出1
头文件:string.h
字符指针
概念
每个变量在内存中存放都对应一段地址,其中首字节即为变量的地址,将存放地址的变量称为指针变量。
& 取地址运算
&x 变量x的地址
* 取内容运算
例
x=4 x的地址为1001 &x=1001 *(&x)=4
定义·
数据类型 * 标识符
数据类型指指针所指向位置存放的数据类型
* 不是变量的一部分
如 int *p; 则p可以存放一个int型变量的地址
初始化
为指针变量赋一个初始值
int a=5,*p=&a;
int a=5,*p; p=&a;
常用运算
赋值运算
p=NULL
p被赋值为NULL(0),且不指向任何对象
p=&a
p指向变量a
p1=&a; p2=p1:
同类型指针变量相互赋值
p=new int;
为p动态分配一个整数的空间
p=new int[10]
为p动态分配10个整数的空间
加减整数的运算
假设p为指针变量,n为整数
p+n(或p-n)
p后面或者前面的第n个元素
自加自减运算
(p++)或(p--)
指向p后面或前面的一个元素
指针相减运算
两个地址之间能存放的数据个数
指针与数组关系
等价关系
设定义 int a[10] , *p=a[0] ;
p <=> a <=> &a[0]
p+i <=> a+i <=> &a[i]
*(p+i) <=> *(a+i) <=> a[i]
指针与字符串
例题
int main() { int a[10][10],n,i,j; cin>>n; for(i=0;i<n;i++) { for(j=0;j<n-i;j++) { if(i==0||j==0) a[i][j]=1; else a[i][j]=a[i-1][j]+a[i][j-1]; cout<<a[i][j]<<' '; } cout<<endl; } for(i=0;i<n;i++) { for(j=n-i;j>0;j--) cout<<" "; for(j=0;j<=i;j++) cout<<a[j][i-j]<<" "; cout<<endl; }
函数
函数的定义
形式
函数类型 函数名(形式参数类型表) { 函数体 }
例
//求三角形面积的函数area float area(float x, float y, float z) { float c,s ; c = (x + y + z)/2; s = sqrt(c*(c-x) * (c-y) * (c-z)); return s; }
形参
float area(float x,float y,float z)
不能写成: float area(float x,y,z)
有多个形参时,形参间用逗号分隔,也可以没有形参,圆括号不能省略
函数体中不允许再次定义函数
函数类型就是函数返回值类型
函数通过return语句返回一个值给调用它的函数
函数返回值的类型与函数类型最好一致。若不一致,转换为函数的类型
函数的调用
形式
函数名(实参,实参)
实参与函数定义时形参的个数,类型,次序要一一对应
调用类型
表达式
m=getmax(a,b);
有返回值
语句
pic(a);
无返回值
函数说明
当调用函数在定义函数之前时,需要函数说明
函数说明和函数定义在返回类型、函数名和形式参数类型表上必须要完全一致。
函数说明可以省略形参的名字,只给出形参的个数与类型
例
int max(int x , int );
数组名做函数参数
形式
定义
void sort(int a[] , int n)
调用
sort(a ,10)
[ ] 里不写数组长度
数组元素中数组长度一般作为参数输入
形参与实参共用内存空间
函数间的参数传递
型参与实参
函数调用时,将实参值赋给形参,参与计算后释放形参数值
参数为单向传递,函数中形参的改变对实参没有影响
引用参数
引用
引用是一种特殊类型的变量,可认为是另一个变量的别名
如果a是x的引用,a和x共用同一内存单元,a改变则x也改变了
引用变量做形参函数
形参是引用,形参和实参使用相同内存单元
使用:
主函数
swap(x,y)
子函数
void swap(int &a , int &b )
指针参数
传递特点
形参中存放实参内存单元地址
改变形参指向的内存单元的内容就是改变实参的值
使用
主函数
swap( &x , &y )
子函数
void swap(int*a , int*b)
返回指针值的函数
函数的返回值可以是变量的地址,数组名或指针变量等
在说明或定义返回值为指针值的函数时,只须在函数名前加一指针类型说明符即可
例
char *fun(float x[], float y);
输出字符串中最大字符之后的字符
作用域与存储类别
结构和链表
结构体
结构类型
概念
将类型和性质可能不同但互有关联的数据组合在一起构成的集合
声明
struct 结构类型标识符 { 结构成员1定义; 结构成员2定义; …… 结构成员n定义; };
结构变量成员可以像同类型普通变量一样使用
结构成员名可以与结构外的其它变量同名,二者不代表同一个对象
e.g.
struct date { int month; int day; int year; };
嵌套定义
struct person { char name[15]; char sex; int age; date birthday; };
结构变量
结构类型不是程序操作的对象,不占用内存空间,只有在定义了结构变量后,系统才会为之分配内存单元
定义
声明类型的同时定义变量
struct person { char name[15]; char sex; int age; struct date birthday; } p1, p2;
先声明定义再定义变量
struct person { char name[15]; char sex; int age; struct date birthday; }; struct person p1, p2;
无类型名变量
struct { char name[15]; char sex; int age; struct date birthday; } p1, p2;
访问
结构变量多数情况下需访问到成员而不能整体访问
通过结构变量访问成员
结构变量名 . 成员名
通过指向结构的指针访问成员
(* 指向结构的指针) . 成员名
指向结构的指针 -> 成员名
e.g.
假设有定义
struct date {int month; int day; int year; };
struct person { char name[15]; char sex; int age; date birthday; } p1,*p=&p1;
访问
p1.age = 21;
strcpy (p->name , "Fang Min");
p->name 是字符数组,赋值要用strcpy函数
p->birthday . month = 8;
此处注意用”.”运算,不能用”->”运算
原则
不允许整体输入输出结构变量,必须逐成员输入输出
允许整体赋值及做函数参数
引用成员时若成员本身又属复杂类型,则需逐级找到最低一级成员
成员需遵循同类型普通变量的使用规则,并可参与同类型变量允许的各种运算
初始化
结构变量初始化
各成员的初值按顺序组织在一对花括号中
struct person { char name[15]; char sex; int age; struct date birthday; }; struct person p ={"Tom", 'F' ,18, {12,21,2015} };
成员本身也是结构类型,也组织在一个花括号里
结构数组初始化
每个数组元素都是一个结构变量,组织在一对内层花括号中
所有数组元素需组织在一对外层花括号中
struct student { char name[15]; char num[7]; int score; }p[10] ={ {"Fang Min", "1403235" ,84} , {"Fang Hua", "1403256" ,75} };
例题
#define N 5 struct student { //char mun[5]; char *mun; int score; }c[N]; int max(struct student *ps) { int i,max,imax(0); max=c[0].score; for(i=0;i<N;i++) { if(max<c[i].score) { max=c[i].score; imax=i; } } return(imax); } void main() { int i; struct student *ps; ps=c; cout<<"输入学号,成绩:"<<endl; for(i=0;i<N;i++) { c[i].mun=new char[5]; cin>>c[i].mun>>c[i].score; } cout<<c[max(ps)].mun<<","<<c[max(ps)].score<<endl; for(i=0;i<N;i++) { delete c[i].mun; } system("pause"); }
链表
概念
由若干结点元素组成,结点可在动态运行中生成
组成
头指针
存放一个指针,该地址指向第一个结点
结点
需要处理的实际数据和指向下一结点的指针组成
特点
链接存储的特点是利用指针来表示数据元素之间的逻辑关系
每个结点由数据域data和指针域next组成,指针域指向下一元素的首地址,若不存在则为NULL
结点的物理存储顺序可以不连续
结点的逻辑顺序与物理顺序可以不一致
链表长度可根据需要动态扩充
不能像数组一样按下标随机存取任一元素
结点
结点结构
结点由数据成员和指针成员共同构成,组织在一个结构类型中
struct node { 数据类型 data; struct node *next; };
data可不止一项
定义表头指针
struct node *head;
动态生成结点
向链表中加入新数据时,需创建一个新结点以存放新数据
假设有定义: struct node *p
使用new运算符
p=new node ;
使用malloc函数
p=(struct node *)malloc(sizeof(node));
(struct node *)
将返回值强制转化为指向节点结构的指针类型
malloc( )
求字节数运算
结点的创建过程
假设有定义
struct node { int data; struct node *next; };
创建
p=new node; p->data=10; q=new node; q->data=20; q->next=NULL; p->next=q;
或p=(struct node *)malloc(sizeof(struct node))
释放节点变量空间
删除链表中结点时,应将其占用的存储空间返还系统
deleta p;
释放new运算申请的结点空间
ferr(p);
释放malloc函数申请的结点点空间
结点的访问
对指针p所指向的结点数据域(date)的访问
p -> data
常用
(*p).date
不常用
对指针p所指向的结点指针域(next)的访问
p -> next
常用
(*p).next
不常用
常见操作
创建链表
原理
依次动态创建每个结点,输入该结点的数据,并建立这些结点间前后链接的关系
定义三个指针
head
表头指针
newnode
指向当前动态创建的结点
tail
表尾指针,指向当前链表的最后一个结点
步骤
建立空链表
head=NULL
动态创建新结点,使newnode指向该结点,并向其数据域输入数据
newnode = new node ;
cin>>newnode -> data ;
将newnode所指向的结点插入到链表中
若当前链表为空
newnode所指向的结点成为该链表中的首结点,让head指向该结点
head = newnode ;
若链表非空
将newnode所指向的结点作为最后一个结点加入,将其插在tail指向的结点后边
tail -> next =newnode ;
newnode所指向的结点成为新的表尾结点,移动表尾指针指向该结点
tail = newnode ;
执行 2-4 步 n 次
将最后一个结点的指针域置空
tail -> next =NULL ;
函数实例
struct node *create( int n ) { node *head = NULL ; node *tail , *newnode ; for( int i=0 ; i<n ; i++ ) { newnode = new node ; cin >> newnode -> data ; if(head == NULL) head = newnode ; else tail -> next = newnode ; tail = newnode ; } tail -> next = NULL ; return( head ) ; }
遍历链表
分析
链表中数据的访问通过一个工作指针实现
该指针从表头开始逐一指向后续各结点,每指向一个结点,便通过该指针访问结点的数据域,直到该指针为NULL为止
函数实现
void print( struct node *head) { struct node *p=head ; while ( p != NULL) { cout<<p -> data << '\t' ; p = p -> next ; } }
总结
工作指针移动不用p++是由于链表存储并不物理连续
统计链表结点个数只需设个计数器,随着p的移动计数器逐步+1即可
查找第 i 个结点
分析
需设置一个序号计数器j和一个工作指针p寻找到指定的结点
工作指针p从表头结点开始,顺着链表的链接方向进行查找。 每经过一个结点,计数器j的值增加1。 仅当j==i并且p!= NULL时查找成功;否则查找失败
函数实现
void search( struct node *head , int i ) { int j=1 ; struct node *p=head ; if(i=0) cout<<"illegal argument"; else { while( j !=i & &p!=NULL) { j++; p=p -> next ; } if( j==i & &p!=NULL ) cout<< p->data ; else cout<<"illegal argument"; } }
插入新的结点
分析
一般情况
将结点插入 front 和 behind 之间
newnode->next = behind ; front->next = newnode ;
特殊情况
在表头之前插入
newnode->next = head ; head = newnode ;
在尾结点之后插入
behind->next = newnode ; newnode->next = NULL ;
步骤
设一工作指针behind从表头开始查找待插入位置 (behind之前)
若当前结点不是待插入位置,则将其保存于前指针front中,工作指针移向下一结点
重复第2步至找到待插入位置或到达表尾
根据待插入位置的不同情况执行相应插入操作
函数实现
删除某个结点
分析
被删除结点的后继结点的地址赋给其前趋结点的指针域或表头指针head
无后继结点时,则赋NULL
分类
假定p指向待删除结点,q为其前驱节点
若p==head,则删除第一个结点
head = p->next ; delete p ;
若删除的是中间结点,则应将其后继结点的地址,赋给其前趋结点q的指针域
q->next = p->next ; delete p ;
若删除的是尾结点,则其前趋结点q应成为尾结点
q->next = NULL ;
delete p ;
步骤
设一工作指针p从表头开始查找待删除结点
若当前结点不是待删除结点,则将其保存于前指针q中,工作指针移向下一结点
重复第2步至找到待删除结点或到达表尾
根据待删除结点位置执行相应删除操作
函数实现
node *del(node *head,int n) { node *fro=head,*beh=head; int i=1; if(n==1) { head=head->next; delete fro; } while(beh!=NULL&&i!=n) { fro=beh; beh=beh->next; i++; } if(fro!=NULL) { fro->next=beh->next; delete beh; } else cout<<"cb"; return head; }
文件
文件的概述
数据处理
定义
文件是存储在外存(如硬盘)上的数据集合
每个文件通过一个唯一的文件名来标识
计算机按文件名对文件进行读写等操作
文件名
e.g.
D:\document\file1.txt
文件路径
指明文件在外存中的位置
主文件名
要遵循标识符命名原则
文件后缀(扩展名)
表示文件性质
分类
文本文件(ASCII文件)
把内存中的数据转换成ASCII码,每个字符用一个ASCII码存储
二进制文件
把内存中的数据按其内存中的存储形式不进行格式转换直接存放在文件上
存取方式
顺序存取
每当“打开”文件进行读或写操作时,总是从文件的开头开始,从头到尾顺序地读写;
随机存取
可以通过调用C语言的库函数去指定开始读写的字节号,然后直接对此位置上的数据进行读写操作。
C操作步骤
定义文件类型指针
定义
FILE *文件指针变量
例如
FILE *fp1, *fp2;
FILE是结构体变量,存放每一个被打开文件的有关信息(如缓冲区状态,大小,文件位置等)
需包含stdio.h文件
打开文件
调用fopen材料
文件读写
调用读写函数
对文件的处理通过调用标准输入输出库函数实现
文件操作一般采用“缓冲文件系统”的方式
关闭文件
调用fclose函数
文件的打开与关闭
文件的打开
函数原型
FILE *fopen( char *fame, char *mode)
FILE *fp; fp=fopen("t1.txt","r");
功能说明
按照mode规定的方式,打开由fname指定的文件
参数说明
fname: 字符指针,指向要打开或建立的文件名字符串
mode: 字符指针,指向文件处理方式字符串
返回值
正常返回
被打开文件的文件指针
异常返回
NULL,表示打开操作不成功
模式选择符号
r
以只读方式打开文件,读文件必须存在
w
打开只写文件,若文件存在则清除内容,若不存在则创建该文件。
a
以追加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后。
+表示读/写
b表示打开二进制文件
t表示打开文本文件,不加b默认加t。
r+
以读/写方式打开文件,该文件必须存在
w+
打开可读/写文件,若文件存在则清除内容,若文件不存在则建立该文件。
a+
以追加方式打开可读/写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后。
rb
以只读方式打开一个二进制文件,只允许读数据。
wb
以只写方式打开或新建一个二进制文件,只允许写数据。
ab
加打开一个二进制文件,并在文件末尾写数据。
rb+
以读/写方式打开一个二进制文件,文件必须存在。
wb+
以读/写方式打开或建立一个二进制文件,允许读和写。
ab+
以读/写方式打开一个二进制文件,允许读或在文件末追加数据。
注
文件名可在程序运行时输入,如:
如果文件名直接给出,则路径中的 \ 应写成 \\
如果文件名在程序运行时输入,则路径中的分隔符直接输入字符 \
FILE *fp; char fname[15]; cout<<"Input filename:\n"; cin>>fname; fp = fopen(fname,"r");
文件校验
为保证程序正常运行,需对fopen函数的返回值进行检验,以判断文件是否成功地打开。
形式
if ((fp=fopen(fname, mode)) == NULL) { cout<<"can't open file\n"; exit(1); }
该段程序使得文件打开失败时,显示提示信息,然后调用exit函数结束程序,使用该函数包含文件"stdlib.h"
文件的关闭
函数原型
int fclose( FILE *fp )
功能说明
关闭由fp所指的文件,释放由fp所指的文件类型结构体变量
参数说明
fp:一个已打开文件的文件指针
返回值
正常返回
0
异常返回
EOF(-1),表示文件在关闭时发生错误
注
及时关闭文件,防止数据丢失
文件的读写
文件结束测试函数
函数原型
int feof( FILE *fp )
功能说明
判断文件是否结束
参数说明
fp: 文件指针
返回值
0
假值,表示文件未结束
1
真值,表示文件结束
实例
字符
从文件读取字符
函数原型
int fgetc( FILE *fp )
功能说明
从fp所指文件中读取一个字符,并使文件指针后移一个字符位置
参数说明
fp: 文件指针,指向要读取字符的文件
返回值
正常返回
读取的字符
异常返回
EOF(-1)
返回类型说明
向文件写入字符
函数原型
int fputc( int ch , FILE *fp )
功能说明
把ch中的字符写入fp所指文件当前位置处,并使文件指针后移一个字符位置
参数说明
ch
整型变量,内存要写到文件中的字符
fp
文件指针,指向要在其中写入字符的文件
返回值
正常返回
写入的字符
异常返回
EOF(-1)
字符串
向文件写入字符串
函数原型
int fputs( char *str, FILE *fp )
fputs( a, fp )
功能说明
将str指向的字符串的内容输出到fp所指向文件的当前位置
同时将fp自动向前移动strlen(str)个字符位置
参数说明
str
可以是字符串常量,字符串指针或字符数组名等
fp
文件指针,指向字符串要写入其中的文件
返回值
正常返回
非负整数
异常返回
EOF(-1)
说明
字符串结束符'\0'不输出到文件
不自动在字符串结尾添加换行符
从文件读取字符串
函数原型
char *fgets( char *str, int n, FILE *fp )
功能说明
从由fp指出的文件中读取n-1个字符,
并把它们存放到由str指出的字符数组中去,
最后自动加上一个字符串结束符'\0'
参数说明
str
接收字符串的内存地址,可以是数组名或指针
n
指出要读取字符的个数
fp
文件指针,指向要从中读取字符的文件
数据块
从文件读取数据块
函数原型
int fread( void *buffer, int size, int count, FILE *fp )
功能说明
从文件指针fp所指的文件的当前位置读取字节数为size大小的数据块共count个,存到buffer所指的内存储区中。
参数说明
buffer
指向存放读入数据存储区的首地址的指针
如:主函数中自定义的变量
size
数据块的字节数,即一个数据块的大小
count
一次读入数据块的数量
fp
文件指针,要从中读出数据的文件
返回值
正常返回
实际读取数据块的个数,即count
异常返回
0
向文件写入数据块
函数原型
int fwrite( void *buffer, int size, int count, FILE *fp )
功能说明
将以buffer为起始地址的长度为size的count个数据块输出到文件指针fp所指的位置去
参数说明
buffer
指向存放输出数据存储区的首地址的指针
如:主函数中自定义的变量
size
数据块的字节数,即一个数据块的大小
count
一次读入数据块的数量
fp
文件指针,要从中读出数据的文件
返回值
正常返回
实际输出数据块的个数,即count
异常返回
0
实例
如有定义
float f; double d[10];
把浮点数f写入文件
fwrite( &f, sizeof(float), 1, fp );
从文件中以块形式读一浮点数到变量f中
fread(&f, sizeof(float), 1, fp );
把数组d中所有数写入文件
fwrite( d, sizeof(double), 10, fp );
从文件中读一个数组大小的数据到数组d中
fread( d, sizeof(d), 1, fp );
格式化
向文件格式化写入数据
函数原型
int fprintf( FILE *fp, const char *format, arg_list )
功能说明
将变量表列(arg_list)中的数据,按照format指出的 格式,写入由fp指定的文件
参数说明
fp
文件指针,指向将数据写入的文件
fromat
指向写出数据格式字符串的指针
arg_list
要写入文件的变量表列,各变量之间用逗号分隔
返回值
正常返回
输出的字节数
异常返回
负值
示例
fprintf( fp, "%d%s", 4, "China" );
表示将整数4和字符串“China”写入fp所指文件中
向文件格式化读取数据
函数原型
int fscanf( FILE *fp, const char *format, add_list )
功能说明
按照format指出的格式,从fp指定的文件中读取数据存放至地址表列(add_list)的变量中
参数说明
fp
文件指针,指向读取数据的文件
fromat
指向读取数据格式字符串的指针
arg_list
要存放读取数据的变量的地址表列
返回值
正常返回
成功读取的参数的个数
异常返回
EOF(-1)
示例
fscanf( fp, "%d%d", &x, &y );
表示从fp所指的文件中顺序读出两个整数给变量x和y
随机读写
特点
顺序读写文件只能从头开始,顺序读写各个数据。
随机读写可按需要只读写文件中某些指定的部分
随机读写的关键是要按要求移动位置指针,即进行文件的定位
实现文件定位、移动文件内部位置指针的函数主要有rewind函数和fseek函数
rewind函数
函数原型
void rewind( FILE *fp )
功能说明
使指示文件位置的指针重新回到文件开始
fseek函数
函数原型
int fseek( FILE *fp, long offset, int whence )
功能说明
使文件指针fp移到基于whence的相对位置offset处
参数说明
offset
offset是相对whence的字节位移量,用长整型表示
L后缀表示长整数
whence
whence是移动的基准,常用符号常量表示
返回值
正常
0
异常
-1
示例
fseek(fp, 1234L, SEEK_CUR);
把读写位置从当前位置向后移动1234字节
fseek(fp, 0L, 2);
把读写位置移动到文件尾
类与对象
面向对象的基本概念及特征
基本概念
类
抽象出了一类事物所具有的共性特征,包括属性和行为。
类为程序提供了模板,其操作方法和属性被称为“成员”
对象
类的实例,即将类具体化为一个可以操作的实体
类与对象的概念
类是抽象的概念,系统不为其分配空间,它创建了软件对象的模板
对象是具象的概念,系统为其分配空间,并对其进行操作
类与对象的关系好比数据类型与变量的关系
面向对象的特征
封装性
为保护对象的属性不受外界影响,将其属性和行为这些成员打包在类这样一个软件构件中
继承性
利用现有类派生出新类的过程称为类的继承
原有的类称为父类或基类,新类称为子类或派生类
子类可以继承父类的属性和行为,同时也可以另外定义属于它们自己的属性和行为
多态性
同一消息(或方法)作用在不同对象上产生不同的行为
类的定义
例
成员包括
形式
特征
Circle类相当于一种新的数据类型,包含了数据和对数据的操作
若成员函数在说明部分已定义,则实现部分可省略
访问权限
public(公有)
private(私有)
缺省时为private
protected(保护)
成员函数和数据成员声明的位置没有先后顺序
成员函数可直接操作数据成员;若在函数内部定义与数据成员同名的变量,则操作的是函数内的局部变量
类体中不允许对数据成员初始化
自身类的对象不可以作为自己的成员
类体内只给出成员函数的说明而未给出具体实现时,则在实现部分成员函数名前需加类名和作用域运算符(::)
对象的定义与访问
对象的定义
类名仅提供一种类型定义,只有在定义属于类的对象后,系统才会为其分配空间,进而可以对其进行相关操作
形式
类名 对象名表;
例
Circle c1,*p,c[5];
对象的访问
对象除了赋值、做参数及返回值,其它地方需访问到成员,方式同结构变量的访问
对象成员的访问
对象. 数据成员
对象. 成员函数 (参数表)
通过指向对象的指针访问成员
对象指针->数据成员 (*对象指针).数据成员
对象指针->成员函数(参数表) (*对象指针).成员函数(参数表)
构造函数与析构函数
构造函数
概念
定义一个对象,对系统而言就意味着要创建这个对象,这需要构造函数的支持
对象也可以初始化,这也需要构造函数的支持
特点
是类的一个特殊成员函数,创建对象时需调用该函数;
在创建对象时由系统自动调用,程序中不能直接调用;
函数名同类名,不能指定函数类型,可以带参数;
可定义多个参数个数不同的构造函数,即构造函数允许重载
缺省构造函数
形式
<构造函数名>() { }
无参,无函数体
若没定义过构造函数,则系统自动生成缺省的构造函数
系统中隐含定义的另外一个特殊的缺省构造函数,该函数只有一个参数,且是对某个对象的引用
作用
用已知对象初始化被创建的同类对象
做函数的形参及返回值时创建对象
析构函数
功能
当对象的生存期结束时,通过析构函数释放对象
若一个对象被定义在函数体内,则当该函数结束时,该对象的析构函数被自动调用,对象占用的空间被释放
若一个对象是使用new运算符被动态创建的,则在执行delete运算时,析构函数将会被自动调用,该对象占用的空间被释放
特点
是一个特殊的成员函数,用于释放对象,生存期结束时由系统自动调用,也可由用户调用。
函数名同类名,前面加字符“~” ,不指定类型,无参。
不可重载,即一个类只能定义一个析构函数
缺省构造函数
形式
~<析构函数名>() {}
若用户没定义过析构函数,系统会自动生成缺省形式的析构函数
拷贝构造函数
系统中隐含定义的另外一个特殊的缺省构造函数,该函数只有一个参数,且是对某个对象的引用
作用
用已知对象初始化被创建的同类对象
做函数的形参及返回值时创建对象