C语言复习笔记

指数形式

                  12.34e3 = 12.34x10^3         0.145E-25 = 0.145x10^-25        输出时用%e表示

                  13**3 = 2197 (13的3次方)

转义字符

                  \a 警告,通过扬声器发出一次警报声

                  \b 退格,光标向前移动一位,后继输出会覆盖后面的数据

                  \r  回车,把光标当前位置移动到本行的开头,后继输出会覆盖

                  \t 水平制表符,光标移动到下一个tab位置,后续覆盖

符号常量

也叫宏定义,注意最后没有分号

#define PI 3.1415926

常变量

不能改变的变量,初始化时需要给其赋值,书上推荐使用常变量不用符号常量。

const int a = 3; 

标识符

标识符为变量,函数,数组,类型等的统称,其定义时只能由数字,字母,下划线组成,而且首位必须由字母或下划线组成。

数据类型

下列是几种常见的数据类型关键字及其位数。c标准要求long不短于int类型,short类型不长于int类型。float数据类型能得到6位有效数字。在c语言中进行浮点运算时,会自动把float转换位double类型在计数。计算机在编译时会自动把带小数点的常量按照双精度浮点数处理,分配8个字节,当我们定义float类型时给了5位小数,编译器会警报,意思为把一个双精度的数赋值给单精度的变量会损失精度,但是我们可以在常量的后面加上f,此时表示此常量就是单精度的,赋值时不会报错,同理可以在单精度常量后面加上L,那么编译器会把单精度的常量作为long double类型处理。

int              //整形根据计算机决定位数,一般为32位
short int        //短整形16位
long int         //长整型32位
long long int    //双长整型64位
unsigned         //无符号类型,一般搭配整型和浮点型使用
char             //字符型8位
float             //浮点型32位,小数点后4位 -3.4x10^-38 ~ 3.4x10^-38
double           //双精度浮点型64位 小数点后8位 -1.7x10^-308 ~ 1.7x10^-308
enum             //枚举类型
struct           //结构体类型
union            //共同体类型

float pi = 3.1415925f;    //编译器会把其作为点精度处理,不会报错
long double a = 1.23L;    //上述同理

volatile          //禁止优化,一般用于地址操作

运算符

%的两侧都需要为整型才能运算。

循环

结束循环用break,中断本次循环用continue。

输入输出

输入双精度时需使用%lf的格式声明。在输出浮点型时可以在%后面紧跟一个浮点类型的常量,例如:%7.2f,表示为指定数据占7位,其中小数占两位,也可已不指定数据直接编写成%.2f,代表保留两位小数。在%后还可以加一个负号,表示位输出的数据向左对齐,例如:%-7.2f。输出格式附加字符:m代表一个正整数,数据最小宽度。n代表一个正整数,对实数表示输出n位小数,对字符串表示截取的字符个数。“-”输出的数字或字符在域内向左靠。如果要输出 '\n' 而不是要输出换行符时,需要用 '\\n' 来代替,编译器会自动处理成 '\n'。

//输出高位显0
printf("%d",1);    //输出为 1
printf("%02d",1);  //输出为 01
printf("%03d",1);  //输出为 001

常见头文件

一些常见用到头文件,以及它们常用的函数。

#inclued <stdio.h>
gets(a);    //输入字符串给a


#inclued <math.h>
b = aqrt(a)    //把a开根号后赋值给b
b = abs(a)     //把a的绝对值赋值给b,其类型为整型
b = fabs(a)    //把a的绝对值赋值给b,其类型为双精度浮点型

字符串

在字符串类型的最末尾处有一个结束符'\0',使用%s输入时在输入完成后,最末尾处自动添加结束符,在输出时使用%s会把'\0'前面的内容输出。在使用字符串输入时用scanf函数不能有效的输入第一次空格后面的字符,scanf会把遇到的第一个空格检测为结束符,如需要输入带空格的字符串可以使用gets()函数。输入单个字符可以用getchar()函数,他没有输入,返回值就是输入的字符。另外还有getch()与getchar()的使用方法相同,但是没有输入显示,可以用来设计密码,上述的两种输入在输入一个字符串后自动运行后面的代码,与scanf不同需要输入enter的等待。

//字符串处理函数,需要加头文件string.h
pust(a);         //输出字符串,a里面的内容以'\0'为结束位,只能输出一个字符串
gets(a);         //输入字符串,a里面的内容以'\0'为结束位,只能输出一个字符串
c = strcat(a,b); //字符串拼接函数,把a和b的内容给c,需要保证c的长度足够
strcpy(a,b);     //把b中的内容赋值到a中,a必须大于b
strcpy(a,"abd"); //b必须为字符串,b可以是字符常量
strncpy(a,b,n);  //把b中前n个字符复制到a中去
strcmp(a,b);     //字符串比较函数,将两个字符串按照从左到右按照ASCII的值进行比较,直到'\0'
strlen(a);       //字符串长度测量,以'\0'为结束位,并不计算在内
strlwe(a);       //将字符串中大写的字母转化为小写的字母,其他不改变
strupr(a);       //将字符串中小写的字母转化为大写的字母,其他不改变

递归

函数调用自己本身,利用返回值结束调用,形成类似累加或循环程序。

函数参数传递时有形参和实参,他们的含义为分别为 实参:实际的数或者变量   形参:地址

变量影响范围

局部变量与全局变量,全局变量同一文件内生效,若函数内有同名的局部变量那优先选择局部变量进行运算。若想全局变量在同一工程不同文件内生效,则要编写外部变量声明。

int a;           //不同文件中定义的全局变量

extern int a;    //在外部变量声明后,就可以使用
extern a;       //可以省略变量类型

//若想让变量只在本文件内生效即可如下定义
static int a;    //静态外部变量
 
extern a;        //此时程序会出错,a不能被外部变量声明


//函数定义也和变量相同,若在定义时加上 static 则定义的是静态函数,外部不可调用
void a()        //定义外部函数
{
    return;
}

extern void a(); //不同文件下声明后即可使用

static void a()        //定义内部函数
{
    return;
}

extern void a();       //此时程序会出错,a不能被外部函数声明

变量持续时间

自动变量与静态变量,所以默认定义的变量都为自动变量,持续时间为所定义的函数运行的时间,全局变量的持续时间为从工程开始到结束,静态变量的持续时间为从代码运行到定义处开始,持续到工程结束。

static int a;    //静态变量定义格式

指针

*p++ 由于++与*的优先级是一样的,所以按照从右到左的顺序计算,所以等价与*(p++)。

指针数组的一些操作

//一维数组
int a[3];
int *b = a;
//a[1] 等价 b[1];
//*b++ 等价 *(b++)

//二维数组
int c[3][3];
int *d = c;
//c[1][1] 等价 d[1][1] 等价 *(*(d+1)+1) 等价 *(d[1] + 1);


//指向一维数组的指针与指针数组
int p;
/*数组指针可以理解为一个二维数组,其x轴的大小为3,y轴的大小由指针控制,分配好内存或起始地址后可以在有限的空间内自增*/
int (*p1)[3]  //数组指针,指向一维数组的指针,一维数组的个数为3个

char *p2[3] = {"aaa","bbb","ccc"};    //指针数组

int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
p1 = a;

p = *(p1+1);    //*p = 4;
p = *p1+1;      //*p = 2; 

在while或for循环中可以写赋值运算表达式

//这是一个字符串复制函数,以字符串的结束符'\0'为循环结束判断
void copy_sting(char *from,char *to)
{
    while((*to++ = *from++) != '\0');
}

//与上述while等价
for(;*to++ = *from;);


//由于'/0'在ASCLL中的数值等于0,上述的代码还能简化
while(*to++ = *from++);
for(;*to++ = *from++;);

指针函数

//用指针调用函数
int max(int x,int y);    //获取最大值的函数声明

int (*p)(int int);     //定义函数指针
int a,b,c;

c = (*p)(a,b);          //*p两边的括号不可缺少

指向指针的指针

char *a[] = {"aaa","bbb","ccc"};
char **p;
p = a;    
printf("%s",*p); //输出为:aaa

动态内存分配

//开辟动态存储区,返回值都为开辟内存的首地址,需要用到stdlib.h库

//size为需要开辟的字节数,一般用sizeof()计数数值
void *malloc(unsigned int size);    

//在动态存储区中分配 n 个长度为 size 的连续空间
void *calloc(unsigned n,unsigned size);

//重新分配动态存储区函数,p 为内存首地址,大小改为 size ,如果分配不成功返回值为NULL
void *realloc(void *p,unsigned int size);

//释放开辟的内存,p为需要释放内存的首地址
void free(void *p);

结构体

//结构体编写格式,注意最后的分号不能缺少
struct 结构体名称
{成员列表};

//也可以不写结构体名称直接在后面写结构体变量
struct 
{成员列表}test1;

//定义结构体变量
struct 结构体名称 test2;

结构体指针

struct temp
{
    int a;
    char b;
};

struct temp test;
struct temp *p;
p = &test;

//结构体与结构体指针的引用方式
temp.a = (*p).a = p->a;

链表

链表是一种常见的数据结构,可以根据需要,开辟内存单元。利用头指针定位地址,所以需要定义一个头指针,然后与结构体变量结合形成链表。

struct temp
{
    int a;
    struct temp *next;
};

//建立静态链表
struct temp a,b,c;
struct temp *head,*p;
head = p = &a;
a.next = %b;
b.next = %c;
c.next = NULL; 
//利用指针的操作对链表的成员进行操作
p = p->next;

//建立动态链表
struct temp *head,*p;
head  = p = malloc(sizeof(struct temp));  //建立链表的头

p->next = malloc(sizeof(struct temp));    //根据需求利用循环,建立需要的链表长度
p = p->next;
p->next = malloc(sizeof(struct temp));  
p = p->next;
.
.
.
p->next = NULL;    //链表最后的指针要指向空

共同体

定义一个新的变量,它可以储存几种不同的数据类型,其占用空间为最大BIT的数据类型,它与结构体不用,它只能存储一个数据(非数组字符串格式下)

//共同体定义格式,与结构体基本相同
union 共同体名称
{
    成员列表
}变量列表;

union temp
{
    int i;
    char c;
};

//用共同体时要引用成员,要不然编译器不知道你所使用的那种变量类型
union temp a; 
a.i = 97;
printf("%d %c",a.i,a.c); //输出的值为 97 a 因为在ASCLL中97号为小写字母a

//使用共同体赋值时也需要引用成员,同一种共同体可以直接赋值
union temp a,c; 
int = b;
a = 1;    //错误
b = a;    //错误
a = c;    //正确

枚举类型

枚举类型的作用是固定变量的取值,把变量可取的值都一一列出来,变量只能取列出的值。枚举元素列表默认为int类型,从0开始每个元素加1,同时也可以自己定义元素值,从自己定义的元素开始后面的元素默认加1。这个数值可进行基本的运算。

//定义枚举变量格式
enum 变量名称 {枚举元素列表};

//sun = 7,mon = 1,tie = 2,wed = 3,thu = 4,fri = 5,sat = 6
enum weekday {sun = 7,mon =1,tie,wed,thu,fri,sat};

weekday = sun;    //枚举类型只能取枚举列表内的值
weekday = 7;      //也可以用数字代替
weekday = 8;      //非法,不用取未枚举的值

typedef 变量类型声明关键字

//重定义基本数据类型,注意最后有一个分号
typedef 基本类型 自定义名称;    //基本类型是c语言中的变量类型
typedef unsigned int u_int; 
typedef unsigned char u_cahr;

//还可以用typedef重定义结构体
typedef struct
{
    结构体成员;
}变量名称;

typedef temp    //这样就可以直接用test定义结构体变量,这样好像定义不了链表结构
{
    int a;
    char n;
}test;

test i;

文件操作

//文件类型指针,文件操作系统相关函数需要用到stdlib.h库
FILE *fp;

//打开数据文件
fopen(文件名称,使用文件格式);     //返回值为文件格式指针,若失败则返回NULL,可以用exit(0)结束
fp = fopen("test.txt","r");      //注意要加双引号,文件使用方式在下列表格中查找

//关闭数据文件
fclose(文件指针);    //关闭成功返回值为0,否则返回值为EOF(-1)
fclose(fp);

//单个字符读写文件函数
fgetc(文件指针);    //读取文件内的单个字符,读取成功返回读取到的值,否则返回EOF
fputc(字符,文件指针);    //把字符写入到文件指针所指的文件

//检测文件末尾标志是否被读取过
feof(文件指针)    //若被读取过返回1,否则返回0

//字符串写入文件函数
fgets(str,n,fp);    //从fp指向的文件读入一个长度为(n-1)的字符,存放到字符串数组str中
fputs(str,fp);      //把str所指向的字符串写到文件指针fp所指向的文件中

//用格式化的方式读写文件
fprintf(文件指针,格式字符串,输出列表);    fprintf(fp,"%d %f",a,b);
fscanf(文件指针,格式字符串,输入列表);     fscanf(fp,"%d %f",&a,&b);

//用上述读写方式时由于输入输出需要平凡的转换为ASCLL,所在内存与磁盘频繁交换时使用fread与fwrite
//使用二进制向文件读写一组数据
fread(buffer,size,fp);    //buffer用于存放文件读取的内容,size要读多少个字节
fwrite(buffer,size,fp);   //buffer用于存放文件写入的内容,size要写多少个字节

在C语言中换行是用'\n',但是在windows系统中换行用'\r'和'\n',我们在编译的时候用非二进制打开文件时,编译器会自动转换,进行输入时也会自动转换,这就是使用文件格式带不带b的数据上的差异。 

文件使用方式含义如果指定的文件不存在
r(只读)为了输入数据,打开一个已存在的文本文件出错
w(只写)为了输出数据,打开一个文本文件建立新文件
a(追加)向文本文件尾添加数据出错
rb(只读)为了输入数据,打开一个出错
wb(只写)为了输出数据,打开一个建立新文件
ab(追加)向二进制文件尾添加数据出错
“r十”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建立一个新的文本文件建立新文件
“a十”(读写)为了读和写,打开一个文本文件出错
“rb+”(读写)为了读和写,打开一个二进制文件出错
“wb+”(读写)为了读和写,建立一个新的二进制文件建立新文件
“ab+”(读写)为读写打开一个二进制文件

文件位置标记

文件内容在被读写时,每读写一个字符或一个字符串后文件位置标记会自动向后移动,类似windows的光标,我们可以使用函数控制光标的位置。

//文件位置标记指向文件开头
rewind(fp);    //没有返回值

//任意改变文件位置标记
//起始点为0表示为文件开始位置,1为文件当前位置,2为文件末尾位置
fseek(fp,位置量,起始点);    
fseek(fp,100L,0);        //从文件开头向后移动100个字节,L为long型,位置量可以为负数

//检测当前位置函数
ftell(fp);    //返回值为当前位置,若调用失败返回 -1L

文件写入出错检测

//若返回值为0表示未出错,返回非0数表示出错
//对同一个文件每使用一次输入输出函数都会返回一个新的ferror函数值
ferror(fp);

//清除错误标志,使ferror的值为0,还可以对文件再次进行读写操作也可以进行清零操作
clererr(fp);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值