一、C语言的IO
1.键盘与显示屏
//键盘与显示屏的交互
int main()
{
//从键盘读取格式化字符串。
int i = 0;
scanf("%d", &i);
//在显示屏上打印获取到的信息。
printf("%d", i);
return 0;
}
2. 文件与内存
int main()
{
FILE* fptr = fopen("test.txt", "w+");
//w只写、w+可读可写。
//向文件里输入格式化字符串
fprintf(fptr, "%d hello", 123);
//调整文件指针的位置为开头
rewind(fptr);
//从文件里面读取字符串与数字。
char arr[15] = { 0 };
int n = 0;
//只能以某种形式对字符串进行解读
fscanf(fptr, "%d%s", &n,arr);
printf("%s %d", arr, n);
fclose(fptr);//关闭文件并刷新缓存区。
return 0;
}
3.字符串与内存
//字符串的输入输出,对字符串按指定方式进行解读。
int main()
{
//从内存向字符串输出可控制的格式化字符串
char str[100];
sprintf(str, "hello %d", 11);//这里的11可变换为变量。
cout << "输出的字符串为:" << str << endl;
//从字符串向变量中读入可控制的格式化字符串
int i = 0;
char buf[256];
sscanf(str, "%s %d",buf,&i);
cout<<"输入的字符为:" << i << " " << buf << endl;
return 0;
}
-
总结:
说明:这是基于内存的理解,方便理解printf即从内存往外输出,scanf即从外面向内存读写。
补充:程序在运行时默认打开三个流——stdin,stdout,stderror。
至于更多
C语言的文件操作
内容详见【进阶C语言】文件操作
二、C++IO
其中<iostream>是我们经常包的头文件,现在看来竟然还是一个菱形虚拟继承,不愧是实现库的大佬,没有困难创造困难迎着困难上,不过也为我们提供一点的便利。
1.iostream
1.1基本使用
先来看最简便的一段C++代码:
int main()
{
int x;
cin >> x;//从键盘对x进行输入数据
cout << "hello world" << endl;//向显示器上打印数据
return 0;
}
不知各位刚学这一段代码的时候,是什么感觉,我是感觉看起来比较便捷形象易懂
,只是最近再看其实就是一大堆的运算符重载形成的集合
,而且当我们想要用char*打印地址时,它其实给我们呈现的是一段字符串,而不是地址
, 不过用起来是真香。
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)
{}
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;
}
int main()
{
Date d1;
cin >> d1;//其原理就是调用自定义的运算符重载函数。
cout << d1 << endl;//同理。
return 0;
}
稍微总结一下:
说明:
- 实用小知识
同时回想在进行刷题时,如果面临读入一整行的字符串数据,有什么方法吗?
- gets
char* gets(char* str);
- fgets
char * fgets ( char * str, int num, FILE * stream );
基本使用:
int main()
{
char buf[256];
//从标准输入流(键盘)里读取最大不超过buf大小的一行数量,到buf数组中
fgets(buf, sizeof(buf), stdin);
cout << buf << endl;
return 0;
}
int main()
{
char buf[256];
//从标准输入流(键盘)里读取一行数量,到buf数组中
scanf("%[^n]", buf);//直到遇到换行才停止。
cout << buf << endl;
return 0;
}
#include<iostream>
#include<string>
int main()
{
string buf;
//从标准输入流(键盘)里读取一行数量,到buf中
getline(cin, buf);
cout << buf << endl;
return 0;
}
1.2operator bool
除此之外,我们可能对多组输入的cin,会产生疑惑 , 比如如下一段代码:
int main()
{
int x;
while (cin >> x)
{
cout << x << endl;
}
return 0;
}
istream& operator>> (int& val);
//返回的是cin,也就是类型为istream的对象,
//而while()里面进行判断的是bool值,两者能进行转换吗?答案是肯定能的,
//那是如何进行转换的呢?
就比如:
class A
{
public:
private:
int _a = 0;
};
int main()
{
A a;
if(a)//此处会报错:表达式必须包含 bool 类型(或可转换为 bool)
{}
return 0;
}
class A
{
public:
operator bool()
{
return _a == 0 ? false : true;
}
private:
int _a = 0;
};
int main()
{
A a;
if(a){}
//这也间接说明,iostream是实现了operator bool的。
return 0;
}
说明:这里的实现的运算符重载没有返回值是有点奇怪的,这里当做特殊情况对待即可,不必深究。
2. fstream
- 对于fostream的对象默认打开了out,对于fistream的对象默认打开了in。
- 操作可通过 | 进行结合起来。
- truncate——对文件之前的内容进行覆盖。
- 对于有些对象比如fstream,可以支持输入也可以支持输出。
2.1二进制的文件读写
struct PeopleInfor
{
PeopleInfor()
{}
PeopleInfor(const char* id,const char* name,int age)
//:_id(id)
{
strcpy(_id, id);
strcpy(_name, name);
_age = age;
}
char _id[256];//家庭住址
char _name[256] = {0};//名字
int _age = 0;//年龄
};
struct ManagePeoInf
{
//初始化
ManagePeoInf(const char* file)
:_FileName(file)
{}
//向文件以二进制写入个人信息
void WriteBianry(const PeopleInfor& pe)
{
ofstream of(_FileName, ios_base::out | ios_base::binary);
//这里的out默认已经有了,可以不写。
of.write((char*)&pe, sizeof(pe));
}
void ReadBinary(PeopleInfor& pe)
{
ifstream in(_FileName, ios_base::in | ios_base::binary);
//这里的in默认已经有了,可以不写。
in.read((char*)&pe, sizeof(pe));
}
//向文件以二进制读取个人信息
string _FileName;
};
void BinaryWrite()
{
PeopleInfor pe1 = { "河南省","舜华",19 };
ManagePeoInf m1("text.txt");
//向文件中输出字符串x
m1.WriteBianry(pe1);
}
void BinaryRead()
{
PeopleInfor pe2;
ManagePeoInf m2("text.txt");
m2.ReadBinary(pe2);
cout << pe2._id << " " << pe2._name << " " << pe2._age << endl;
}
int main()
{
//向文件里以二进制的形式写入数据
BinaryWrite();
//从文件中以二进制的形式读取数据
BinaryRead();
return 0;
}
说明:这里的_id与_name并没有采用string的形式进行使用,而是char类型的数组进行的使用,其原因在于拷贝的是对象的内存,而string里面存的是指向字符串的地址,string释放时,读取在恢复时,其实是一段野指针,即使访问成功了也是幸运。
2.2字符串的文件读写
struct PeopleInfor
{
PeopleInfor()
{}
PeopleInfor(const char* id, const char* name, int age)
:_id(id)
{
//strcpy(_id, id);
strcpy(_name, name);
_age = age;
}
string _id;//家庭住址
char _name[256] = { 0 };//名字
int _age = 0;//年龄
};
struct ManagePeoInf
{
//初始化
ManagePeoInf(const char* file)
:_FileName(file)
{}
//向文件以二进制写入个人信息
void WriteText(const PeopleInfor& pe)
{
ofstream of(_FileName, ios_base::binary);
of << pe._id << " " << pe._name << " " << pe._age;
//这里的id是调用了string的流插入。
}
void ReadText(PeopleInfor& pe)
{
ifstream in(_FileName, ios_base::binary);
in >> pe._id >> pe._name >> pe._age;
//这里的_id是调用了string的流提取。
//读取自动识别空格与换行与分割符。
}
//向文件以二进制读取个人信息
string _FileName;
};
void WriteText()
{
PeopleInfor pe1 = { "河南省","舜华",19 };
ManagePeoInf m1("text.txt");
m1.WriteText(pe1);
}
void ReadText()
{
PeopleInfor p2;
ManagePeoInf m2("text.txt");
m2.ReadText(p2);
cout << p2._id << " " << p2._name << " " << p2._age << endl;
}
int main()
{
WriteText();
ReadText();
return 0;
}
3. sstream
3.1序列化与反序列化
- 此处说明:这里存在序列化与反序列化,因为在存储的形式中,要么以二进制的形式进行存储(人看不懂),要么以字符串的形式进行存储(序列化),总之在计算机用于计算的类型比如int,float,double等形式,在文件中不复存在,因此计算机要想用存储的数据进行计算,就需要将字符串转换为相应的格式再参与计算(反序列化)。
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
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)
{}
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;
}
int main()
{
string str;
Date d = { 2023,10,21 };
ostringstream os;
os << d;
str = os.str();
cout<<"字符串:" << str << endl;
//再将字符串转换为日期类
Date d1;
istringstream is(str);
is >> d1;
cout<<"日期类:" << d1 << endl;
return 0;
}
这里附上一道序列化与反序列化的题:二叉树的序列化与反序列化
3.2拼接字符串
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main()
{
ostringstream os;
os << "hello";//当然也可是一些变量,比如int
os << " world";//同理
cout << os.str() << endl;
return 0;
}
说明:
3.3将数据类型转换为字符串
int main()
{
int a = 12345678;
string sa;
// 将一个整形变量转化为字符串,存储到string类对象中
stringstream s;
s << a;
s >> sa;
s.str("");//将s维护的字符串置为空
s.clear();
// 说明:
// stringstreams在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit
// 因此下一次转换是必须调用clear()将状态重置为goodbit才可以转换
double d = 12.34;
s << d;
s >> sa;
string sValue;
sValue = s.str();
cout << sValue << endl;
return 0;
}
总结
原文地址:https://blog.csdn.net/Shun_Hua/article/details/133943497
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_22498.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!