前言:期末考试即将来临,出于复习的目的,做此博客以回顾c语言帮助我的知识点回顾。
目录
- ① 32个关键字与常见ASCII码
② 逻辑运算符和算术运算符
③ 语法结构
④ 函数
⑤ 数组与指针
⑥ 结构体与链表
⑦ 文件处理操作
① 32个关键字与常见ASCII码
32个关键字
1.数据类型(相对于三十二位操作系统而言):char(1字节,字符类型)、int(4字节,整数类型)、short(4字节,整数类型,基本不会用到)、long(4字节,整数类型,基本不会用到)、longlong(8字节,整数类型)、float(4字节,浮点数类型-单精度)、double(8字节,浮点数类型-双精度)、signed(前缀,有符号数)、unsigned(前缀,无符号数)、void(抽象概念,无类型)、enum(枚举类型,基本不会用到)、struct(结构体类型)、union(共用体,基本不会用到)
2.控制语句:for(循环),do、while(循环),while(循环),break,continue,switch(选择)、case、default,if、else(条件),goto(跳转,基本不用),return
3.存储类型:auto(基本不用)、extern(外部变量)、register(被弃用)、static(静态变量)
4.其它功能:const(前缀,只读变量),sizeof(计算存储空间)、typedef(给数据类型取别名)、volatile(类型修饰符,现阶段不会用到)
常见ASCII码
十进制数 | 字符 | 十进制数 | 字符 |
48~57 | 0~9 | 65~90 | A~Z |
97~122 | a~z |
10 | 换行符 | 32 | space(空格) |
② 逻辑运算符和算术运算符
逻辑运算符
~ | 反运算符 | 二进制对应位数取反(即0变1,1变0), 公式:~x = -(x+1) |
& | 位与运算符 | 两个二进制数对应位值都为1时,结果对应位值为1,否则为0 |
| | 位或运算符 | 两个二进制数对应位值存在一个以上为1,结果对应位值为1,否则为0 |
^ | 位异运算符 | 两个二进制二进制数对应位值不同时,结果对应值为1,否则为0 |
a ?b :c :三目运算符(a、b、c皆为表达式)
理解:先对表达式a判断,如果成立则执行b,否则执行c
a && b:双目运算符(a、b皆为表达式)
理解:逻辑和,先判断a、b是否成立,如果都成立则结果为真,可以理解为返回1;否则为假,返回0
a || b:双目运算符
理解:逻辑或,先判断a、b是否成立,存在一个以上成立则结果为真,可以理解为返回结果1;否则为假,返回0;
!a:单目运算符
理解:逻辑非,用于逆转操作数的逻辑状态,即条件为真则逻辑非运算符使其为假
算术运算符:
移位运算(二目运算符): >>x 右移x位 <<x 左移x位
eg: 对于a=0100(2),a>>2 ,此时a会变成0001(2)
优先级:‘~’ 大于 ‘<<’ ‘>>’ 大于 ‘&’ 大于 ‘^’ 大于 ‘|’
③ 语法结构
条件语句
if语句:
if{
语句/语句块;
}
循环语句(3种)
for(变量初始化;判断条件;迭代效果) //常用,先判断再执行语句
{
(判断条件)
(变量初始化)
循环体;
(迭代效果)
}
do{
循环体;
}while(判断条件); //先执行一次语句再判断
while(判断条件) //先判断再执行语句
{
循环体;
}
选择语句
switch(整型表达式){
case(整型数据): //判断整型表达式的值与整型数据是否相等
……;
(break;) //如果不添加break且判断成立,则继续往下执行(注意:下面 的case不用再判断!);添加了break,则语句终止,跳出switch语句。
……
case(整型数据):
同上;
default :
……; //默认会执行该语句,除非在此之前已经break跳出switch语句
}
④ 函数
一般而言:函数的声明落于main函数之前;函数的定义放在main函数之后。也可在main函数前不声明直接定义函数,效果一样。
结构:
<头文件>
函数返回值的数据类型 函数名 (传入参数的数据类型)
eg:int hanshu(int a,char b); --- 括号里的a,b可写可不写,为了规范还是写比较好。
int main(void)
{
;
}
int hanshu(int a,char b)
{
定义;
}
注意:函数声明中的变量a和b是形参,可以理解为主函数传入两个值的副本,这里的a和b只是传入参数的值,不是参数本身,(可以理解为把两个参数的值分别赋给a和b),所以在函数名为hanshu的函数中,对a和b进行一顿操作后,并不会影响从main函数传入的两个参数的实际值,所以这也是为什么函数声明中a和b与main函数调用’hanshu‘这个函数时传入参数的参数名可以不同,因为两者没有本质上的联系。
·想通过调用函数改变传入参数的值/main函数里变量的值得用指针。
⑤ 数组与指针
·首先要知道数组与指针的微妙关系。
其实数组名就是指针。
·数组是一片连续的空间,而数组名是指针的首地址,eg:char a[10];char * p;p=a(而不是p=&a,这是因为a本身就是一个地址)。(等效操作:*(p+n)=a[n])
·指针变量指向对象的地址,int *p,p是指针变量名,此时有一个int类型的a,另p=&a,即让指针变量p指向a的地址。
·需要知道的是:’*‘是解地址符,上面有p=&a,则通过使用’*p‘可以改变a的值,函数通过指针改变main函数中的实际值的方式就是如此。
int **q,二级指针,上面有一级指针p(int *p)指向a的地址(p=&a),如果此时让二级指针q指向p(q=&p),则q指向一级指针变量p的地址,通过*q就可以改变p的指向,就好比p本来指向变量a,这时我可以*q=&b,让p指向变量b的地址,还可以**q=……,改变b的值。
(二级指针在链表和函数都用到了)
另外对于数组:
可分为静态数组与动态数组
静态即常见的 数据类型 数组名 [数组大小] ;
动态则需要分配,我常用malloc()函数 ---对应头文件#include <stdlib.h>
在与用户交互过程,我希望等用户输入具体要求后再创造相应大小的数组,此时就需要用到动态分配,如果是整型 则是 int *数组名=(int *)malloc(sizeof(int)* 输入的值);
注意:动态分配申请的内存在程序结束后系统不会帮你自动还回去,要手动free掉,所以free这一步操作至关重要,不要省去,最好在malloc时候就赶紧在main函数的最后加上free()。
多维数组:现阶段也就到二维吧,一般用于解决矩阵类型题目,或者‘句子与单词‘这种包含关系的题目,对于int a[n][m],可理解为外层是n个盒子,这n个盒子里面有m个小球,那你也可这么认为,n个单词,单词对应m个字母。二维数组也可动态分配内存,需要用到for循环语句逐个malloc
结构体与链表
结构体:抽象数据类型,当要集合多种基础数据类型时,就用它来实现
struct{
各种数据类型;
}
main函数中要访问struct中的某项数据,需要用'.'运算符实现,跟指针的'*'有点异曲同工之妙。
要区分结构体类型和结构体变量名。
结构体类型可以有多个,每个类型也可以有很多个变量名。
声明手段:struct 类型名{
;}变量名
或者先声明 struct 类型名{
;} 再在main函数中struct 类型名 变量名,以此声明结构体变量。
是不是觉得 struct 类型名 变量名声明结构体变量太冗杂。
那么可以利用typedef来方便结构体声明操作
首先在声明结构体变量前,可以typedef 类型名 新类型名,然后直接 新类型名 变量名声明结构体变量即可,省去了个'struct'。同理可以 typedef struct 原类型名{;}新类型名,在后面直接新类型名 变量名声明变量即可。
链表,不过就是结构体里面多了个指针,指针指向另一个同类型结构体,每个同类型结构体可以看成是一个结点,通过指针,将结点串在一起,如果最后一个结点的指针指向头结点,那么这个链表就变成了环形,如果指向空(NULL)那么就是单向链表。
链表的操作:插入,删除,遍历,销毁,清空。
链表需要理解结构体,指针,函数,动态分配。
⑦ 文件处理操作
打开文件:
FILE *fopen(文件名,打开方式);
打开方式
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。程序会从文件的开头写入内容。如果文件存在,则写入的新内容会覆盖原有的内容。 |
a | 打开一个文本文件,追加模式写入内容。文件不存在,则会创建一个新文件。在这里,程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。文件存在,则新内容会覆盖原有内容,不存在则创建一个新文件 |
a+ | 打开一个文本文件,允许读写文件。文件不存在,则创建一个新文件,读取会从文件的开头开始,写入只能是追加模式 |
关闭文件
fclose(文件指针);
在进行文件操作时候,打开文件后先判断文件是否打开成功,代码如下:
FILE *fp;
fp=fopen(文件名,打开方式);
if(fp==NULL)
{
perror(”open file fuiled“); //perror函数会说明打开失败的原因,一般是文件不存在。
return;
}
文件读写
fputs
函数原型为:
int fputs(const char *str, FILE *stream);
fprintf
函数原型为:
int fprintf(FILE *stream, const char *format, ...);
如果只需要简单地输出一些字符串,那么 fputs
函数会更加适合;如果需要进行格式化输出,或者输出更复杂的数据类型,则可以选择使用 fprintf
函数。
fgets
函数:
原型:char *fgets(char *str, int n, FILE *stream)
fscanf
函数:
原型:int fscanf(FILE *stream, const char *format, ...)
fgets
适用于逐行读取文件内容且处理相对简单的情况,而 fscanf
则更适用于根据指定的格式从文件中读取各种类型的数据。具体使用哪个函数取决于文件的结构和需求的灵活性。