C语言复习——文件操作以及各种输入输出
翁老师说现在很少有人直接用C语言来操作文件来储存或者读取数据了,稍微有点量的用数据库。个人觉得C语言实现文件操作还是挺有意思的。做个练习——一个简单的学生信息系统
头文件
#ifndef _STUDENT_H_
#define _STUDENT_H_#define STR_SIZE 20
/*声明学生结构体*/
typedef struct _student{int id;char name[STR_SIZE];int gender;int age;
}STUDENT;
#endifvoid getlist(STUDENT *std,int num);//读入学生信息
int save(STUDENT *std,int num);//储存至文件
void read(FILE *fp,int cnt);//读取数据
main函数,确定学生数量,调用getlist(),用数组存储(也可用链表);调用save(),将数据保存至文件;调用read(),读取数据。
#include <stdio.h>
#include <stdlib.h>
#include "student.h"int main(int argc, char *argv[]) {int num=0;printf("请输入学生数量:");scanf("%d",&num);STUDENT std[num];//学生结构数组 getlist(std,num);//读取数据,也就是给给各元素的成员赋值 printf("是否保存数据?(1-保存,0-取消)");int flag=-1;scanf("%d",&flag);if(flag){if(save(std,num)){printf("保存成功\n");}else{printf("保存失败\n");}}/*读取*/FILE *fp=fopen("student.date","r");if(fp){
//fseek()函数可将文件指针指向某位置,SEEK_SET-文件头,SEEK_END-文件末,SEEK_CUR-文件当前位置,第二个参数是偏移字节数,+-决定偏移方向 fseek(fp,0,SEEK_END);
//ftell()函数,定位文件指针位置,返回文件头到该位置的字节数int num=ftell(fp)/sizeof(STUDENT);printf("共有%d个数据,要看第几个?",num);int cnt;scanf("%d",&cnt); read(fp,cnt);fclose(fp);}return 0;
}
分别用二进制模式和文本模式写入、读取文件
void getlist(STUDENT *std,int num){char format[STR_SIZE];sprintf(format,"%%%ds",STR_SIZE-1); //利用格式化输出,做一个格式字符串“%19s” for(int i=0;i<num;i++){printf("请输入第%d个学生的信息\n\t学号:",i+1);scanf("%d",&std[i].id);printf("\n\t姓名:");scanf(format,std[i].name);//格式字符串的地址替代“%s”printf("\n\t性别(0-女,1-男):");scanf("%d",&std[i].gender);printf("\n\t年龄:");scanf("%d",&std[i].age);}
}
int save(STUDENT *std,int num){int ret=0;FILE *fp=fopen("student.date","w");if(fp){ret=fwrite(std,sizeof(STUDENT),num,fp);//二进制写入文件
//文本写入文件
// for(int i=0;i<num;i++){
// fprintf(fp,"学号:%d",std[i].id);
// fprintf(fp,"\n姓名:%s",std[i].name);
// fprintf(fp,"\n性别:%s",(std[i].gender==1?"男":"女"));
// fprintf(fp,"\n年龄:%d",std[i].age);
// fprintf(fp,"\n");
// }
// ret=1;//文本模式下赋值1,代表执行到此,写入成功 fclose(fp);}else{printf("文件打开失败!");}
// return ret;return ret==num;//二进制写入文件fwrite()返回值为写入 某个结构体(某大小字节块) 的个数
}
/*读取文件内数据*/
void read(FILE *fp,int cnt){
//以文本模式读取文件内容,一次读入100个字符,fgets遇行末‘\0’停止、遇到换行停止。
// char s[100];
// while(fgets(s,100,fp)){
// printf("%s\n",s);
// }
//以二进制模式读取文件内容,可用fseek()函数定位至第几个结构。 STUDENT std;fseek(fp,(cnt-1)*sizeof(STUDENT),SEEK_SET);fread(&std,sizeof(STUDENT),1,fp);printf("学号:%d\n",std.id);printf("姓名:%s\n",std.name);printf("性别:%s\n",std.gender==1?"男":"女"); printf("年龄:%d\n",std.age);
}
注意:r+和w+的读写模式,在第一次读取或者写入后,文件指针会指向读取或者写入的当前位置,无法继续进行反向操作。只有rewind()重置指针位置至文件头才能继续。
w和w+会清空原文件内容;
a和a+是在文件末追加内容,不会清空原文件内容;
r+会覆盖原文件内容。
补充知识点,格式化输入输出:
一、格式化输出
printf("%d",i)中,%d为格式化输出字符串在%和d中间可以添加4种参数:
%[flag][width][.prec][hil]type
1、flag
flag | 含义 |
- | 左对齐 |
+ | 显示+-符号 |
空格 | 正数留空 |
0 | 0填充所占位数 |
例:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char const *argv[]){int a=50,b=-100;printf("|%-+9.5d|\n|%+-9.4d|\n",a,b);system("pause");return 0;
}
2、width和.prec
width/.prec | 含义 |
number | 输出所占字符数 |
.number |
对于float保留几位小数 对于int是填补0后共占用几个字符数 |
* | 将number作为参数替代字符串中的* |
.* | 将.number作为参数替代字符串中的.* |
例:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char const *argv[]){float a=50,b=-100;printf("|%-+*.*f|\n|%+-*.*f|\n",9,6,a,9,5,b);system("pause");return 0;
}
由此可得当[width]和[.prec]冲突时,以[.prec]为主,width自动增加。
3、HIL
类型修饰(HIL) | 含义 |
hh | 以单字节形式输出 |
h | short |
l | long |
ll | long long |
L | long double |
hh以单字节形式输出:例如一个整形占4个字节,hh将最小字节上的内容输出。
例:12345 二进制最小字节内容为0011 1001,则输出为57。
但:我的电脑hhd单字节格式输出不正常, 不知道什么原因。。。
当printf("%hhd",(char)a);输出单字节整数时,对a进行强制类型转换,输出57正确。
#include <stdio.h>
#include <stdlib.h>int main(int argc,char const *argv[]){int a=12345;printf("%i\n",a);//a可以是8/10/16进制的任何一种 printf("%u\n",a);//unsigned 无符号整形 printf("%o\n",a);//八进制整形 printf("%x\n",a);//十六进制整形 printf("%hhd\n",(char)a);//单字节整形 unsigned int mask=1;for(mask=1u<<31;mask;mask>>=1){//二进制printf("%d",a&mask?1:0); }return 0;
}
#include <stdio.h>
#include <stdlib.h>int main(int argc,char const *argv[]){int a=54321;printf("%hhi\n",a);//a可以是8/10/16进制的任何一种 printf("%hhu\n",a);//unsigned 无符号整形 printf("%#o\n",a);//八进制整形 #可以显示8和16进制的前缀 printf("%#x\n",a);//十六进制整形 printf("%hhd\n",(char)a);//单字节整形 unsigned int mask=1;for(mask=1u<<31;mask;mask>>=1){//二进制 printf("%d",a&mask?1:0); }return 0;
}
4、利用格式化输出可以自己制作格式化输出字符串。
例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define len 20
int main(int argc,char const *argv[]){float a=50,b=-100;char format[len];sprintf(format,"%%%ds",len-1);//自定义一个格式化字符串"%19s"输出到format里面.printf("%s\n",format);char name[len];scanf(format,name);printf("%s\n",name);return 0;
}
二、格式化输入
scanf("%d",&a);
%[flag]type
flag | 含义 | flag | 含义 |
* | 跳过 | l | long |
number | 输入最大字符数 | ll | long long |
hh | char | L | double long |
h | short |
type | 含义 | type | 含义 |
d | int | a/e/f/g | float |
i | 可8可10可16 | c | char |
u | unsigned int | s | 字符串 |
o | 8进制 | p | 指针 |
x | 16进制 | [^。] | 。前的所有字符 |
*跳过输入指定格式;i的输入格式可为10、8、16三种进制
例:
#include <stdio.h>
#include <stdlib.h>int main(int argc,char const *argv[]){int num;scanf("%*d%i",&num);printf("%d",num);return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define len 20
int main(int argc,char const *argv[]){char str[len];scanf("%*[^.].%[^.].",str);
//%*[^.].跳过.前面所有字符并读掉.;%[^.].读取.前面的所有字符放入str,并读掉.printf("%s",str);return 0;
}
三、scanf和printf的返回值
scanf返回值为整形,返回读取的变量个数。
printf返回值为整形,返回输出的字符个数。
#include <stdio.h>
#include <stdlib.h>
#define len 20
int main(int argc,char const *argv[]){char str[len];int a=scanf("%*[^.].%[^.].",str);int b=printf("%s\n",str);printf("a:b=%d:%d",a,b);return 0;
}
a为读取的变量个数,在程序中第一个字段跳过,第二个字段存入了str也就是读取了一个字符数组。b为输出的字符个数,在程序中输出了str,也就是san以及\n换行共4个字符。
四、其他输入输出方式
C语言除了scanf和printf外,还有getchar和putchar用于读取和输出单个字符;gets和puts用于读取和输出字符串;fgets和fputs也是用来读取和输出字符串;fscanf和fprintf用来和文件交互,读取或者输入。用法如下:
1、int c=getchar(void)读入单个字符,存为int型;int num=putchar(c),输出单个字符,返回该字符的int型值。
2、char *str=gets(char *str);读入字符串,存入str.该函数遇到换行符结束读取,会将换行符读掉,并在字符串末尾添加\0;该函数无法控制读取内容长度,存在越界风险。
int n=puts(char *str);输出字符串,自动换行,返回非负整数表示输出成功,EOF表示失败。
3、char *str=fgets(char *str,int ,FILE *);从文件中或者缓冲区stdin读取字符串,存入str字符数组中,读取长度为str长度-1,自动添加\0终止符。遇到\n终止读取,如果\n在字符数组长度范围内,换行符会被存入str并以\0结尾,如果\n刚好落在字符数组最后一位,将被转换为\0。当缓冲区字符串长度超过str长度,剩余的字符会留在缓冲区。
int n=fputs(char *str,FILE*);向文件或者输出流输出字符串str,不会自动换行,返回非负整数表示成功,EOF表示失败。
4、int n=fscanf(FILE*,格式化字符串,存入地址);从文件流或者输入流读取内容,可以是任意类型格式化字符串,存入相应的变量地址,返回值是读取变量的数量。当读取字符串时,遇到任意空字符(空格、制表符、换行符)均结束读取,空字符依然存在流中。返回值为读取数据个数,失败或者结尾返回EOF。
int n=fprintf(FILE*,format,变量名);向文件或者缓冲区输出数据,可以是任意类型变量,配合相应的格式化字符串。当输出字符串时,遇到\0结束,返回值为输出字符个数,失败返回EOF。
5、int getc(FILE *stream)和int putc(FILE *stream)两个函数,基本功能和getchar()/putchar一样,不仅用于终端单个字符的读取和输出,还能用于文件中单个字符的输入和输出。
C语言复习——文件操作以及各种输入输出相关推荐
- C语言进阶-文件操作超详解
目录 为什么使用文件 什么是文件 分类(从文件功能的角度) 文件名 文件的打开和关闭 文件指针 fopen和fclose函数 打开方式表 文件的顺序读写 顺序读写函数表 什么是输入输出流 fgetc/ ...
- 【C 语言】文件操作 ( 配置文件读写 | 写出或更新配置文件 | 追加键值对数据 | 更新键值对数据 )
文章目录 一.追加键值对数据 二.更新键值对数据 三.完整代码示例 一.追加键值对数据 在上一篇博客 [C 语言]文件操作 ( 配置文件读写 | 写出或更新配置文件 | 逐行遍历文件文本数据 | 获取 ...
- 【C 语言】文件操作 ( 按照单个字符的方式读写文件 | fgetc 函数 | fputc 函数 )
文章目录 一.文件名路径设置 二.文件打开方式 三.fputc 函数 | 按照字符方式写文件 1.fputc 函数 2.代码示例 四.fgetc 函数 | 按照字符方式读文件 1.fgetc 函数 2 ...
- 【C 语言】文件操作 ( 学生管理系统 | 命令行接收数据填充结构体 | 结构体写出到文件中 | 查询文件中的结构体数据 )
文章目录 一.学生管理系统 二.代码示例 一.学生管理系统 前两篇博客 [C 语言]文件操作 ( 将结构体写出到文件中并读取结构体数据 | 将结构体数组写出到文件中并读取结构体数组数据 ) [C 语言 ...
- 【C 语言】文件操作 ( 使用 fread 和 fwrite 实现二进制文件的拷贝 | stat 统计文件大小 | feof 判定文件结尾 )
文章目录 一.stat 统计文件大小 二.feof 判定文件结尾 三.使用 fread 和 fwrite 实现二进制文件的拷贝 一.stat 统计文件大小 统计文件大小 , 需要借助 stat 结构体 ...
- c读取ini配置文件_Go-INI - 超赞的Go语言INI文件操作库
INI 文件(Initialization File)是十分常用的配置文件格式,其由节(section).键(key)和值(value)组成,编写方便,表达性强,并能实现基本的配置分组功能,被各类软件 ...
- go 默认http版本_【每日一库】超赞的 Go 语言 INI 文件操作
点击上方蓝色"Go语言中文网"关注我们,领全套Go资料,每天学习 Go 语言 如果你使用 INI 作为系统的配置文件,那么一定会使用这个库吧.没错,它就是号称地表 最强大.最方便 ...
- c语言数据文件是,C语言数据文件操作.ppt
C语言数据文件操作 第十一章 文件 11.1 C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 文件处理方法 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区 ...
- c语言课程设计 水电系统,广东工业大学水电费系统c语言设计(文件操作部分)
广东工业大学水电费系统c语言设计(文件操作部分) (8页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 本人工作:主机和客户端的文件操作,主机 ...
最新文章
- vue之mapMutaions的使用 vuex中 action 用法示例 api.js的使用
- 手动部署OpenStack环境(五:新建网络及部署虚拟机)
- Linux多线程实践(3) --线程属性
- 数据挖掘建模之常见概率分布总结
- iOS-在团队开发过程中控制代码版本
- Duilib嵌入CEF以及JavaScript与C++交互
- php中文网侵权事件,【杂谈】程序员删库跑路事件,php中文网的几点声明!
- Java 泛型中的? super T和? extends T
- Unity教程之-Unity3d中针对Android Apk的签名验证(C#实现)
- 教你一种U盘病毒的快速检测方法
- C#:SQLite大量插入的效率问题
- 百度地图多点路线规划_自驾游路线规划神器:高德地图路书功能
- 系列课程 ElasticSearch 之第 6 篇 —— 自定义扩展分词文件、文档映射
- AliExpress国际速卖通唰信誉用什么虚拟卡用信可以成功扣款?
- --save-dev 与 --save的区别
- 联想Win10安装Ubuntu双系统教程
- module ‘cv2‘ has no attribute ‘face‘已安装仍报错解决
- 企业邮箱品牌哪家好?四大品牌企业邮箱推荐
- win10此电脑不见了_Win10如何把控制面板放到桌面上?Win10控制面板不见了解决方法...
- Java多线程同步和异步详解