#define _CRT_SECURE_NO_WARNINGS#includestdio.h#includestring.h#includeassert.h//LSB 低位置编号//共用体与枚举//共用体内的所有成员都是共用一片区域内存区域的大小与最大的数据类型成员决定//定义的语法//union 共用体类型名{// 数据结构 成员名1//};//typedef union 共用体类型名 {// 数据结构 成员名1//}共用体类型别名;union Num{unsigned char val;struct {unsigned char a : 3;unsigned char b : 1;unsigned char c : 4;}Bits;};int main(){//int n 0X01020304;////如何读取0x02位置上的值//int n2 n 0x00ff0000;// 0 0 -0 1 0-0 1 1-1//unsigned char c 53;//110101////如何读取2进制的第三位上的值//char c1 c 13;//printf(%d\n, c1 3);Num n1 {53};printf(%d %d %d\n, n1.Bits.a, n1.Bits.b, n1.Bits.c);}//读取字符的新方式//union String {// char arr[32];// char* p;//};//int main()//{// //char *a 123;//字符串存储在常量区// ////*a2; //不能修改运行报段错误// //char arr[100] 123;// //arr[0]//// union String s1 { {a,b,c}};// printf(%s\n,s1.arr);// return 0;//}union Char {unsigned char c;unsigned int val:8;};int main(){union Char c1 { A };printf(%d, c1.val);}//枚举//语法//enum 枚举类型名{名称1名称2.....}//名称1的默认值为0//enum 枚举类型名{名称1名称2.....}//名称2的指定值1//类别enum CardType{SID,PID};void getVal(int* target, enum CardType cType) {if (cType SID){*target rand() % 1000 100;}else {*target rand() % 100000000 1000000;}}int main(){int val;//可能是学号 可能是身份证号getVal(val, PID);printf(%d, val);}//动态内存管理//在C中支持三种动态内存申请的函数和一个释放动态内存的函数//动态内存 在程序运行时从堆空间申请的内存//动态内存申请成功后 和程序运行的生命周期相同 从创建成功到程序退出为止//1 malloc//void* malloc (size_t, size);//从堆空间中申请成功则返回其首地址失败则输出NULL//void free(void*p//释放申请的堆空间int main(){char*p(char*) malloc(32);//一定要验证是否为NULLif (p NULL){return -1;}assert(p ! NULL);//断言成功则继续运行反之退出程序//初始化p空间//memset(p, 0, 32);//将p指向空间的连续32个字节位置清零*p A;*p B;*p C;*p 0;//截断p - 3;printf(%s\n, p);free(p);}struct P {int x;int y;};P* getP(int x, int y){P* p (P*)malloc(sizeof(p));p-x x;p-y y;return 0;}int main(){P* p1 getP(1, 2);printf((%d,%d)\n, p1-x, p1-y);free(p1);return 0;}#define _CRT_SECURE_NO_WARNINGS#include stdio.h#include stdlib.h#include assert.h#include string.htypedef struct stu {long sid;char name[64];int age;double score;}Stu;int size 2;int i 0;Stu* stus;void add(){if (i size){size * 2;stus (Stu*)realloc(stus, size * sizeof(Stu)); // 自动复制功能}printf(请输入学生信息 学号 姓名 年龄 成绩\n# );scanf(%ld %s %d %lf, stus[i].sid, stus[i].name, stus[i].age,stus[i].score);i;printf(OK\n);}void query() {if (i 0) {printf(学生表是空的!\n);return;}printf(请输入查询的学号\n# );long sid 0;int ok 0; // 是否查询到for (int k 0; k i; k) {if (stus[k].sid sid) {ok 1;printf(%ld %s %d %.2lf\n,stus[k].sid,stus[k].name,stus[k].age,stus[k].score);break;}}if (!ok) {printf(查无此学生!\n);}}int main() {stus (Stu*)malloc(size * sizeof(Stu));assert(stus ! NULL);memset(stus, 0, size * sizeof(Stu));int opt 0;while (1) {printf(请选择: 1. 添加 2. 查询 0.退出\n# );scanf(%d, opt);if (opt 0) break;if (opt 1) addStu();else if (opt 2) query();else {printf(选择无效请重新选择!);}}free(stus);return 0;}}//一、文件操作//文件是用于存储数据或程序代码也是持久化一种方式。文件分为文本文件、图像或视频文件、二//进制文件可执行文件等。//文件 存储数据的一种载体或媒介。//文件的分类与扩展名//.c, .cpp, .h 程序的文本文件 记事本可以打开的//.jpg, .gif, .png 图像文本//.mp3, .mp4, .avi 音 / 视频文件//.exe, 二进制的可执行文件//在程序中需要存储数据或查询数据时可以打开文件并操作。// 返回文件指针句柄, 可以是NULL空指针打开失败FILE* fopen(char const* _FileName, // 文件名char const* _Mode // 打开模式);void fclose(FILE* _f); // 关闭文件//1.1 打开和关闭文件的函数//文件名 参数 打开文件的位置 也可以是相对于当前程序所在位置相对位置//a.txt 相当于当前程序的位置//D : / a.txt 绝对位置从盘符开始 / Linux风格的文件分隔符Window的文件分隔是 \, 必须//要转义 \\ 。//模式的参数 打开文件时确认的模式//w 只写 如果文件不存在时自动创建。如果文件存在时则会清空。//r 只读 如果文件不存在时则打开失败。//a 追加写 如果文件不存在则自动创建。如果文件存在则会移动光标到文件尾部。// 可读可写 与以上3种进行组合保留以上的特性。//如 a 追加写和可读//如 w 可写可读//如 r 可读可写int main() {// stdin 标准输入, stdout 标准输出1.2 写文件操作以下的函数必须是.c 的源文件 :如1如2FILE * f fopen(a.txt, a);assert(f ! NULL);fclose(f);// 关闭文件return 0;}//1.2 写文件操作//以下的函数必须是.c 的源文件 :// stdin/stdout 都是FILE *类型int fputchar(int c); // 向stdout标准输出写入一个字符int fputc(int c, FILE* f); // 向指定的f文件中写入一个字符int fputs(const char* Buffer, File* f); // 向f文件中写入字符串成功返回0// 返回写入元素的个数size_t fwrite(const void* buffer, // 存储数据的首地址size_t elementSize, // 存储数据中元素的大小size_t elementCount, // 总元素的个数FILE* stream); // 文件流文件指针、文件句柄//如1int main() {// stdin 标准输入, stdout 标准输出FILE* f fopen(a.txt, a);assert(f ! NULL);// 向f文件写入一个字符int ret fputc(a, f); // 返回字符的数值printf(ret %d\n, ret);// 向f文件中写入一个字符串ret fputs(bc\n, f); // 写入成功返回0printf(ret %d\n, ret);// 不使用printf向控制台输出字符串 hi,C2505!fputs(Hi,C2505!\n, stdout);fclose(f);// 关闭文件return 0;}//如2int main() {FILE* f fopen(b.dat, w);int arr[10] { 1,2,3,4,5,6,7,8,9,10 };// 返回是写入元素的个数size_t len fwrite(arr, sizeof(int), 10, f);printf(len %ld\n, len);fclose(f);return 0;}//1.3 读文件操作int fgetc(FILE* stream); // 从stream文件流中读取一个字符int fgetchar(); // 从stdin 标准输入流中读取一个字符过时了int _fgetchar();int getchar(); // 同上// 从_Stream文件流读取字符串遇到 \n 或 读取_MaxCount个数时 则结束。// 读取成功后返回存储位置的首地址 读取失败则返回NULL。char* fgets(char* _Buffer, // 存储的位置int _MaxCount, // 最大字符数FILE* _Stream // 文件流);// 读取元素的实际个数size_t fread(void* buffer, // 存储的位置size_t elementSize, // 元素的大小size_t elementCount, // 元素的个数FILE* stream); // 文件流#include stdio.hint main() {// 读取a.txt的第一个字符FILE* f fopen(a.txt, r);int c fgetc(f);printf(%c\n, c);// 读取第三个字符fgetc(f);c fgetc(f);printf(%c\n, c);// 读取剩下所有的字符// EOF(-1) 表示读取到文件结束位置while ((c fgetc(f)) ! EOF) {printf(%c, c);}fclose(f);return 0;//循环从键盘输入字符 并写入到c.txt文件中直到输入E时则停止输入。//输入字符不要使用 scanf()int main() {int c;FILE* fc fopen(c.txt, w);// fgetchar() POSIX标准的函数在Window VS2022工具中过时while ((c _fgetchar()) ! E) {fputc(c, fc);}fclose(fc);return 0;}//1.3.2 读字符串#define _CRT_SECURE_NO_WARNINGS#include stdio.hint main() {FILE* f fopen(c.txt, r);// 读取文件中所有行的内容char buffer[128] ;while (fgets(buffer, 128, f) ! NULL) {printf(%s, buffer); // 读取一行数据中包含\n}#if 0// 读取一行数据char buffer[128] ; // 定义从文件中读取数据之后存储的位置char* p fgets(buffer, 128, f); // 读取的字符数包含 \0的if (p ! NULL) {1.3.3 读数据块1.4 综合练习printf(%s, buffer);}#endiffclose(f);return 0;}// 1.3.3 读数据块int main() {// 从b.dat文件 读取10个int的数组数据FILE* fb fopen(b.dat, r);int arr[10] { 0 };size_t len fread(arr, sizeof(int), 10, fb);printf(读取的个数 %llu\n, len);for (int i 0; i len; i) {printf(%d , arr[i]);}printf(\n);fclose(fb);return 0;}//综合练习#define _CRT_SECURE_NO_WARNINGS#include stdio.htypedef struct _book {char name[32];double price;} Book;// 实现文件内容的清空void clear(const char* fileName) {FILE* fbook fopen(fileName, w);fclose(fbook);}void append(Book* book, const char* fileName) {fwrite(book, sizeof(Book), 1, fbook);fclose(fbook);}void showAll(const char* fileName) {FILE* fbook fopen(fileName, r);if (fbook ! NULL) {size_t len 0;while (1) {Book book;len fread(book, sizeof(Book), 1, fbook);printf(Read Book count: %llu\n, len);if (len 0) {break;}printf(%s:%.2f\n, book.name, book.price);}fclose(fbook);}}int main() {Book b1 { C, 19.5 }, b2 { Linux, 9.9 }, b3 { C, 99 };append(b1, book.dat);append(b2, book.dat);append(b3, book.dat);showAll(book.dat);return 0;}//1.5 ftell 和 fseek 函数long ftell(FILE* stream); // 从stream文件流中的光标位置开始到文件开始位置总字节数。 在//VS中计算失败.// 移动文件光标 成功返回0// offset 移动的字节数 如果是负数表示向前移动// origin:// SEEK_SET(0) 从文件首位置开始移动// SEEK_CUR(1) 从当前光标位置向后移动// SEEK_END(2) 从文件结尾的位置向后移动int fseek(FILE* stream, long offset, int origin);int main(){FILE* f fopen(a.txt, r);#if 0// 读取book.dat文件的大小long size ftell(f); // 计算当前光标开始到文件头部的字节数printf(a.txt file size is %ld\n, size);#endif// 移动光标到 第五个字符之后,(\n 表示2个字节) 读取一个字符fseek(f, 5, SEEK_SET); // 4字符前printf(%c\n, fgetc(f));fseek(f, 1, SEEK_CUR); // 6字符前printf(%c\n, fgetc(f));fseek(f, -3, SEEK_END);printf(%c\n, fgetc(f));fclose(f);return 0;}