c语言:文件处理操作-2

简介: c语言:文件处理操作

c语言:文件处理操作-1

https://developer.aliyun.com/article/1515718


四、顺序读写

我们已经知到该如何打开和关闭我们要访问的文件,但是,如何对文件内部用代码进行操作呢?

接下来就要谈到顺序读写函数

顺序读写函数

功能 函数名 用于
字符输入函数 fgetc 所有输入流
字符输出函数 fputc 所有输出流
文本行输入函数 fgets 所有输入流
文本行输出函数 fputs 所有输出流
格式化输入函数 fscanf 所有输入流
格式化输出函数 fprintf 所有输出流
二进制输入 fread 文件
二进制输出 fwrite 文件


1、fputc

作用:将字符写入文件

返回值为字符ascll码值,类型为int,int character 为字符的ascll码值,stream为文件流

  • 返回值为所写入字符的ascll码值。
  • 每次写入都会让位置指示器所指向的字符将向后移一位
  • 如果写入错误,将会返回EOF,并为文件指示器设置ferror。

例如,我们要对一个文本文件进行写入26个小写字母的操作:

#include<stdio.h>
#include<stdlib.h>
int main()
{
  int a = 0;
  FILE* pf = fopen("ilike.txt", "w"); //打开文件
  if (pf == NULL)
    printf("pf fopen \"ilike\" fail");
  else
  {
    for (int i = 0;i < 26;i++)
    {
      a=fputc('a'+i, pf);//文件写入操作
      printf("%d ", a);
    }
    fclose(pf);//关闭文件
    pf = NULL;//将pf滞空,防止野指针
  }
  system("pause");
  return 0;
}


打开项目目录查看ilike.txt的文件查看,结果如下:

 

2、fgetc

既然能将字符写入文件,那么自然也能从文件读取字符进行输出。我们查阅c++reference可以看到


解释说明:

  •   int fgetc (FILE * stream); 返回值为访问的文件的当前位置指示符指向的字符的ascll码值,参数为文件流。
  • 每次读取后,当前位置指示符指向的字符会指向下一个字符
  • 如果在调用的时候遇到文件尾,则返回EOF(值为-1).
  • 如果读取错误,则返回EOF并为流设置错误指示符FERROR。


读的时候,打开方式用"r",我们读取上面用fputc写入的26个小写字母并打印出来,举个例子:

#include<stdio.h>
#include<stdlib.h>
int main()
{
  int arr[26] = { 0 };
  FILE* pf = fopen("ilike.txt", "r");
  if (pf == NULL)
    printf("pf fopen \"ilike\" fail");
  else
  {
    for (int i = 0;i < 26;i++)
    {
      arr[i] = fgetc(pf);
    }
    fclose(pf);
    pf = NULL;
  }
  for (int i = 0;i < 26;i++)
  {
    printf("%c ", arr[i]);
  }
  system("pause");
  return 0;
}


运行结果如图

如果对文件的操作每次只能读取或者写入一个字符,那么效率会不会有点低下了?

这就要说说下面两个函数了:fgets,fputs。


3、fputs

首先想要使用这个函数,就必然要看看这个函数是如何定义的,同样我们查阅c++reference:


解释一下:

  • 作用:将一个字符串写入文件流。(str是要写入的字符串,stream为文件流)
  • 如果写入成功,则返回一个非负的值,如果写入失败则返回EOF,并未该文件设置错误的指示器。
#include<stdio.h>
#include<stdlib.h>
int main()
{
  char arr[10] = { 0 }; //定义要写入的字符串
  int a = 0;
  for (int i = 0;i < 9;i++)
  {
    arr[i] = 'x';
  }
  FILE* pf = fopen("ilike.txt", "w"); //打开文件
  if (pf == NULL)
    printf("pf fopen \"ilike\" fail");
  else
  {
    a=fputs(arr, pf); //写入文件
    fclose(pf);    // 关闭文件
    pf = NULL;    //指针置空
  }
  printf("%d", a);
  system("pause");
  return 0;
}


打开工程目录里面的ilike.txt文件,结果如下

(我们用一个整形接收fputs的返回值,结果为0)

注意: 如果使用两个 fputs(),对一个文件分别写入两个字符串,如果第一个写入的字符串末尾没有'\n',那么两个字符串将会在同一行进行写入。

 

4、fgets

既然能一行一行地写入,那么必然能一行一行地读取:查阅c++reference,结果如下


  这里不再进行过多地截取,可以自行查阅

  cplusplus网站:

cplusplus.com - The C++ Resources Network

https://legacy.cplusplus.com/


  • 返回值为读取到地字符串的地址,类型为char*
  • 读一个字符串,然后将字符串存入str所指向的数组,直到遇到换行符或者文件末尾
  • 使用int num来控制读取字符串的长度。
  • fgets读取遇到换行符停止读取,但是函数认为他是有效字符,并将其一起复制到str指向的字符串。
  • 在读取完字符后,str后面会自动追加终止字符。
  • 如果读取错误,则返回值为一个空指针,成功则返回的是str。

直接上代码:

#include<stdio.h>
#include<stdlib.h>
int main()
{
  char arr[100] = { 0 };
  FILE* pf = fopen("ilike.txt", "r");
  if (pf == NULL)
    printf("pf fopen \"ilike\" fail");
  else
  {
    fgets(arr,23,pf);
    fclose(pf);
    pf = NULL;
  }
  printf("%s", arr);
  system("pause");
  return 0;
}


这里,文件里面原来的数据为a-z,26个小写字母。我们使用fgets(arr,23,pf)来读取前23位

并打印arr,结果如下:后三位如预测结果一样未打印。


注意:这里不管是每行还是单个字符读取,每次操作完,位置指示器都会指向下一个将被读取的目标。

例如读取  文本文件中存在这样一串数据 :  abcdefgh
使用fgets 读取前五个字符,原本位置指示器指向a,在读取五个字符后,位置指示器指向f所在的位置

对于文件的操作如果只是单个字符或者单个字符串的进行读取和写入,那么对文件的操作的精准度就不会很高,所以定义格式化输入输出函数来对文件进行操作:

5、fprintf

将文件格式化输出,其定义如下

stream为要写入的文件流,后面紧跟要输入数据的格式和对应的数据。

直接上代码:我们格式化写入一个结构体类型的数据。

  • 如果写入成功,则返回写入字符的总数
  • 如果写入错误,则设置指示符FERROR并返回一个负数
#include<stdio.h>
#include<stdlib.h>
struct S
{
  char name[20];
  int age;
};
int main()
{
  S s = { "xiaoxin",18 };
  FILE* pf = fopen("ilike.txt", "w");
  if (pf == NULL)
    printf("pf fopen \"ilike\" fail");
  else
  {
    fprintf(pf,"%s %d",s.name,s.age);
    fclose(pf);
    pf = NULL;
  }
  system("pause");
  return 0;
}

对应目录里ilike.txt文件的内容被修改为:

我们可以将其和printf做一个对比

发现唯一不同的就是在前面的参数,fprintf多了一个FILE*类型的指针变量,这个变量就是用来定位你所要写入的文件。


6、fscanf

同样的,我们首先将其和scanf做一个对比:

同样是多了一个指向文件的FILE*类型的指针。

  • 写入成功,函数返回参数列表中成功写入的项数
  • 如果读取发生错误或者读到了文件末尾,则设置正确的指示符feof,
  • 如果在成功读取任何数据之前,都会返回EOF


我们将之前的写入的结构体变量进行写入操作,并将读取到的数据赋值给另外一个同名结构体不同变量a,并打印。

#include<stdio.h>
#include<stdlib.h>
struct S
{
  char name[20];
  int age;
};
int main()
{
  S a = { "xiaoxin",18 };
  FILE* pf = fopen("ilike.txt", "r");
  if (pf == NULL)
    printf("pf fopen \"ilike\" fail");
  else
  {
    fscanf(pf,"%s %d",&a.name,&a.age);
    fclose(pf);
    pf = NULL;
  }
  printf("%s %d", a.name, a.age);
  system("pause");
  return 0;
}

结果如下:


c语言:文件处理操作-3

https://developer.aliyun.com/article/1515733

目录
相关文章
|
3月前
|
存储 C语言 C++
C语言文件处理
C语言文件处理
36 5
|
4月前
|
语音技术 C语言 Windows
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
|
5月前
|
C语言
C语言---函数--数组---创建一个整形数组,完成对数组的3种操作
C语言---函数--数组---创建一个整形数组,完成对数组的3种操作
|
6月前
|
存储 C语言
c语言:文件处理操作-3
c语言:文件处理操作
45 0
|
6月前
|
存储 编译器 C语言
c语言:文件处理操作-1
c语言:文件处理操作
29 0
|
6月前
|
C语言 C++
C语言进阶⑭(内存函数_以字节操作)momcpy+mommove+memcmp+memset
C语言进阶⑭(内存函数_以字节操作)momcpy+mommove+memcmp+memset
60 0
|
6月前
|
存储 C语言
C语言进阶第十课 --------文件的操作-2
C语言进阶第十课 --------文件的操作
|
6月前
|
存储 编译器 C语言
C语言进阶第十课 --------文件的操作-1
C语言进阶第十课 --------文件的操作
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
33 3
|
6天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
21 6