一.初识C语言
1.可能用到的ASCII码值
ACSII码值 | 对应字符 |
048 | 0 |
057 | 9 |
065 | A |
090 | Z |
097 | a |
122 | z |
2.常见运算符优先级问题
‘[ ]’ > ' * ' |
‘ * ’ > ' + ' |
‘ --> ’ > ' ++ ' |
‘ ++ ’ >' + ' |
二.运算符,表达式与控制流
1.逗号表达式 (其实考的是优先级问题)
优先级:括号>赋值号>逗号
整个逗号表达式是从左向右依次执行的,表达式最终的值为最后一个语句的值
#include<stdio.h>
main( )
{ int a=1, b=1, c;
c=a++, b++, ++b; //优先级问题,逗号优先级最低
printf(“a=%d,b=%d,c=%d\n”,a,b,c);
}
运行结果:2,3,1
#include<stdio.h>
main( )
{ int a=1, b=1, c;
c=(a++, b++, ++b); //由于括号优先级高,所以c等于整个逗号表达式的值
printf(“a=%d,b=%d,c=%d\n”,a,b,c);
}
运行结果:2,3,3
2.短路效应
两种短路情况 &&左侧为假,||左侧为真
int main()
{
int x,y,z;
x=y=z=-1;
++x&&++y||++z;
printf("%d,%d,%d\n",x,y,z);
运行结果:0,-1,0
int main()
{
int x,y,z;
x=y=z=-1;
++x||++y&&++z;
printf("%d,%d,%d\n",x,y,z);
运行结果:0,0,-1
int main()
{
int x, y, z;
x = y = z = -1;
++x && ++y && ++z;
printf("%d,%d,%d\n", x, y, z);
}
运行结果:0,-1,-1
#include<stdio.h>
int main()
{
int x, y, z;
x = y = z = -1;
++x || ++y || ++z;
printf("%d,%d,%d\n", x, y, z);
}
运行结果:0, 0, 0
3.重要的控制/转义字符
转义字符 | 表达意义 |
%c | 字符型 |
%s | 字符串 |
%5d | 空5格输出一个整形变量 |
%.2d | 输出保留了两位小数的整形变量 |
%5.2d | 每空5格输出一个保留了2位小数的整形变量 |
\0 | 字符串的结束符 |
4.字符输入输出函数
getchar | 从键盘输入一个字符,存入字符变量中(若一次性输入多个字符,则字符变量只获取第一个字符) |
putchar | 输出字符变量a的值 |
main()
{
char c;
c=getchar(); //getchar每次只接受一个字符
while(c!=‘?’)
{
putchar(c);
c=getchar();
}
}
当输入abcde?fg时,可以看到c只获得了第一个字符a
当再一次getchar时,c则获取到了下一个字符b,以此类推。
5.scanf函数和gets函数的区别
scanf函数与空格就结束输入,gets函数遇空格不会结束输入
若键盘输入为:abcde fg<CR>
int main()
{
char c[10];
scanf("%s",c); //scanf不认空格
printf("c=%s",c);
}
运行结果:c=abcde
三.分支
1.if与else的配对问题
关键:else与它上方离它最近的if配对
int main()
{
int a=2,b=-1,c=2;
if(a<b)
if(b<0)
c=0;
else //这里的else与上方if(b<0)配对
c+=1;
printf("%d\n",c);
}
运行结果:2
2.switch-case
关键:default是指没有符合的条件就执行其后面的语句,不遇到break就一直往下执行所有分支
特别注意:default后如果没有break也依然继续往下执行
#include<stdio.h>
int main()
{
int x=1,y=0;
switch(x)
{
case 1:
switch(y)
{
case 0: printf(“first\n”);break; //这里的break只是跳出switch(y)这个分支
case 1: printf(“second\n”);break;
}
case 2: printf(“third\n”); //该分支属于switch(x),所以依然要被执行
}
}
运行结果:first,third
四.循环
1.do while语句
while(a) 表示当a!=0时执行循环,其等价于while(a!=0)。
if(a) 同上
while(!a) 表示当a=0时执行循环,其等价于while(a==0)。
if(!a) 同上
2.for循环
特别注意:for循环若存在两个判断条件,则必须两个判断条件均为假,才能结束循环
main( )
{
int x,y;
for(x=30,y=0;x>=10,y<10;x--,y++)
x/=2,y+=2;
printf(“x=%d,y=%d\n”,x,y);
}
运行结果:x=0,y=12
3.for循环中的break和continue
break表示直接跳出循环,不再执行判断语句
continue表示跳过本次循环,直接进入判断语句
五.函数
1.宏替换 关键:先替换后计算
#include<stdio.h>
#define F(x,y,z) x*y*z/4
main( )
{ int i=3, j=2, k=3;
printf("%d\n",F(j+i, i*++j,i+j+k));
}
x=j+i, y=i*++j, z=i+j+k
运行结果:87
2.static初始化只进行一次
#include<stdio.h>
int func(int a, int b)
{
static int m = 1,i = 3;
//static初始化只进行一次,第二次调用函数时m和i的值为上一次调用结束时的值
i += m + 1; m = i + a + b;
return(m);
}
int main()
{
int k = 4, m = 1, p;
p = func(k, m);
printf("%d", p);
p = func(k, m);
printf("%d\n", p);
}
运行结果:10 21
六.数组
1.字符串处理函数
1.strcpy(字符数组1,字符数组2)//用字符数组2中的值替换掉字符数组1中的值
2.strlen//计算字符数组的长度(不包括\0)
3.strcmp(字符数组1,字符数组2)//比较两个字符串大小(用ASCII码值比)
4.strcat(字符数组1,字符数组2)//将字符数组2连接到字符数组1之后
strcmp函数会从字符串中的第一个字符开始,利用ASCII码依次向后进行大小比较。若1>2则返回正值,相等则返回0,否则返回负值。
2.冒泡排序
升序:从小到大
降序:从大到小
void bubble_sort(int *a,int length)
{
int i=0;
for(i=0;i<length-1;i++) //外层循环,循环次数与数组长度相同
{
int j=0;
for(j=0;j<length-1-i;j++)
//每一轮循环后,最大的数便会浮到右边,因此右侧已经排好的数无需再次排序
{
if(a[j]>a[j+1])
{
int t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
此函数可实现对长度为length的数组的升序排序
void bubble_sort(int* a, int length)
{
int i = 0;
for (i = 0; i < length - 1; i++) //外层循环,循环次数与数组长度相同
{
int j;
for (j = length-1; j > i-1; j--)
//每一轮循环后,最大的数便会浮到右边,因此右侧已经排好的数无需再次排序
{
if (a[j] < a[j + 1])
{
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
}
该函数可完成数组的降序排序
3.数组名称的两层含义
1.数组的首地址
2.第0行第0列的地址
4.自己编写字符串处理函数
//以下为strcat函数
char mystrcat(char a[],char b[])
{
int i=0,j=0;
while(a[i]!='\0')
{
i++;
}
while(b[j]!='\0')
{
a[i++]=b[j];
j++;
}
a[i]='\0';
return a;
}
//以下为strcpy函数
char fx(char *a,char *b)
{
while(*b)
{
*a=*b ;
a++;
b++;
}
*a=*b;
}
}
//以下为strlen函数
int mystrlen(char *a)
{
int i=0;
while(*a)
{
i++;
a++;
}
return i;
}
//以下为strcmp函数
char mystrcmp(char *a,char *b)
{
int i,j;
for(i=0;a[i]!='\0';i++)
for(j=0;b[j]!='\0';j++)
if(i>j)
//以下内容根据题目要求编写
七.指针
1.一级地址和二级地址(当指针与数组结合时)
判断标准:只存在1个‘ * ’或‘[ ]’的为一级地址
不止一个的即为元素值
而一个符号都不存在的即为二级地址
#include<stdio.h>
int main()
{
const char* p[4] = { "CHINA","JAPAN","ENGLAND","GERMANY" };
//这里其实定义了一个二维指针数组,它把每一个国家名看做一行
int i;
const char** pp;
pp = p; //pp指向二维数组第0行第0列元素的地址
for (i = 0; i < 4; i++, pp++)
printf("\n%c", *(*pp + 2) + 1);
}
难点突破:1. *与()优先级大于+,所以先执行*(*PP+2)
2. *(*pp+2)存在两个*,代表的是一个元素值,就是每一个国家名的第三个字母
3. 字母+1等价于下一个字母
运行结果:
J
Q
H
S
八.结构
1.与链表有关的操作
2.结构体 指针指向结构体数组
九.文件 (C语言只能处理文本文件和二进制文件)
1.文件的打开
FILE *fp; //定义文件指针
fp=fopen(文件名,使用文件格式);
以下针对的是文本文件
w | 只写(若文件不存在,则会创建一个文件;若文件已存在,则会自动删除其中内容) |
r | 只读(文件需要已经存在) |
a | 在已有文件中添加内容 |
w+/r+/a+ | 允许读写文件 |
以下针对的是二进制文件
wb | 只写 |
rb | 只读 |
ab | 添加 |
wb+/rb+/ab+ | 既可读又可写 |
2.关闭文件
fclose(fp);
3.二进制文件读写函数
fread(&s,sizeof(struct),1,fp) | 从fp所指向的文件中读取连续1个sizeof(struct)字节的的数据,并把它存到&s下方的地址 |
fwrite(&s,sizeof(struct),1,fp) | 向fp所指向的文件中写入首地址为&s的连续1个sizeof(struct)字节的数据 |
注意:C语言只能处理文本类型和二进制类型的文件