【文件实训】使用FILE结构操作文本文件

文件类型
C 语言在对文件进行操作时,将文件分为文本文件和二进制文件。
文本文件:指可以用任何文字处理程序阅读和编辑的简单 ASCII 文件;
二进制文件:指一般含有特殊的格式或计算机代码,如图形文件和可执行文件等。

下面我们本章节所学的操作都是针对文本文件而言。

文件的操作
C 语言中对文件的操作一般分为三个步骤:打开文件、读写文件、关闭文件。

打开文件
打开文件后,操作系统为文件建立一个文件控制结构(文件控制块),并在内存中建立一个缓冲区,该缓冲区的数据对应文件的数据,之后的文件读写操作实际上是在缓冲区中进行。

读写文件
通过文件控制块实现文件的输入输出。

关闭文件
将文件缓冲区中的数据写回到磁盘文件中,并释放文件控制块。

操作文件的函数
用 FILE 结构操作文件是 C 语言提供的文件操作方式,只要包含头文件stdio.h就能使用文件操作的相关函数。下面就给大家介绍一些函数的使用。

打开文件
fopen 是stdio.h提供的文件打开函数。

如下面的程序可以打开一个文件用于读:

#include <stdio.h>
FILE *fp = fopen(“a.txt”,“r”); // 打开一个供读取数据的文件a.txt。
其中函数的第一个参数是拟打开文件的路径和名字,可以包含相对路径或者绝对路径,如上面程序中就是打开当前目录下的a.txt文件。第二个参数是打开方式,fopen函数可以使用的打开方式如下表:

打开方式 描述
r 打开一个供读取数据的文件
w 建立或打开一个供写入数据的文件,如果该文件已经存在,则废弃文件内容
a 建立或打开一个供写入数据的文件,如果文件已经存在,则写入的数据将追加到文件的尾部
r+ 打开一个已存在的文件,该文件可以写入和读出数据
w+ 建立或打开一个可供读和写的文件,如果文件已存在,则废弃文件内容
a+ 建立或打开一个可供读和写的文件,如果文件已存在,则写入的数据追加到文件的尾部
b 打开一个二进制文件
如果文件打开成功,函数 fopen 将返回一个指向 FILE 结构的指针,该指针指向的 FILE 结构管理了被打开的那个文件。

如果文件打开失败(如打开一个不存在的文件用于读),那么该函数将返回 NULL。上面的程序将返回值赋值给FILE*的指针 fp ,之后就可以通过 fp 来操作打开的文件了。

读写文件
从文本文件中读取一个字符可以使用 fgetc 函数:
int fgetc(FILE *stream);
该函数表示从文件指针 stream 指向的文件的当前位置读取一个字符,并以 int 类型返回。

从文本文件读取一行可以使用 fgets 函数:
char *fgets(char *string, int n, FILE *stream);
该函数表示从文件指针 stream 指向的文件的当前位置开始读取字符串,直到遇到换行符(读入该换行符),或到达文件结束位置,或读取了 n-1 个字符。读取的字符串存入 string 所指的内存单元中,并在所有读取的字符之后添加字符串结束标记\0。

如果读取成功,函数返回 string,如果出错或读取前已经到达了文件结束的位置,将返回 NULL。

从文本文件中进行格式化读取可以使用 fscanf 函数:
int fscanf(FILE *stream, const char *format [,argument]…);
该函数的功能是从指定文件中将数据按照格式控制串 format 读出并转换成相应的类型以存入对应的参数中。如果读取成功,该函数返回转换成功的参数的个数,如果出错或读取前已经到达了文件结束的位置,将返回文件结束标志 EOF。

函数 fscanf 与 scanf 函数非常相似,只是 fscanf 函数多了一个参数 stream 以指向要读取数据的文件。

输出格式化数据到文本文件中可以使用 fprintf 函数:
int fprintf(FILE *stream, const char *format [,argument]…);
该函数的功能是将数据按照格式控制串 format 写入到文件指针 stream 指向的文件中。如果写入成功,函数返回写入的字节数,否则返回一个负数表示错误。

函数 fprintf 与 printf 函数相似,只是 fprintf 函数多了一个参数 stream 以表示要写入数据的文件。

关闭文件
使用 fclose 函数就可以把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区。

函数原型为:

int fclose(FILE *fp);
如果流成功关闭,fclose 返回0,否则返回 EOF(−1)。(如果流为NULL,而且程序可以继续执行,fclose设定error number给EINVAL,并返回EOF。)

例如:

#include <stdio.h>
int main(){
FILE *fp;
fp = fopen(“a.txt”, “w”);
fprintf(fp, “%s”, “www.educoder.net”);
fclose(fp);
return(0);
}

版本1

    FILE * fa = fopen("a.txt", "r");
    FILE * fb = fopen("b.txt", "w");
    int idx=0;
    int val = 0;
    char ch;
    while((ch = fgetc(fa)) != EOF)
    {
        if(isdigit(ch))
        {
            val =val * 10 + (ch - '0');
            idx++;
            if(idx  == 3)
            {
                fprintf(fb, "%d ", val);
                idx = val = 0;
            }
        }
    }
    if(idx)fprintf(fb, "%d ", val);
    fclose(fa);
    fclose(fb);

版本2

    ifstream in("a.txt");
    ofstream out("b.txt");

    string line;
    getline(in, line);
    string nums;
    nums.reserve(line.size());

    for (auto ch : line)if (isdigit(ch))nums.push_back(ch);

    int i = 0;
    for (; i < nums.size(); )
    {
        if (i + 3 < nums.size())
        {
            out << stoi(string(nums.begin()+i,nums.begin()+i+3)) << endl;
            i += 3;
        }
        else
        {
            out << stoi(string(nums.begin()+i, nums.end())) << endl;
            break;
        }
    }
    
    in.close();
    out.close();

版本3

    int arr[1000];
    FILE* fa = fopen("a.txt", "r");
    int len = 0;
    if (true)
    {
        int ch;
        while ((ch = fgetc(fa)) != EOF)
        {
            if (isdigit(ch))
            {
                arr[len++] = ch - '0';
            }
        }
    }
    fclose(fa);

    FILE* fb = fopen("b.txt", "w");
    
    for (int i=0; i < len; )
    {
        if (i + 3 <= len)
        {
            int val = arr[i] * 100 + arr[i+1] * 10 + arr[i+2];
            fprintf(fb, "%d ", val);
            i += 3;
        }
        else
        {
            int val = 0;
            if(i+2==len)val = arr[i] * 10 + arr[i + 1];
            if(i+1==len)val = arr[i];
            fprintf(fb, "%d ", val);
            break;
        }
    }

    fclose(fb);
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值