写这篇博客原因:
c程序课设 忙的头昏脑涨,看了大量的博客。但是发现,文件操作这方面很少有简单易懂实用的博客。我作为大一新生,把自己学到的一点点文件操作功能分享一下。希望可以加快学者们的步伐。
源代码在最下面!
已更新代码 新加说明书界面 修改信息功能及界面超帅
再次更新代码 新加了智能化功能
**1.读取文件信息到链表。 省去了手动输入的麻烦
老师力推这个功能!!
2.删除读入的全部信息。**
与基本功能配套使用 很完美
喔对了。系统可以使用特殊符号 记得自己尝试一下
还没学如何快速到达自己感兴趣的模块 不好意思。。。。
1.数据储存到文件
2.如何按格式读取文件想要的信息,常用于密码登录。
进入正题:
先看效果 是不是你们想要的。
这是写出后的两个文件对比;
左边是录入原数据,右边是排名计算后写入的数据。
上代码(可以先看下代码下方的分部解析)
1.原始数据储存 功能函数
void Save_massage1(struct stu*p_Head) {
struct stu* p = p_Head;
char s[100] = {
"NAME\tNO.\t sco1 sco2 sco3 sco4 sco5 sco6 sco7 sco8 sco9 sco10 \n" };
char s2[100] = {
"-----------------------------------------------------------------------------------\n" };
//打开文件
//定义一个文件指针p_file
FILE* p_File;//这里是文件结构体声明 这里不展开。没有它不行
p_File = fopen("playerOriginal.dat.txt", "w");
if (p_File == NULL) {
printf("打开文件失败\n");
return 0; //exit (0);
}
else
//写入数据
{
fprintf(p_File, "%s", s);
fprintf(p_File, "%s", s2);
while (p!= NULL)
{
int i = 0;
fprintf(p_File, "%s\t", p->name);
fprintf(p_File, "%d\t", p->rank);
for (i = 0; i < 10; i++)
{
fprintf(p_File, "%6.2f", p->score[i]);
}
fprintf(p_File, "\n");
p = p->p_next;
}
}
printf("本地保存成功\n");
//关闭文件
fclose(p_File);
}
首先看这个格式:如何实现?
先将你的格式写入字符串 ,用fprintf库函数先将你的格式所在的字符数组写入文件,然后在写入链表内容数据。
(不用fwrite是因为这个是二进制写入 写int 数据会乱码 所以没有深入了解)
2.排名后数据储存 功能函数
void Save_massage2(struct stu* p_Head) {
//打开文件
//定义一个文件指针p_file
FILE* p_File; //这里是文件结构体声明 这里不展开。没有它不行
p_File = fopen("playerGrade.dat.txt", "w");
if (p_File == NULL) {
printf("打开文件失败\n");
return 0; //exit (0);
}
else
printf("本地保存成功\n");
struct stu* p = p_Head;
char s[100] = {
"NAME\tNO.\t sco1 sco2 sco3 sco4 sco5 sco6 sco7 sco8 sco9 sco10 average\n" };
char s2[100] = {
"---------------------------------------------------------------------------------------------\n" };
//写入数据
fprintf(p_File, "%s", s);
fprintf(p_File, "%s", s2);
while (p != NULL)
{
int i = 0;
fprintf(p_File, "%s\t", p->name);
fprintf(p_File, "%d\t", p->rank);
for (i = 0; i < 10; i++)
{
fprintf(p_File, "%6.2f", p->score[i]);
}
fprintf(p_File, "%6.2f\n", p->aver);
p = p->p_next;
}
//关闭文件
fclose(p_File);
}
这里的实现跟上面那个差不多
这个文件名要自己输入你的txt文件名**(txt文件与你的c语言代码源文件在一起哦!一个人多孤单!)**
文件比较乱哈哈
3.最后一个文件操作功能压轴出场:
文件写入后的读取,与密码登录系统有关。
如何正确读取你想要的数据呢。
看代码!
/* struct stu {
int rank;
char name[20];
float score[10];
float aver;
struct stu* p_next;
};
struct Stu {
int rank;
char name[20];
float score[10];
float aver;
};*/
//这里用的是第二个 读取信息。
//第一个是链表节点
void Read_file(char name[])
{
int i;
struct Stu p_temp = {
0," ",0,0 }; //这里用的是vs2019 如果代码不在一个文件内 需要进行结构体定义;
FILE* fp;
char filename[30] = {
"playerGrade.dat.txt" };//z这里是要读取的文件名
if ((fp = fopen(filename, "r+")) == NULL)//判断文件是否打开失败
{
printf("can not open!\npress any key to continue\n");
getchar();
exit(0);
}
else
{
int j;
//对文件读写操作 行 列。 for 循环 行读取 便读取边赋值结构体变量。
fseek(fp,173, 0);//跳过开头
for (i = 0; i<N; i++)
{
//这里比较笨拙 读者看看有没有方法简化 这里用fscanf 库函数 注意 %f与f%之间是空格哦 要注意这个问题 写入文件的时候就是隔个空格 写出格式要相同
fscanf(fp, "%s %d %f %f %f %f %f %f %f %f %f %f %f\n", &p_temp.name, &p_temp.rank, &p_temp.score[0], &p_temp.score[1], &p_temp.score[2], &p_temp.score[3], &p_temp.score[4], &p_temp.score[5], &p_temp.score[6], &p_temp.score[7], &p_temp.score[8], &p_temp.score[9], &p_temp.aver);
//是否找到
//这里采用名字登录,读者可以升级为学号登录。
if (strcmp(p_temp.name, name) == 0)
{
Menu_player();//这里是我自定义的界面函数 可忽略
system("pause");//忽略
//这个是界面设置 前面一半在主函数 读者自己设计界面美化
//下面的printf 内的** 星号 空格都是为了界面美化搞得 可以不要
printf("** 姓名%s\t", p_temp.name);
printf("排名%d\t", p_temp.rank);
//十个评委的分数可不要
/*for (j = 0; j < 10; j++)
{
printf("%6.2f ", p_temp.score[j]);
}*/
printf("最终成绩:%6.2f **\n", p_temp.aver);
printf("*************************************************\n");
printf("************--欢迎下年再来--*********************\n");
break;
}
}
//文件查找 相同姓名 然后输出那一行内容
if (strcmp(p_temp.name, name) != 0)
printf("输入信息错误,或者未录入。");
system("pause");
system("cls");
fclose(fp);
}
问题来了:
1.文件内容开头是我们的格式 并不需要读取,那么怎么跳过?
这里利用fseek库函数
fseek(fp,173, 0);//跳过开头格式
fseek(文件指针,跳过的字节数,从哪里开始跳)
文件指针 经过上面两个信息储存大家应该了解了,
那么字节数怎么把控?一个一个数?其中’+’’-'代表往前往后跳。
我们用的是+
往哪里跳,0 开头,1当前所在位置 这个目前还没用过,2从尾开始跳
我们用的是0 开头
下面就看怎么获得格式数据的字节数了 ,如何刚刚好跳过没用信息?
看操作
都秒懂是吧???
不过要注意
这里我读取的是我的第二个文件
两个文件的格式不一样哦
多一个average
2.如何正确读取文件数据到变量;
我这里写入的时候就是用的链表数据写入的
所以我定义了一个结构体 类型 不含 next指针
用第二种;
看代码:
呃,,,,自己往上面翻。
下面将我的整个代码给出来吧。
我是用vs2019 写的 忽略scanf警告
如何忽略?
看图 两种方法
右击源文件 点属性
在预处理器定义内输入 _CRT_SECURE_NO_WARNINGS
每建立一个新文件都需要这个操作
第二种方法;
在代码前头加
#define _CRT_SECURE_NO_WARNING
例如:
如果有不足的地方或者可以优化的地方 还望指出 每个代码人 都渴望提升啊。
评分管理系统要求如图:
#include<stdio.h>
#include<string.h>
#include<process.h>
int i_count=0;
int menu1=1, menu2=1;//菜单选项
#define N 10 //最大节点数 可修改
//说明书界面
void Menu_help()
{
printf("*****************比赛评分系统灿哥版520.v*******************\n");
printf("** **\n");
printf("**_____________________--欢迎使用--_____________________ **\n");
printf("** **\n");
printf("** **\n");
printf("***************《详细说明书.爱心6.0tv版》******************\n");
printf("**-------------------------------------------------------**\n");
printf("** **\n");
printf("**一、姓名确定身份!决定你的权限 **\n");
printf("** **\n");
printf("**二、按照功能菜单进行键入对应数字! **\n");
printf("** **\n");
printf("**三、选手只能查取自己对应的最终成绩! **\n");
printf("** **\n");
printf("**四、管理员切记按正常顺序操作,记得保存录入的信息到文件!**\n");
printf("** **\n"