C语言学习笔记
linux常用指令
- pwd:查看当前路径
- cd:进入某个文件夹
cd 文件夹名 cd .. ——返回上一级 cd / ——进入根目录 cd /home/ ——进入到相对目录 cd ~ ——进入到当前用户的文件目录下(家目录)
- ls:查看文件目录所包含的文件名
ls -a ——查看文件目录所包含的文件名,包括隐藏文件夹 ls -l ——查看文件目录所包含的文件详细信息
- drwxr-xr-x
符号 权限 r 可读 w 可写 x 可执行 rwx 当前用户权限 r-x 其他用户组权限 r-x 其他用户权限 - mkdir:创建文件夹
mkdir 文件夹名 ——创建文件夹 mkdir 路径/文件名 ——在某一路径下创建文件夹
- touch:创建文件
touch 文件名 ——仅创建文件
- gedit:编辑文本内容
gedit 文件名 ——编辑文件(文件后缀可加可不加)
- rm:删除文件/文件夹
rm 文件名 ——删除文件(文件加后缀) rm -r 文件夹名 ——删除文件夹 rm -f 文件 ——强制删除不询问(一般不用)
- cp:复制文件/文件夹
cp 文件名 目的路径 ——将文件复制到指定目录 cp 文件名 新文件名 ——将文件复制为新文件 cp -r 文件夹 目的路径 ——将文件夹复制到指定目录
- mv:剪切文件/文件夹
mv 文件/文件夹 目标路径 ——将文件/文件夹移动到指定路径
- tar:压缩,解压文件
tar cvf 压缩后的文件名.gz 要压缩的文件路径 ——压缩文件 tar xvf 要解压文件名 ——解压文件 tar xvf 要解压文件名 —C 指定目录 ——解压文件到指定目录
符号 含义 C 压缩文件指令 X 解压文件指令 V 显示压缩解压文件的详细过程 F 后紧跟压缩/解压文件名 - 补充
sudo ——管理权限下放 passwd ——修改用户密码(需要下方权限) su ——切换用户 sudo apt-get update ——更新 sudo apt-get install 插件名 ——安装插件
C语言程序结构
-
linux指令
sudo apt-get install gcc ——安装gcc gcc 文件名(带后缀) ——生成a.out文件 ./a.out ——运行a.out gcc 文件名(带后缀)-o 编译后的文件名 ——生成可执行的编译文件
-
数据类型
RAM:内存,临时保存数据——程序结束/电脑关机——数据丢失 ROM:硬盘,长久保存——不手动删除/电脑不崩溃 printf("%*s",i,"");//*是占位符由i代替指定域宽,和%2d类似。 \t,跳过8个空格,从第8个位置结束,从第9个位置开始.若前面的字节<=7,从第8个位置结束,从第9个位置开始。若前面有8个字符,则从第16个位置结束,从第17个位置开始 被const修饰的是常量 输出: %d ——十进制 %ld ——长整型 %5d ——等宽输出 %c ——字符 %f ——浮点数 %lf ——双浮点数 %.2f ——输出两位小数 %p ——内存地址 %#x ——16进制 %#o ——8进制 输入: scanf(“%d”,&a)
字符常量
转义序列 含义 \ \ \ 字符 ' ' 字符 " " 字符 ? ? 字符 \a 警报铃声 \b 退格键 \f 换页符 \n 换行符 \r 回车 \t 水平制表符 \v 垂直制表符 \ooo 一到三位的八进制数 \xhh . . . 一个或多个数字的十六进制数 -
运算符
单目运算符,双目运算符,三目运算符(条件运算符)
自增自减运算符 a++与++a的区别: 假设a=5,那么: b=a++; //相当于b=a; a=a+1; 结果是b=5, a=6 b=++a; //相当于a=a+1; b=a; 结果是b=6, a=6
逻辑运算符
运算符 描述 实例 && 称为逻辑与运算符。两个都为真,则为真。 只要第一个条件为假,第二个条件不运行。 || 称为逻辑或运算符。一个为真,则为真。 只要第一个条件为真,程序不运行。 ! 称为逻辑非运算符。真为假,假为真。 杂项运算符
运算符 描述 实例 sizeof() 返回变量的大小。 sizeof(a) 将返回 4,其中 a 是整数。 & 返回变量的地址。 &a; 将给出变量的实际地址。 * 指向一个变量。 *a; 将指向一个变量。 ? : 条件表达式 如果条件为真 ? 则值为 X : 否则值为 Y 位运算
&:与运算,全1为1,遇到0为0
|:或运算,全0为0,遇1为1
^:异或运算:相同为0,不同为1
~:取反
<<:左移后的数据=原数据*2的位移次方
>>:右移后的数据=原数据/2的位移次方(取商)运算符优先级:初等运算符(()、[])
流程控制语句(9个语句)
- if(){} else{}
- switch(){} case : default:
- while(){}:先判断后执行,循环操作可能一个都不会执行;多用于循环次数未知的场景。
- d0{} while():先执行后判断
- for(){}:多用于循环次数已知
- continue
- break
- return
- goto
数组
-
一维数组:
1. int num[3]={1,2,3}——定义时指明长度 2. int num[]={1,2,3}——在初始化时,根据初始化的数据多少决定数组长度 3. int num[3]={5}——数据不全的情况下后续数值为0;nun[0]=3,num[1]=0,num[2]=0; 冒泡排序: N个数据来排序 两两相比小靠前 外层循环N-1 内层循环N-1-i
-
二维(多维)数组
int num[2][3]={1,2,3,4,5,6}; 或者 int num[2][3]={{1,2},{3,4}{5,6}}; 或者 int num[][3]={1,2,3,4,5,6}; char num[][5]={"abc","def","hij"}; 行长度可以不指定,但是列长度必须指定
-
字符数组
char ch[5]=['a','b','c','d','e']; char c[]=["hello world"]; printf("%S",c);——输出结果为hello world char c[]=["hello\0 world"]; printf("%s",c):——输出结果为hello char c[1024]; scanf("%s",c);——不需要加取地址符
-
字符串常用函数
char ch; getchar()——输入一个字符 putchar()——输出一个字符 getc()——输入一个字符(能接收空格) putc()——输出一个字符 scanf()——输入(空格作为结束输入标志) printf()——输出 strlen()——获取字符串长度 strcat(x,y)——字符串拼接,拼接后为x-y strcpy(x,y)——字符串复制,复制y到字符串x strncpy(x,y,n)——复制n个字符 strcmp(x,y)——x-y 如果x,y相同则返回0,X<Y返回小于0,X>Y返回大于0
指针
指针属于数据类型——存储内存地址
内存地址以十六进制出现
指针类型——类型 * 比如: int *
指针的打印:%p
int *p——野指针(×)
int *p=NULL——指针指向空地址
指针指向某个变量的地址
int *p=#&——取地址
指针类型的大小 sizeof() ——固定8字节
指针指向多个变量,通过指针改变变量的值
int(*)——指针数组
int m[2][3]用一维数组表示如下
int a[3]={1,2,3};
int b[3]={4,5,6};
int c={&a,&b};
int *p=m;
p=&a;
*p=a;
*(*p+1)=a[1];
p+1=&b;
*(p+1)=b;
*(*(p+1)+1)=b[1];
m[i][j]=*(*(p+i)+j);
二维数组指针定义
int a[2][3];
int (*p)[3]=a;
p++:先输出p,然后地址加1
++*p:先解地址,然后输出值加1
函数
函数定义:类型 函数名(类型 形参){函数体}
- 类型——返回值类型——return
char int float double int* void(无类型,无返回值) - 函数名——标识符
- 形参——形式参数
- 没有集体值,在函数中起到占位,传递数据的作业
- 无参无返回
- void fun (void){}
- 无参有返回
- int fun (){return 0;}
- 有参无返回
- void fun(int num){}
- 有参有返回
- int fun(int num){return num}
- 函数体
- 函数要实现的功能代码
函数声明:告诉程序有这个函数的存在
一般在main函数上面
返回值类型 函数名(形参);
int fun(int num);
void fun(void);
函数调用
- 实参——实际参数
- 函数名()
- int num = 函数名()
局部变量和全局变量
- 定义位置
- 全局变量——函数外面
- 局部变量——函数里面
- 初始值
- 全局变量——默认初始值
- 局部变量——必须给初始值,不给默认随机产生
- 作用域
- 全局变量——整个程序
- 局部变量——所在的{}内使用
- 生命周期
- 全局变量——程序结束
- 所在{}结束
- 能否提高局部变量的生命周期
static——静态- 提前预加载
- 提高局部变量的声明周期,但不能提高其作用域
C语言五大区
- 栈区——先入后出——自动释放 ————由编译器自动分配释放
- 堆区——手动释放 ————由程序员分配释放
- 代码区——程序要执行的代码 ————存放函数体的二进制代码
- 全局区/静态区 ————全局变量和静态变量
- 文字常量区 ————常量字符串
补充
extern 在调用外部函数时,
外部变量必须是全局变量
extern在调用时 可以省略不写
外部函数不想被本程序外的所有程序调用——用关键字 static
结构体
- 结构体作用:存储不同类型的数据
- 结构体是什么:自定义数据类型
- 如何定义:struct 类型名{结构体成员变量}
注意:声明结构体类型结尾加“;”
在声明结构体类型时不开辟空间大小 - 结构体类型大小
第一种方法:sizeof()
第二种方法:所有成员变量的数据类型空间大小相加,最终的空间大小是最大成员变量空间大小的整数倍;(成员变量空间大小按顺序定义)
第三种方法:- 先找到成员变量中空间大小最大的,然后和默认对齐进行比较,取其最小值。(默认对齐:8字节)
- 第一个成员变量开始位置,其后每一个变量的开始位置,是其空间大小的整数倍,不够整数倍补齐
- 最终的空间大小要使成员中变量中空间大小最大的整数倍,不够补齐
- 结构体类型使用
- 定义结构体类型变量
//定义学生类型结构体 struct student { int stuNo; char name; double score; }; 或 struct student { int stuNo; char name; double score; }stu; //定义结构体类型变量 struct student stu; // struct { int stuNo; char name; double score; }stu;//定义结构体变量(仅一次)
- 结构体类型变量初始化
stu.stuNo=1001; strcpy(stu.name,"jack"); stu.score=100; printf("%d",stu.stuNo); 或 //定义结构体变量同时进行赋值 struct student stu={1001,"jack",100}; 或 //声明结构体类型同时定义结构体变量并初始化 struct student { int stuNo; char name; double score; }stu={1001,"jack",100}; 或 //给部分成员变量赋值 struct student { int stuNo; char name; double score; }stu={.stuNo=1001,.score=100};
- 结构体变量的使用
printf("%d",stu.stuNo); //结构体类型数组 ——类型 变量名[长度]=初始值 struct student stus[3]= { {1001,"jack",120}, {1002,"maci",130}, {1003,"coco",100} } int main() { for(int i=0;i<3;i++) { printf("%d",stus[i].stuNo); } return 0; } //结构体类型指针 ——类型名 *变量名 //结构体类型指针指向成员变量 ->成员变量 struct student *p=NULL; int main() { p=&stu; scanf("%d",&p->stuNo); scanf("%s",p->name); printf("%d %s",p->stuNo,p->name); return 0; } //关键字typedef——重定义数据类型名——(别名) typedef struct student { int stuNo; char name; double score; }student; student stu; student *p=NULL;
共用体
多个变量共用同一个存储空间
共用体定义——union
union stu
{
char a;
int b;
};
共用体大小:最大成员变量(基本数据类型)的空间大小的整数倍
共用体变量的使用:共用体共用同一个存储空间,因此只需要给其中一个成员变量进行赋值即可
大小端存储
- 计算机存储地址,地址存数据
- 计算机默认是小端存储
- 小端:地址的低位存数据的低位,地址的高位存数据的高位
- 大端:地址的低位存数据的高位,地址的高位存数据的低位
枚举
枚举的定义——enum
enum{ADD,ABB,ACC};
- 成员名字随便起,建议全部大写
- 成员的值,默认从0开始依次递增,默认是int类型的值
- 初始值可以改变
链表
链表的作用
用来存储地址不连续的数据集合——用的时候手动开辟空间
如何开辟空间
动态开辟空间——malloc(形参)
形参——指定开辟空间大小
p=(int *)malloc(sizeof(int));
开辟多个同类型空间
p=(int *)malloc(10*sizeof(int));
释放空间——free()
free(p)
初始化函数——memset
void *memset(初始化空间的首地址,填0,初始化多大的空间);
memset(p,0,sizeof(int));
链表定义
单向链表
数据域
地址域
单项循环
双向链表
双向循环链表
文件操作
文件:实现数据存储的载体
linux下一切皆文件
标准输入文件描述符——stdin——对应键盘
标准输出文件描述符——stdout——对应屏幕
标准出错文件描述符——stderr——对应屏幕
分类:
- 按照逻辑结构:文本(ASCII)文件,二进制文件
- 按照用途分:系统文件,库文件,用户文件
- linux下的文件分类
字符 含义 d 目录文件 - 普通文件 l 链接文件 p 管道文件 s 套接字文件 c 字符设备文件 b 块设备文件
文件操作函数
man 手册 推出:q
man 1 指令
man 2 系统相关函数
man 3 C语言标准库函数
1. fopen——打开文件
FILE *fopen(文件路径,打开模式)
FILE *名称=fopen(文件路径,打开模式)
模式:
1. “r”:只读,文件不存在,打开失败
2. “w”:只写,文件不存在,创建打开,存在,清空写
3. “a”:只写,文件不存在,创建打开,存在,追加写
4. “r+”:读写,文件不存在,打开失败
5. “w+”:读写,文件不存在,创建打开,存在,清空写
6. “a+”:读写,文件不存在,创建打开,存在,追加写
函数返回值:
成功:返回名称
失败:返回NULL
2. fclose——关闭文件
fclose(fopen的名称)
返回值:关闭成功返回0,失败返回-1
插入:perror——打印离他最近的函数执行失败的原因
perror(const char *s)
s:错误标题
3. 文件的读写函数
1. fputc——单字符写入
fputc(char类型单字符,fopen的名称)
返回值:返回写入的字符
2. fgetc——单字符读取
char ch=fgetc(fopen的名称)
rewind——使光标回到文件开头
rewind(fopen的名称)
3. fputs——字符串写入
fputs(要写入的字符串的首地址,fopen的名称)
返回值:成功返回一个非负数,失败返回EOF(-1)
4. fgets——字符串的读取
fgets(读取到的内容存放的地址,读取多大,fopen的名称)
5. fprintf——格式化写入
fprintf(fopen名称,"%d",a);
6. fscanf——格式化读取
fscanf(fopen名称,"%d",&a);
fprintf和fscanf格式必须一至才能准确读取
7. fwrite——块写
fwrite(写入到文件中的首地址,一次写入多大字节,写入几次,fopen名称)
返回值 真正写入的次数
8. fread——块读
fread(读取到的内容存放的首地址,一次都多大字节,读取几次,fopen名称)
返回值:真正读取到的次数
4. 其他函数
1. fseek——光标偏移函数
fseek(fp,偏移量,偏移量的起始位置)
偏移量:+表示往文件末尾便宜,-表示往文件起始位置偏移
起始位置:0——SEEK_SET:文件开头,1——SEEK_CUR:当前位置,2——SEEK_END:文件末尾
2. ftell——计算文件当前位置到文件开头的偏移量
ftell()
3. feof——判断文件是否到达文件末尾
feof(fp):到结尾返回非0值,否则返回0
不会造成光标偏移
4. rewind——光标回到起始位置
rewind(fp);
栈
先进后出
队列
先进先出
树
有序树:左右子树不能交换
二叉树:时有序树,左右子树是严格区分并且不能随意颠倒
满二叉树:一颗深度位k且有2k-1个节点的二叉树
完全二叉树:至多只有最下面的两层上节点的度数可以小于2,并且最下一层的节点都集中在该层最左边的若干位置上
模块化编程
预处理->转汇编->转二进制->链接(链接库)
预处理命令
1. 头文件包含
#include<xxx.h>:在系统默认路径找.h文件
#include"xxx.h":在当前路径下找.h文件,找不到的话,再去系统默认路径下找该.h文件
2. 宏定义
1. 宏定义:#define 宏名 宏体 ——原样替换
对于开发人员:找简单的宏名代替复杂的宏体
对于计算机:在预处理阶段,已经将宏名用宏体替换了
2. 宏定义:#define 宏名
#undef 宏名:取消已定义的宏
3. 条件编译
#if:如果条件为真,则编译下面代码
#elif:类比else if
#ifdef:如果宏已经定义,则编译下面代码
#idndef:如果宏没有定义,则编译下面代码
#endif:结束一个#if...#条件编译块
模块化编程
.c:变量的定义,函数的定义
.h:函数的声明,头文件包含,结构体数据类型的定义,枚举,宏定义
.h格式:#ifdef_XXX_H
#define_XXX_H
函数的声明,头文件包含,结构体数据类型的定义,美剧,宏定义
#endif
这三行的功能:防止重复头文件展开