好啦,最后一天了,C语言就结束了.之后在简单的说下Linux,然后就C++吧.
结构体强制类型对齐
#pragma pack(n) n为2的n次方
与默认选择对齐方式取最小值
其实实际上是牺牲时间换空间,这个是有用的.(结构体内类型的数据也会使结构体内存发生变化)
位段(位域)
只有unsigned int 和 unsiged char
struct BitField
{
占两位
unsigned int a:2;
占四位
unsigned char b:4;
}
相邻位域可以压缩成一块内存,不能超过自身字节数
位段不能取地址(因为步长(最小操作的是一个字节))
赋值不能越界(越界会截断)
占位位段
struct BitField
{
占两位
unsigned char a:2;
只占位
unsigned char :2; //当占位为0的时候会重新开辟字节
占四位
unsigned char c:4;
}
清空数据时可以memset
这个比左移右移方便多了,不过这个嵌入式范围,有兴趣的可以了解下,没兴趣无所谓(毕竟一般也不会真的需要对位进行操作)
共用体
union Data{
int a;
char b;
double c;
};
由最大的数据类型决定空间大小
同一时间只能使用一个
赋值的时候会覆盖(具体值是按照具体类型决定的)
其余操作和结构体相同
这个其实也是单片机的操作,这里也不细说了.
枚举
枚举的意义很大的,可以理解成他是升级版的宏(当然了,只是普通常量)
enum Data{NUM,NUM2,NUM3,NUM4};
如果不定义重0开始不断的加1(NUM = 0,NUM2 = 1,NUM3 = 2,NUM4 = 3)
如果赋值则是从赋值位置开始不断的加1
enum Data{NUM,NUM2 = 10,NUM3,NUM4};
NUM = 0,NUM2 = 10,NUM3 = 11,NUM4 = 12
也可以
enum Data{NUM = 54,NUM2 = 10,NUM3 = 23,NUM4 = 92};
#include <stdio.h>
enum MyEnum
{
NUM = 10, NUM2 = 5, NUM3 = 54
};
int main()
{
enum MyEnum n = NUM2;
printf("%d\n", n);
return 0;
}
下午把链表,文件读写搞定然后C语言就结束了
想了一下,回炉嘛那数据结构呢,链表还是等那时候再来吧.直接上文件读写吧.
文件读写
文件是读写到缓冲区然后再到硬盘,这样可以提高效率,也可以增加硬盘使用寿命.
文件实际上都是以二进制进行存储(字节为单位),分为字符编码文件(文本文件)和值编码文件(二进制文件)两种.
字符编码文件(文本文件):通常以ASCII和Unicode解析(便于查看)
空间利用率低(字节操作)
值编码文件(二进制文件):二进制原样解析(不是人看的东西)
空间利用率高(位操作)
三个特殊的文件指针
stdin 标准输入(终端键盘) stdout 标准输出(终端屏幕) stderr 标准错误(终端屏幕)
文件读写函数
fopen
参数一要打开文件的名字,参数二打开方式
打开失败返回NULL
打开方式: 图片来自网络
fclose
关闭文件,参数文件指针
文件结尾
文本文件结尾是EOF
二进制文件结尾使用feof函数判断
文件读写函数
字节读写:fgetc fputc
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
//定义文件指针
FILE* fp = NULL;
//以写的方式打开文件,文件不存在创建文件
fp = fopen("./text.txt", "w");
//判断文件打开是否成功
if (fp == NULL)
{
perror("fopen");
return 0;
}
//写入文件
fputc('h', fp);
fputc('e', fp);
fputc('l', fp);
fputc('l', fp);
fputc('o', fp);
//关闭文件
fclose(fp);
//读取文件
//以读的方式打开文件
fp = fopen("./text.txt", "r");
if (fp == NULL)
{
perror("fopen");
return 0;
}
char ch = 0;
//文本文件判断文件结尾
while ((ch = fgetc(fp)) != EOF)
{
printf("%c", ch);
}
printf("\n");
fclose(fp);
return 0;
}
字符串读写:fgets fputs
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
//定义文件指针
FILE* fp = NULL;
//以写的方式打开文件,文件不存在创建文件
fp = fopen("./text.txt", "w");
if (fp == NULL)
{
perror("fopen");
return 0;
}
//写入文件
fputs("坚持到无能为力\n", fp);
fputs("拼搏到感动自己\n", fp);
fclose(fp);
fp = fopen("./text.txt", "r");
if (fp == NULL)
{
perror("fopen");
return 0;
}
//文本文件判断文件结尾 实际中不要忘记了fgets是可以读取换行符的
//结束返回null
char buf[1024] = "";
while (fgets(buf,sizeof(buf),fp))
{
printf("%s", buf);
memset(buf, 0, sizeof(buf));
}
//去掉换行符
//buf[strlen(buf) - 1] = 0;
fclose(fp);
return 0;
}
数据块读写:fread fwrite
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
typedef struct
{
char m_name[64];
int m_age;
int m_socre;
}Student;
int main()
{
Student student[5] = {
{"小红",18,60},
{"小灰",19,70},
{"小黑",20,80},
{"小蓝",21,90},
{"小绿",22,100}
};
//定义文件指针
FILE* fp = NULL;
//以写的方式打开文件,文件不存在创建文件
fp = fopen("./text.txt", "w");
if (fp == NULL)
{
perror("fopen");
return 0;
}
//默认以二进制形式存储(内存原样输出到文件)
//第一个参数数据首地址,第二个一次读取多大(字节),第三个读取几块,第四个文件指针
fwrite(student, sizeof(student[0]), 5, fp);
fclose(fp);
fp = fopen("./text.txt", "r");
if (fp == NULL)
{
perror("fopen");
return 0;
}
//读文件
Student student2[5] = { 0 };
fread(student2, sizeof(student2[0]), 5, fp);
for (int i = 0; i < 5; ++i)
{
printf("姓名:%s 年龄:%d 分数:%d\n", student2[i].m_name, student2[i].m_age, student2[i].m_socre);
}
fclose(fp);
return 0;
}
格式化读写:fscanf fprintf
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef struct
{
char m_name[64];
int m_age;
int m_score;
}Student;
int main(int argc, char** argv)
{
FILE* fp = fopen("text.txt", "w");
if (fp == NULL)
{
perror("fopen");
return 0;
}
Student s[5] = {
{"小红",18,60},
{"小绿",19,70},
{"小蓝",20,80},
{"小份",21,90},
{"小黑",22,100}
};
//写文件
for (int i = 0; i < 5; ++i)
{
fprintf(fp, "姓名:%s 年龄:%d 分数:%d\n", s[i].m_name, s[i].m_age, s[i].m_score);
}
fclose(fp);
fp = fopen("text.txt", "r");
if (fp == NULL)
{
perror("fopen");
return 0;
}
Student s2[5] = { 0 };
//读文件
for (int i = 0; i < 5; ++i)
{
fscanf(fp, "姓名:%s 年龄:%d 分数:%d\n", s2[i].m_name, &s2[i].m_age, &s2[i].m_score);
}
for (int i = 0; i < 5; ++i)
{
printf("姓名:%s 年龄:%d 分数:%d\n", s[i].m_name, s[i].m_age, s[i].m_score);
}
fclose(fp);
return 0;
}
文件定位函数
rewind
rewind(fp);
参数文件指针,
使流指针移动到文件首
ftell
ftell(fp);
参数文件指针,
获得距文件首的字节数,失败返回-1,返回值long
fseek
int fseek(fp,0,SEEK_SET); //将文件流指针移动到文件首
参数文件指针,偏移量,起始位置
起始位置
文件开头 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
移动文件流指针到任意位置,成功时返回0,失败时返回非零,返回值int
feof
文件未结束返回0
while(!feof(fp))
{
}