C与C++的文件读写

 
一、c语言:
 
1、文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE。
//VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:
struct _iobuf {
	char* _ptr;
	int   _cnt;
	char* _base;
	int   _flag;
	int   _file;
	int   _charbuf;
	int   _bufsiz;
	char* _tmpfname;
};
typedef struct _iobuf FILE;

2、文件的打开和关闭

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	FILE* pf = fopen("test.txt","r");
	if (NULL == pf)
	{
		perror("fopen");
		return 0;
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

3、文件的顺序读写

①字符输出函数 fputc(适用所有输出流)
   文本行输出函数 fputs(适用所有输出流)

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}

	//写一行数据
	fputs("hello star\n", pf);
	fputs("hello galaxy\n", pf);

	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

②字符输入函数 fgetc(适用于所有输入流)
   文本行输入函数 fgets(适用于所有输入流)

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	int ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	//读一行数据
	char buf[20] = {0};
	fgets(buf, 20, pf);
	printf("%s", buf);
	fgets(buf, 20, pf);
	printf("%s", buf);

	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

③格式化输入函数 fscanf(适用于所有输入流)
   格式化输出函数 fprintf(适用于所有输出流)

struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { "zhangsan", 20, 95.5 };
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//格式化的写入文件
	fprintf(pf, "%s %d %f\n", s.name, s.age, s.score);
	//格式化的读取文件
	fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
	
	//打印看数据
	printf("%s %d %f\n", s.name, s.age, s.score);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

④任何一个C语言程序运行的时候,默认打开3个流:
stdin - 标准输入(键盘)类型:FILE*
stdout - 标准输出(屏幕)类型:FILE*
stderr - 标准错误(屏幕)类型:FILE*
而进行文件操作时,要先手动打开文件。

struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { 0 };
	fscanf(stdin, "%s %d %f", s.name, &(s.age), &(s.score));
	fprintf(stdout, "%s %d %f\n", s.name, s.age, s.score);

	return 0;
}

⑤二进制输入 fread 文件
    二进制输出 fwrite 文件

struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { 0};
	FILE* pf = fopen("test.txt", "rb");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//二进制输入
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s %d %f\n", s.name, s.age, s.score);

	//二进制输出
	fwrite(&s, sizeof(struct S), 1, pf);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

⑥sscanf:从一个字符串中,还原一个格式化的数据
    sprintf:把格式化的数据,存放在(转换成)一个字符串

struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = {"zhangsan", 20, 98.5};
	char buf[100] = { 0 };
	sprintf(buf, "%s %d %f", s.name, s.age, s.score);
	printf("%s\n", buf);//按照字符串打印的

	struct S tmp = { 0 };
	sscanf(buf, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score));
	printf("%s %d %f\n", tmp.name, tmp.age, tmp.score);//打印结构体数据

	return 0;
}

4、文件的随机读写
fseek:根据文件指针的位置和偏移量来定位文件指针
ftell:返回文件指针相对于起始位置的偏移量
rewind:让文件指针的位置回到文件的起始位置

int main()
{
	FILE*pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);//a
		ch = fgetc(pf);
		printf("%c\n", ch);//b
		ch = fgetc(pf);
		printf("%c\n", ch);//c


		//fseek(pf, -2, SEEK_CUR);//从当前位置读取b
		fseek(pf, 1, SEEK_SET);//从起始位置读取b
		ch = fgetc(pf);
		printf("%c\n", ch);//b
		printf("%d\n", ftell(pf));
		rewind(pf);
		ch = fgetc(pf);
		printf("%c\n", ch);//a
	}

	return 0;
}

5、文件读取结束的判定
首先文件读取结束了,结束后想知道读取结束的原因:
feof-返回真,就说明是文件正常读取到了结束标志而结束的。
ferror-返回真,就说明是文件在读取过程中出错了,而结束。

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	int c; // 注意:int,非char,要求处理EOF
	FILE* fp = fopen("test.txt", "r");
	if (!fp) {
		perror("File opening failed");
		return EXIT_FAILURE;
	}
	//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
	while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
	{
		putchar(c);
	}

	//判断是什么原因结束的
	if (ferror(fp))
		puts("I/O error when reading");
	else if (feof(fp))
		puts("End of file reached successfully");
	fclose(fp);
}

二、C++:

1、C++的io流

af19a4cf83aa4bc5934f3819ae511682.png

①运算符重载(operator<<和operator>>)
②自动识别类型(函数重载)
③面向对象可以更好支持自定义类型更形象(cout << x)

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<string>

using namespace std;

//istream& operator>> (int& val);
//explicit operator bool() const;

int main()
{
	string str;
	while (cin >> str) // operator>>(cin, str).operator bool()
	{
		cout << str << endl;
	}

	return 0;
}

2、C++文件的io流

①C语言与C++的二进制/文本读写

class Date
{
	friend ostream& operator << (ostream& out, const Date& d);
	friend istream& operator >> (istream& in, Date& d);
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	operator string()
	{
		string str;
		str += to_string(_year);
		str += ' ';
		str += to_string(_month);
		str += ' ';
		str += to_string(_day);
		return str;
	}

	operator bool()
	{
		// 这里是随意写的,假设输入_year为0,则结束
		if (_year == 0)
			return false;
		else
			return true;
	}
private:
	int _year;
	int _month;
	int _day;
};

istream& operator >> (istream& in, Date& d)
{
	in >> d._year >> d._month >> d._day;
	return in;
}

ostream& operator << (ostream& out, const Date& d)
{
	out << d._year << " " << d._month << " " << d._day;
	return out;
}

#include<fstream>

int main()
{
	Date d(2023, 10, 14);
	//C语言
	FILE* fin = fopen("file.txt", "w");
	// 二进制的方式写入
	fwrite(&d, sizeof(Date), 1, fin);
	fclose(fin);
	//文本的方式写入:调用operator string
	string str = d;
	fputs(str.c_str(), fin);

	//C++
	ofstream ofs("file.txt", ios_base::out | ios_base::binary);//二进制覆盖写入

	ofstream ofs("file.txt");
	// 二进制的方式写入
	ofs.write((const char*)&d, sizeof(d));

	// 文本的方式写入:ofstream是ostream的派生类,故ofstream也可调用operator<<
	ofs << d;

	return 0;
}

②C语言的sprintf和sscanf与C++的ostringstream和istringstream

#include<sstream>

int main()
{
	//C语言:sprintf与sscanf
	int x;
	cin >> x;
	char buff[128];
	sprintf(buff, "int:%d", x);

	//C++:ostringstream与istringstream
	// 简单序列化和反序列化
	Date d(2023, 10, 16);
	ostringstream oss;
	oss << d;
	string str = oss.str();
	cout << str << endl;//ostringstream是ostream的派生类,故ostringstream也可调用operator<<

	string str("2023 10 16");
	istringstream iss(str);
	Date d;
	iss >> d;//istringstream是istream的派生类,故istringstream也可调用operator<<

	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值