前两关为上课时候没有讲到的知识,需要自学,难度比较大。
参考博客:使用FILE结构操作文本文件(文件实训)_【执珪】瑕瑜·夕环玦的博客-CSDN博客_使用file结构操作文本文件
使用FILE结构操作文本文件(文件实训)_【执珪】瑕瑜·夕环玦的博客-CSDN博客_使用file结构操作文本文件
1.文件初始化
FILE *fp = fopen("a.txt","r"); // 打开一个供读取数据的文件a.txt。第一个参数为要打开的文件名,第二个为打开的模式,模式的种类如下:
打开方式 | 描述 |
---|---|
r | 打开一个供读取数据的文件 |
w | 建立或打开一个供写入数据的文件,如果该文件已经存在,则废弃文件内容 |
a | 建立或打开一个供写入数据的文件,如果文件已经存在,则写入的数据将追加到文件的尾部 |
r+ | 打开一个已存在的文件,该文件可以写入和读出数据 |
w+ | 建立或打开一个可供读和写的文件,如果文件已存在,则废弃文件内容 |
a+ | 建立或打开一个可供读和写的文件,如果文件已存在,则写入的数据追加到文件的尾部 |
b | 打开一个二进制文件 |
如果文件打开成功,函数 fopen 将返回一个指向 FILE 结构的指针,该指针指向的 FILE 结构管理了被打开的那个文件。
如果文件打开失败(如打开一个不存在的文件用于读),那么该函数将返回 NULL。上面的程序将返回值赋值给FILE*
的指针 fp ,之后就可以通过 fp 来操作打开的文件了。
2.文件的操作
(1)从文本文件中读取一个字符可以使用 fgetc 函数:
int fgetc(FILE *stream); 参数为文件的指针,比如说初始化中的fp ,返回的是字符的Ascll码,我们可以用字符类型转化,char c=fgetc(fp);就可以读到一个字符。
(2)从文本文件读取一行可以使用 fgets 函数:
char *fgets(char *string, int n, FILE *stream);
该函数表示从文件指针 stream 指向的文件的当前位置开始读取字符串,直到遇到换行符(读入该换行符),或到达文件结束位置,或读取了 n-1 个字符。读取的字符串存入 string 所指的内存单元中,并在所有读取的字符之后添加字符串结束标记\0
。
(3)从文本文件中进行格式化读取可以使用 fscanf 函数和格式化写入可以使用 fprintf 函数:
int fscanf(FILE *stream, const char *format [,argument]...);//与scanf函数的使用类似,
int fprintf(FILE *stream, const char *format [,argument]…);//与printf函数的使用类似,
可以参考C语言fscanf和fprintf函数的用法详解_风叶翩翩的博客-CSDN博客_fprintf和fscanf函数的用法
3.文件关闭
使用 fclose 函数就可以把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区。
函数原型为:
int fclose(FILE *fp);
如果流成功关闭,fclose 返回0,否则返回 EOF(−1)。(如果流为NULL,而且程序可以继续执行,fclose设定error number给EINVAL,并返回EOF。)
第一关
#include <stdio.h>
// 函数extractDigit的功能:从文件a.txt中提取数值写入文件b.txt中
void extractDigit();
// 请在此添加代码,实现extractDigit函数
/********** Begin *********/
void extractDigit()
{
FILE *fpi = fopen("a.txt","r"); // 以读的方式打开文件a.txt
FILE *fpo = fopen("b.txt","w"); // 以写的方式打开文件b.txt
if(fpo==NULL || fpi==NULL) // 如果某个文件打开失败,则返回
{
return;
}
char c=fgetc(fpi);
int s=0,k=0;
while(c!=EOF){
if(c<='9' && c>='0'){
s=s*10+c-'0';
k++;
}
if(k==3){
fprintf(fpo,"%d ",s);
k=0;
s=0;
}
c=fgetc(fpi);
}
if(k!=0){
fprintf(fpo,"%d ",s);
}
fclose(fpi); // 关闭文件fi
fclose(fpo); // 关闭文件fo
}
第二关
#include <stdio.h>
// 结构clothing
struct clothing {
char label[12]; // 编号
float price; // 价格
};
/*
函数readClothing:从文件fp中读取服装信息到cloth中
参数fp:指向打开的二进制文件,cloth:存放读出的服装信息
返回值:服装信息数量
说明:文件中首先以二进制方式存入了一个整数(服装信息数n),然后以二进制方式存入n种服装信息(clothing类型)
*/
int readClothing(FILE *fp, clothing cloth[])
{
// 请在此添加代码,补全函数readClothing
/********** Begin *********/
int n;
fread(&n,sizeof(n),1,fp);
fread(cloth,sizeof(clothing),n,fp);
return n;
/********** End **********/
}
第三关
#include <iostream>
#include <fstream>
using namespace std;
/*
函数count:统计文件fin中每种服装的销售总额,并写入文件fout中
参数fin:文件每种服装的销售情况,fout:每种服装销售总额的写入文件
返回值:无
说明:文件fin中,每种服装信息占一行,分别为服装编号,销售件数,每件的销售价格(整型)。
文件fout:每种服装统计信息占一行,分别为服装编号,销售总额(整型),中间用一个空格隔开。
*/
void count(ifstream & fin, ofstream & fout)
{
// 请在此添加代码,补全函数count
/********** Begin *********/
char s[100];//编号
int num;//销售数量
int price;//每次的价格
int money=0;//销售总钱数
int i=0;
while(fin>>s){
fout<<s<<" ";
fin>>num;
for(int i=0;i<num;i++){
fin>>price;
money+=price;
}
fout<<money<<endl;
money=0;
}
/********** End **********/
}
第四关
#include <fstream>
#include <string.h>
#include <iostream>
using namespace std;
// 结构clothing
struct clothing {
char label[12]; // 编号
int numberRemaining; // 剩余件数
};
/*
函数getNumber:在文件ifile中查找标签为lable的服装数量
参数ifile:存放服装信息的文件,label:要查找的服装标签
返回值:标签为label的服装数量
说明:文件中ifile中存放着服装信息,服装信息为以二进制写入的一个个clothing结构变量
*/
int getNumber(ifstream &ifile, char *label)
{
// 请在此添加代码,补全函数getNumber
/********** Begin *********/
int num;
clothing t;
ifile.read((char*)&t,sizeof(clothing));
while(!ifile.eof()){//判断是否到了结尾
if(strcmp(label, t.label)==0){//label==t.label判断不出来,这里是二进制打开
num=t.numberRemaining;
break;
}
ifile.read((char*)&t,sizeof(clothing));
}
return num;
/********** End **********/
}