多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

嵌入式学习笔记-标准IO

嵌入式学习笔记-标准IO 一、标准IO概念标准I/O库是C语言标准库的一部分stdio.h它封装了底层的系统调用如read/write提供了带缓存的输入输出机制。主要特点跨平台可移植性自带缓存减少系统调用次数提高效率使用文件流指针FILE* 操作文件二、缓存机制C标准IO有三种缓冲模式模式宏说明典型应用全缓冲_IOFBF缓冲区满或手动刷新时才进行实际IO普通文件行缓冲_IOLBF遇到换行符时刷新缓冲区标准输出终端无缓冲_IONBF每次IO操作立即执行标准错误输出示例测试三种缓冲模式#include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h //测试全缓冲 void testFullBuffered(); //测试行缓冲---碰到换行符才进行输出 void testLineBuffered(); //测试无缓冲 void testNoBuffered(); int main(int argc,char *argv[]){ //输出缓冲区默认大小8192个字节 //printf(输出缓冲区默认大小:%d\n,BUFSIZE); //testFullBuffered(); testLineBuffered(); // testNoBuffered();//想测试哪个就取消注释就行 return 0; } void testNoBufferd(){ FILE *fpfopen(./测试缓冲方式.txt,w); if(fpNULL);{ perror(打开i文件失败); return; } setvbuf(fp,NULL,_IONBF,0); fprintf(fp,这里是测试无缓冲数据.....); sleep(5); //关闭文件 fclose(fp); } //测试行缓冲--碰到换行符才进行输出 void testLineBuffered(){ FILE *fpfopen(./测试缓冲方式.txt,w); if(fpNULL){ perror(打开文件失败); return; } setvbuf(fp,NULL,_IOLBF,0); //fprintf(fp,这里是测试行缓冲数据....\n); fprintf(fp,这里是测试行缓冲数据...); sleep(5); //关闭文件 fclose(fp); } //测试全缓冲 void testFullBuffered(){ //打开文件 FILE *fpfopen(./测试缓冲方式.txt,w); if(fpNULL){ perror(打开文件失败); return; } //设置缓冲区属性 //参数一:表示FILE指针 //参数二表示缓冲区属性NULL表示使用默认属性 //参数三缓冲区类型 //参数四缓冲区大小 setvbuf(fp,NULL,_IOFBF,1024); //输出数据到文件中 //参数一:表示FILE指针 //参数二表示写入的数据 fprintf(fp,这里是测试全缓冲数据....\n); sleep(5);//让程序休眠也就是说让程序在这里停留一段时间 //手工清空缓冲区 fflush(fp); //关闭文件 fclose(fp); }三、文件流指针与FILE结构体文件流指针FILE*是文件在C程序中的代表通过fopen获得。FILE结构体内部包含文件描述符、缓冲区指针、错误标志、文件位置指示器、EOF标志等。IO流输入流数据从设备→程序、输出流数据从程序→设备。四、常用标准IO函数详解1. fopen / fcloseFILE* fopen(const char *filename, const char *mode); int fclose(FILE *stream);mode说明r只读文件必须存在w只写文件存在则清空不存在则创建a追加写文件不存在则创建r读写文件必须存在w读写文件存在则清空不存在则创建a读写追加读从开头写追加到末尾示例FILE *fp fopen(example.txt, r); if (fp NULL) { perror(打开文件失败); return -1; } // ... 读写操作 ... fclose(fp);2. fgetc / fputc字符读写int fgetc(FILE *stream); // 读取一个字符返回ASCII值或EOF int fputc(int c, FILE *stream); // 写入一个字符示例复制文件逐字符/*************************************************** # File Name: test04.c # Author: it1412 # Mail: 1017080724qq.com # Created Time: 2026年08月04日 星期二 15时17分18秒 ****************************************************/ #include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h int main(int argc, char *argv[]) { // 打开文件 FILE *fp fopen(./3.txt,r); if(fpNULL){ perror(打开文件失败); return 1; } //按照字符读取文件内容 char ch; chfgetc(fp); printf(%c,ch); while(chfgetc(fp)!-1){ printf(%c,ch); } fclose(fp); //打开文件 // FILE *fpfopen(./4.txt,r); // if(fpNULL){ // perror(打开文件失败); // return 1; // } // //执行读取文件的内容 // char str[16]{0}; // //参数一读取的内容放哪个在字符数组中 // //参数二读取的数据的数据的最大字节数 // //参数3FILE指针 // //返回值字符串的首地址如果为NULL表示文件读物 // fgets(str,sizeof(str)-1,fp); // printf(%s,str); // while(fgets(str,sizeof(str),fp)!NULL){ // printf(%s,str); // //给str设置成0 // memset(str,0,sizeof(str)); // } // fclose(fp); return 0; }3. fgets / fputs行读写char* fgets(char *s, int size, FILE *stream); int fputs(const char *s, FILE *stream);fgets读取一行包括换行符并在末尾加\0。如果一行太长只读取size-1个字符。fputs写入字符串不自动添加换行符。示例读取文件每一行并输出#include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h int main(int argc, char *argv[]) { /* // 打开文件 FILE *fp fopen(./3.txt,r); if(fpNULL){ perror(打开文件失败); return 1; } //按照字符读取文件内容 char ch; //chfgetc(fp); //printf(%c,ch); //while(chfgetc(fp)!-1){ printf(%c,ch); } fclose(fp); }*/ //打开文件 FILE *fpfopen(./4.txt,r); if(fpNULL){ perror(打开文件失败); return 1; } //执行读取文件的内容 char str[16]{0}; //参数一读取的内容放哪个在字符数组中 //参数二读取的数据的数据的最大字节数 //参数3FILE指针 //返回值字符串的首地址如果为NULL表示文件读物 fgets(str,sizeof(str)-1,fp); printf(%s,str); while(fgets(str,sizeof(str),fp)!NULL){ printf(%s,str); //给str设置成0 memset(str,0,sizeof(str)); } fclose(fp); return 0; }4. fscanf / fprintf格式化读写int fscanf(FILE *stream, const char *format, ...); int fprintf(FILE *stream, const char *format, ...);示例从文件读取格式化数据假设文件内容admin a1234 23 male jack 1234 22 maleFILE *fp fopen(users.txt, r); char name[32], pass[32], gender[10]; int age; while (fscanf(fp, %s %s %d %s, name, pass, age, gender) 4) { printf(姓名%s密码%s年龄%d性别%s\n, name, pass, age, gender); } fclose(fp);#include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h int main(int argc, char *argv[]) { FILE *fpfopen(./user.txt,r); if(fpNULL){ perror(打开文件夹); return 1; } //admin,123,20,male char name[32]{0}; char password[32]{0}; int age; char gender[10]{0}; //从文件中读取的数据放到对应的变量中 //参数一表示FILE 指针 //参数二表示格式化字符串占位符可以使用 //参数三地址列表 //fscanf(fp,%s,%s,%d,%s,name.password,age,gender); 这种写法是有问题的适合空格和制表符作为 //分隔符的情况 //%31--最多识别31个字符 //[^,]--直到遇到,为止 //fscanf(fp,%31[^,],%31[^,],%d,%9[^,\n],name,password,age,gender); fscanf(fp,%[^,],%[^,],%d,%[^,\n]\n,name,password,age,gender);//读第一行 printf(用户名:%s,密码:%s,年龄:%d,性别%s\n,name,password,age,gender); fscanf(fp,%[^*]*%[^-]-%d/%[^\n]\n,name,password,age,gender);//读第二行 printf(用户名:%s,密码;%s,年龄;%d性别%s\n,name,password,age,gender); fclose(fp); return 0; }5. fread / fwrite二进制读写size_t fread(void *ptr, size_t size, size_t count, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);示例读写结构体数组#include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h int main(int argc, char *argv[]) { FILE *fp fopen(./6.txt,r); if(fpNULL){ perror(打开文件夹失败); return 1; } //定义字符数组 char str[16]{0}; //实际读取的数据项的个数 size_t count 0; //参数一字符数组 //参数二读取的数据项按照字节来读取 //参数三读取的最大的数据项的个数 //参数四FILE的指针 //fread(str,sizeof(char),sizeof(str)-1,fp); //printf(%s,str); while((countfread(str,sizeof(char),sizeof(str)-1i,fp))0){ //给最后位置设置一个\0 str[count]\0; printf(%s,str); //将str设置成0 memset(str,0,sizeof(str)); } fclose(fp); return 0; }6. fseek / ftell / rewind文件定位int fseek(FILE *stream, long offset, int whence); // 成功返回0 long ftell(FILE *stream); // 返回当前偏移量 void rewind(FILE *stream); // 回到文件开头whenceSEEK_SET开头、SEEK_CUR当前位置、SEEK_END末尾FILE *fp fopen(test.txt, r); fseek(fp, 0, SEEK_END); long size ftell(fp); printf(文件大小%ld 字节\n, size); rewind(fp); // 回到开头准备读取 fclose(fp);7. sprintf / snprintf格式化到字符串int sprintf(char *str, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...);snprintf允许指定一个最大大小来限制写入缓冲区的字符数量示例拼接字符串#include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h int main(int argc, char *argv[]) { //使用sprintf可以完成字符串拼接的作用 char name[]admin; char gender[]male; int age20; float height175; int year2016; int month1; int day2; // 拼接上面的所有的内容放到一个制定的字符数组中 char str[512]{0}; //参数一字符数组 //参数二格式化字符串 //参数三替换格式化字符串中占位符的值的列表 sprintf(str,姓名:%s,性别:%s,年龄:%d,身高:%.2f,出生日期;%4d-%02d-%02d\n,name,gender,age,height,year,month,day) ; printf(%s,str); FILE *fpfopen(./9.txt,w); if(fpNULL){ perror(打开文件夹失败); return 1; } fwrite(str,sizeof(char),strlen(str),fp);//sprintffwritefprintf fflush(fp); fclose(fp); return 0; }8. 标准输入输出函数函数说明getchar()从stdin读取一个字符putchar(c)向stdout输出一个字符puts(s)向stdout输出字符串并自动换行putc(c, fp)向指定流输出一个字符int ch; while ((ch getchar()) ! EOF) {//!\0 putchar(ch); }/*************************************************** # File Name: test09.c # Author: it1412 # Mail: 1017080724qq.com # Created Time: 2026年08月04日 星期二 19时39分07秒 ****************************************************/ #include stdio.h #include stdbool.h #include string.h #include time.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/types.h #include sys/stat.h int main(int argc, char *argv[]) { FILE *fpfopen(./8.txt,r); if(fpNULL){ perror(打开文件失败); return 1; } //putc写入单个字符到文件 //putc(a,fp); //putc(b,fp); //putc(\n,fp); //putc(c,fp); //putc(\n,fp); //fflush(fp); //get从文件中读取单个字符 char ch; //chgetc(fp); //printf(%c,ch); while((chgetc(fp))!EOF){//或者-1 printf(%c,ch); } fclose(fp); return 0; }五、IO函数使用的一般流程fopen打开文件获取文件流指针。使用读写函数如fgets、fputs、fscanf、fprintf、fread、fwrite等进行数据操作。fclose关闭文件流释放资源。1. 统计文件行数#include stdio.h int main() { FILE *fp fopen(test.txt, r); if (!fp) { perror(打开失败); return 1; } int lines 0; char buf[1024]; while (fgets(buf, sizeof(buf), fp)) { lines; } printf(文件行数%d\n, lines); fclose(fp); return 0; }2. 简单日志记录#include stdio.h #include time.h void write_log(const char *user, const char *action) { FILE *log fopen(app.log, a); if (!log) return; time_t now time(NULL); struct tm *t localtime(now); fprintf(log, %04d-%02d-%02d %02d:%02d:%02d | %s, 操作: %s\n, t-tm_year1900, t-tm_mon1, t-tm_mday, t-tm_hour, t-tm_min, t-tm_sec, user, action); fclose(log); } int main() { write_log(admin, 登录操作); write_log(admin, 查询操作); return 0; }3. 在文件每个字母a后插入helloworld#include stdio.h #include string.h int main() { FILE *src fopen(old.txt, r); FILE *dst fopen(new.txt, w); if (!src || !dst) { perror(文件打开失败); return 1; } int ch; while ((ch fgetc(src)) ! EOF) { fputc(ch, dst); if (ch a) { fputs(helloworld, dst); } } fclose(src); fclose(dst); remove(old.txt); rename(new.txt, old.txt); return 0; }
返回列表