结构体
1.结构体变量声明和定义
结构体是一种构造类型,必须先声明再定义后使用.
声明一般形式:
struct student
{
成员类型 成员名1;
……
};
定义一般形式:
struct student st1,st2;
在声明的同时定义struct student {}st1,st2;
直接定义变量struct {}st1,st2;//这种变量只能是两个不能再增加
typedef struct student{}ST;
ST st1,st2;//一般使用这种
2.结构体的引用
成员点记法:st1.data;
由于结构体占用的内存较大,在函数中传递结构体时一般传递结构体的地址.
ST *p;
此时可写成p->data;引用成员.
3.结构体数组
与普通数组一样,相当于有N个一样结构体.
4.结构体指针
定义指针变量方式:
struct 结构体类型名 *结构体指针变量名;
访问成员方式:
1) 结构体变量名.成员名;
2)(*结构体指针变量名).成员名;
3)结构体指针变量名->成员;
5.动态内存分配
为什么要动态内存分配?
用多少分多少,随时分配,随时释放,静态的在程序结束后自动释放,浪费空间.
分配内存空间函数
1)malloc函数
使用:(类型说明符*)malloc(size);
类型说明符*:强制转换为这种类型的空间.
功能:在内存的动态存储区中分配一块长度为size的连续区域,函数的值是该区域的首地址.
2)calloc函数
使用:(类型说明符*)calloc(n,size);
功能:在内存动态存储区中分配n块长度为size的连续区域,函数的返回值为该区域的首地址.
释放内存空间函数
1)free函数
使用:free(指针变量);
功能:释放动态分配的空间.
6.共用体(联合体)
共用体的声明与调用
一般形式:
union 共用体类型名
{
类型 成员名1;
……
};
调用方式:与结构体一样.
共用体的存储方式
每个成员不占用专门的空间,全体成员共用一块内存,在初始化时每次只能初始化一个
注意:
1) 不能引用共用体的整体,只能引用某个成员
2) 与结构体的调用方式一样,可以是使用->和.
3) 不能在定义共用体时进行初始化
4) 共用体中起作用的是最后一次存放的成员
5) 共用体变量不能作为函数的参数,成员可以
7.枚举类型
枚举类型的声明与定义
枚举类型与结构体类型一样,是一个新的数据类型,需要先声明后定义再使用
声明一般形式:
enum 枚举类型名
{
枚举常量1,//默认标号为0-n
枚举常量2,//可以枚举常量 = 1重新改变标号
……
};
枚举类型的使用
typedef enum UARTx
{
UART0,
UART1
}UARTx;
void SCI_Init(UARTx uart,long unsigned int baud)
文件
1.文件的打开和关闭
1)文件的打开
使用(fopen(fp)函数)
FILE *fp;
fp = fopen (“文件路径及文件名”,“文件使用方式”)
if(fp == NULL)//判断文件是否打开成功,文件打开失败fopen返回NULL
文件路径:
(1)C\\code\\aaa.txt(自定义文件路径).
(2)C/code/aaa.txt(自定义文件路径).
(3)aaa.txt(保存在当前文件中).
文件名:自定义任意拓展名.
文件使用方式:
r:只读打开一个文件(文件必须存在).
w:只写打开一个文件(文件存在会重新创建一个).
a:追加打开一个文件(文件必须存在).
rb、wb、ab:二进制的方式操作.
r+:按读写的方式打开一个文本文件.
w+:按读写的方式创建一个文本文件.
a+:按读写的方式打开一个文本文件.
rb+、wb+、ab+:二进制的方式操作.
2)文件的关闭
使用(fclose(fp))每一次文件操作完成后都要关闭.
2.文件的读写
1)字符的输入输出函数
fgetc 函数和fputc函数:
从文件中读写一个字符(以字节为单位读写).
(1)fgetc 函数(从指定的文件中读入一个字符)
FILE *fp;
char ch;
fp = fopen (“file.txt”,”r”) ;
ch = fgetc (fp);
读入的字符可以输出到屏幕(printf (“%c”,ch)或putch(ch)).
可以循环读取每读一次指针向后移动一位读到文件末尾时返回EOF如果读取错误也返回EOF(EOF的值为-1).
注意文件必须以只读或读写的方式打开
ANSIC中feof函数判断文件是否读完.
feof(fp)如果文件结束返回1,否则返回0.
while(!feof(fp))
{
ch = fgetc (fp);
……
}
(2)fputc函数(向指定的文件中写入一个字符)
while (ch ==‘指定的结束字符’)
{
ch = getchar ();//键盘输入要写入的字符//scanf(“%c”,&ch)//二者等价
fputc (ch,fp)//将字符写入文件
putchar (ch);//输出到屏幕上
……
}
注意如果函数写入成功,返回字符否则返回EOF
可以用w、w+、a等方式打开文件.
2)字符串的输入输出函数
(1)字符串的输出函数fgets(string,n,fp)//从文件中读给字符串.
string 是定义的数组存储文件中读出的字符串.
n是读出的字符串不超过(n-1)个字符,在最后一个字符后加上’\0’而fgets函数读完时返回NULL,开始读的时候返回字符数组的首地址读取的字符串存在数组中.
文件已w、w+、a+等方式打开且必须存在.
(2)字符串的输入函数fputs(string,fp)//从字符串中写到文件
字符串可以是数组名或指针变量,但是字符'\0'不输出.
fputs(“abc”,fp);//将字符串abc写入到文件.
fputs(string,fp);//将字符串数组string写入到文件.
与fputc的区别是fputc需要结束标志要不停的写入.
3)格式化读写函数
(1)格式化输入函数fscanf(文件指针,格式字符串,输入参数)
fscanf (fp,”%d%f”,&i,&t);//从文件中读取给变量
(2)格式化输出函数fprintf(文件指针,格式字符串,输入参数)
fprintf (fp,”%d%c”,i,ch);//从变量写到文件
4)数据读写函数
(1)数据读函数
整型变量 = getw(fp)//从文件中读入一个整数
注意:如果超出整型所占的大小返回的值是垃圾值.
(2)数据写函数
putw(整数,fp)//从变量中写入到文件
5)数据块读写函数
(1)读数据块函数fread(buffer,size,count,fp)
最多读取count个项,每个项size个字节,如果调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回 0.
//从文件中读取到buffer地址内.
buffer 为数据块的起始地址.
size为读取一个数据块的长度(sizeof ()).
count 为读取数据块的个数(a[5]读取1次就能读完).
(2)写数据块函数fwrite(buffer,size,count,fp)
//从地址中的变量写到文件.
buffer 待写入数据块的起始地址.
size为写入一个数据块的长度(sizeof ()).
count 为写入数据块的个数(a[5]写入1次就能写完).
char a[11] = "HelloWorld!";
fwrite (a,sizeof(a),1,fp);
注意如果是字符串的话只能读n-1个.
3.文件的随机读写
1)rewind函数
用法:rewind(fp);
功能:使文件内部的位置指针重新返回文件的开头.
2)fseek函数
用法:fseek(fp,位移量,起始点);
位移量:以起点为基点,向前移动的字节数.
offset为偏移量,正数表示正向偏移,负数表示负向偏移.
起始点:SEEK-SET(0),SEEK-CUR(1),SEEK-END(2).
分别是文件首,当前位置,文件末尾.
fseek(fp,-100L,2);把stream指针退回到离文件结尾100字节处.
功能:使位置指针移到指定的位置
while (!feof(fp1))
fputc(fgetc(fp1),fp2);// 整体含义:将fp1中的字符复制到fp2指向的文件中.
注意:文件指针指向文件/流。位置指针指向文件内部的字节位置,随着文件的读取会移动,文件指针如果不重新赋值将不会改变或指向别的文件.
3)ftell函数
用法:name = ftell (fp);//name为long型变量.
功能:得到文件位置指针的当前位置.
文件刚打开时文件指针位置在文件首,随着操作的进行文件指针会随之移动,读一次移动一次,直到在循环中通过feof函数检测到文件结束时,此时文件指针位置在文件的末尾.
4.文件的出错检测
1)feof函数
用法:feof(fp);
功能:判断文件是否处于文件的结束位置,如结束返回1否则返回0.
2)ferror函数
用法:ferror(fp);
功能:检查它前面一个输入或输出文件操作是否有错误,有返回1否则0.
3)clearerr函数
用法:clearerr(fp);
功能:使文件错误标志和文件结束标志置为0.假设在调用一个输入输出函数时出现了错误,ferror函数值为一个非零值。在调用clearerr(fp)后,ferror(fp)的值变为0.
编译预处理
1.宏定义#define
1)无参数
#define 标识符 字符串
2)有参数
#define 宏名(参数表) 字符串
#define S(a,b) a*b
Area = S(3,2);
注意事项
(1)宏定义后加分号,连分号一起替换.
(2)宏定义必须写在函数之外,作用域为从定义处到程序结束,终止用#undef.
(3)宏定义中若双引号括起来,则不替换.
(4)宏定义允许嵌套,层层替换.
(5)宏定义名习惯是上用大写.
(6)#define PIN1 int* typedef (int*)PIN2; PIN1 a,b;PIN2a,b;意义不同.
(7)宏名与参数表中间不能出现空格#define S (a,b) a*b.
(8)带参宏中只存在符号代换,不存在值传递.
(9)字符串内的形参通常要用括号括起来避免错误#define S(a,b) (a)*(b).
2.文件包含
1)#include“文件名”
先从源文件目录中查找,再到系统指定的其他目录中找.
2)#include
只在系统指定的目录中找.
3.条件编译
1)#ifdef使用格式
#ifdef 标识符
程序段1
#else
程序段2
#endif
功能:当标识符已经被定义过,对程序1进行编译,否则编译程序段2.
2)#ifndef使用格式
#ifndef 标识符
程序段1
#else
程序段2
#endif
功能:当标识符未被定义过,对程序1进行编译,否则编译程序段2.
3)#if使用格式
#if 表达式
程序段1
#else
程序段2
#endif’
功能:当表达式成立,编译程序段1否则编译程序段2.
领取专属 10元无门槛券
私享最新 技术干货