C语言笔记(总结)
姚 翔
VI编辑器
vi :打开文件,如果文件不存在则创建文件
vim编辑器三种模式:命令模式、插入模式(编辑模式)、底行模式
打开文件默认处于命令模式
命令模式:复制、粘贴、剪切等
nyy:复制光标所在n行内容
p:粘贴
ndd:剪切光标所在n行内容
u:撤销
插入模式:从命令行输入a、i、o进入插入模式
a:从光标后开始插入
i:从光标当前位置开始插入
o:从光标下一行开始插入
ESC切换到命令模式
底行模式:保存文件等,从命令行输入冒号(shift + ;)
w:写入保存
q:退出文件
wq:保存并退出
x:保存并退出
!:强制执行
gcc + 文件名:编译源文件
./a.out:执行程序
计算数据
数值数据:计算机可以直接用来运算的数据
例:十进制、二进制、八进制、十六进制
非数值数据:计算机不能直接用来运算的数据
例:字符、符号等
man ascii
0 — ‘\0’
10 — ‘\n’
32 — ’ ’ 空格
48 — ‘0’
65 — ‘A’
97 — ‘a’
标识符的命名规则:
1.用数字、字母、下划线
2.不能以数字开头
3.不能和关键字重名
输入输出
标准输出 printf
把输出表的数据按照格式控制符的样式进行输出到终端
printf("格式控制串",输出表);
格式控制串:格式控制符 + 普通字符
普通字符原样输出
格式控制符:
%d:十进制整数
%c:字符形式
%s:字符串
%p:地址
%f:浮点型数据
%o:八进制
%x:十六进制
%%:一个%本身
修饰符
标准输入 scanf
晚补习2
标准输出函数 printf
printf("格式控制串",输出表);
格式控制串:格式控制符 + 普通字符
普通字符原样输出
格式控制符:
%d:十进制整数
%c:字符形式
%s:字符串
%p:地址
%f:浮点型数据
%o:八进制
%x:十六进制
%%:一个%本身
修饰符:
m:输出域宽,数据长度<m显示空余位置,否则原样输出
.n:对小数使用指定输出小数个数为n个
对字符串使用指定输出字符个数
-:修改为左对齐
l:提升输出精度
标准输入 scanf
scanf("格式控制串",地址表);
格式控制串:格式控制符
格式控制符:
%d:十进制整数
%c:字符形式
%s:字符串
%f:浮点型数据
%o:八进制
%x:十六进制
修饰符:
*:抑制符
m:输入域宽
h:降低输入精度
l:提升输入精度
scanf结束一次输入的条件:
1.空白符(空格、回车、制表符)
2.遇非法输入
3.遇宽度结束
脏字符:获取字符数据时不必要的字符数据
1.抑制符处理
2.getchar处理
3.空白符处理
字符输入函数 getchar
返回获取到的一个字符
字符输出函数 putchar
char a;
a = getchar();
putchar(a);
putchar(65);
putchar(10);
putchar('#');
putchar('\n');
晚补习3
控制语句
顺序结构、选择结构、循环结构
选择结构
if…else
if(表达式)
{
语句块;
}
if(表达式)
{
语句块;
}
else
{
语句块;
}
if(表达式)
{
语句块;
}
else if(表达式)
{
语句块;
}
else if(表达式)
{
语句块;
}
else
{
语句块;
}
执行顺序:判断if里面的表达式结果是否为真,为真则执行对应的语句块;如果为假则向下判断其他表达式,如果都为假则执行else下的语句块
注意:
1. 一定是if开始
2. 如果有else就一定是最后一个
3. 整个if结构之间不能参杂其它语句
4. 整个if结构中最多执行一个语句块
switch…case
switch(表达式)
{
case 常量表达式1:
语句块1;
break;
case 常量表达式2:
语句块2;
break;
case 常量表达式3:
语句块3;
break;
default:
}
执行顺序:判断表达式和常量表达式的结果,相同时进入执行对应的语句块,直到break语句退出结构,如果没有break语句继续向下执行语句块
注意:
- swtich…case 可以执行多个语句块
- break语句的合理使用
循环结构
while
while(表达式)
{
循环体;
}
执行顺序:判断表达式结果是否为真,为真则执行一次循环体后再次判断,为假则退出循环
ctrl + c :强制结束进程
死循环
while(1);
do…while
do
{
循环体;
}while(表达式);
执行顺序:先执行一次循环体,判断表达式结果是否为真,为真则执行一次循环体后再次判断,为假则退出循环
注意:do…while至少会执行一次
for
for(表达式1;表达式2;表达式3)
{
循环体;
}
执行顺序:先执行表达式1(只执行一次),判断表达式2的结果,结果为真则执行一次循环体后再执行表达式3,再次判断表达式2;结果为假退出循环
数组
数组是用户自定义数据类型,用来存储大量同类型数据,地址上连续
定义
存储类型 数据类型 变量名[元素个数];
存储类型:atuo、register、static、exturn
元素个数:能够存储的最大元素个数
例:
auto int a[10];//定义一个名为a的数组,可以存储10个int数据
char b[1024];//定义一个名为b的数组可以存储1024个char数据
初始化
初始化:定义的同时的赋值
完全初始化:
int arr[10] = {12,34,567,25,67,345,67,3546,67,23};
未完全初始化:
int arr_1[10] = {12,345,44};//未赋值部分是0
数组元素的访问
数组名[元素下标];
下标:下标从0开始,最大为n-1
例:
arr[5];//345
arr[0]=21;
注意:数组只能一个一个元素访问,不能多个元素一起访问
晚补习4
字符数组
字符串:由一个或多个字符组成,用""包含,末尾由’\0’
char buf[20] = {'a','3','?'};
例:
'a'//字符a
"a"//字符串a
""//
动态开辟二维数组
int **arr2 = (int **)malloc(sizeof(int *)*2);
for(int i=0;i<2;i++)
{
arr2[i] = (int *)malloc(sizeof(int)*3);
}
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
arr2[i][j] = i+j;
}
}
指针
计算机内存空间由多个内存单元组成,每个内存单元由一个或多个字节组成,每个字节都有一个编号,这个编号叫做地址,指针就是地址
使用指针访问变量是间接访问
指针变量定义
数据类型 *指针变量名;
数据类型:指向的数据的数据类型
*:标识变量是指针变量
例:
int *p;//定义一个整型指针变量p,可以使用地址及以后4个字节空间
char *q;//定义一个字符型指针变量q,可以使用地址及以后1个字节空间
long *m;//定义一个浮点型指针变量m,可以使用地址及以后8个字节空间
int a = 258;//由两个字节组成0 0 1 2
int *q = &a;
char *p = (char *)&a;
printf("%p,%p,%p\n",p,&a,q);//p==q==&a
printf("*q:%d\n",*q);//258
printf("*p:%d\n",*p);//2
printf("*(p+1):%d\n",*(p+1));//1
指针的访问
*:
1. 定义变量时标识变量是指针变量
2. 乘法
3. 取内容,对地址使用得到该地址空间的数据
&:
1. 位与
2. 取地址
例:
int a;
a = 100;//直接访问
int * p = &a;//取a的地址编号存放在p里面
*p = 200;//间接访问,将数据存放进p表示的地址空间中
int c = *p + 20;
指针的运算
指针和指针只有减法,结果是两个地址之间相差的数据个数
指针和整数运算
指针偏移n个数据单位
p + n/p - n;
p++/p–;
特殊指针
野指针:定义指针变量不赋值
空指针:指向零地址空间的指针,防止野指针出现
空类型指针:使用空类型指针前要强制转换
注意:不能直接使用特殊指针
晚补习5
指针和数组
int arr[10];
srand(time(NULL));
for(int i=0;i<10;i++)
{
arr[i] = rand()%100;
printf("%d ",arr[i]);
}
puts("");
int *p = arr;//&arr[0] == arr 数组名是数组首地址,也是数组首元素地址
printf("*p=%d\n",*p);
printf("*arr=%d\n",*arr);
printf("*(arr+2)=%d\n",*(arr+2));
printf("p[0]=%d\n",p[0]);
printf("*p+9=%d\n",*p+9);
printf("*(p+9)=%d\n",*(p+9));
printf("p[9]=%d\n",p[9]);
printf("9[p]=%d\n",9[p]);//a[b] -> *(a+b)
p[n] == *(p+n)
指针和二维数组(行指针)
int arr[3][5];
srand(time(NULL));
for(int i=0;i<3;i++)
{
for(int j=0;j<5;j++)
{
arr[i][j] = rand()%100;
printf("%-3d",arr[i][j]);
}
puts("");
}
int (*p)[5] = arr;//二维数组名是行指针,代表首行
printf("%p\n",arr);
printf("%p\n",arr+1);//偏移一行数据20个字节
printf("%p\n",&arr);
printf("%p\n",&arr+1);//偏移一整个数组空间60个字节
printf("p[0][0]=%d\n",p[0][0]);
printf("p[1][2]=%d\n",p[1][2]);
printf("*(*(p+1)+2)=%d\n",*(*(p+1)+2));
printf("(*(p+1))[2]=%d\n",(*(p+1))[2]);
int *q = &arr[0][0];
printf("*(q+7)=%d\n",*(q+7));
指针数组
数组里存放的元素的地址数据
字符指针
char *p = "hello world";//hello world是字符串常量不能改变
//*(p+3) = 'n';
函数
实现特定功能的代码模块
定义
数据类型 函数名(形式参数1,形式参数2,...)
{
函数体;
return 返回值;//可以没有
}
数据类型:返回值的数据类型
形式参数:定义函数时指定参数类型
int func(int a,char b,float c)
{
//高级功能
return a+b+c;
}
调用
函数名(参数1,参数2,...);
声明
声明函数位置,让函数可见,能被主函数发现
声明在主函数之上/头文件之中