C++数据的输入输出秘境:IO流

1.C语言IO流

C语言中我们用到的最频繁的输入输出方式就是scanf ()printf()scanf():从标准输入设备(键盘)读取数据,并将值存放在变量中。printf():将指定的文字/字符串输出到标准输出设备(屏幕)

注意宽度输出和精度输出控制。C语言借助了相应的缓冲区来进行输入与输出。如下图所示:

对输入输出缓冲区的理解:

  1. 可以屏蔽掉低级I/O的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序
  2. 可以使用这部分的内容实现“行”读取的行为,对于计算机而言是没有“行”这个概念,有了这部分,就可以定义“行”的概念,然后解析缓冲区的内容,返回一个“行”

2.流的概念

“流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据(其单位可以是bitbytepacket)的抽象描述C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”

它的特性是:有序连续、具有方向性

为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能

3.C++IO流

C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios

3.1 C++标准IO流

C++标准库提供了4个全局流对象cincoutcerrclog,使用cout进行标准输出,即数据从内存流向控制台(显示器)。使用cin进行标准输入即数据通过键盘输入到程序中,同时C++标准库还提供了cerr用来进行标准错误的输出,以及clog进行日志的输出,从上图可以看出,coutcerrclogostream类的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同

在使用时候必须要包含文件并引入std标准命名空间

注意:

  1. cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据
  2. 输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state中对应位置位(置1),程序继续
  3. 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有空格。回车符也无法读入

操作

是否跳过空白符

读取内容

典型场景

cin >> ch;

下一个非空白字符

读取用户输入的非空白字符(如姓名首字母)

cin.get(ch);

下一个字符(包括空白符)

读取文件中的原始字符(如换行符)

cin.getline(buf, size);

读取一整行(直到换行符)

读取包含空格的句子

  1. cincout可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和输出全部重载了
  2. 对于自定义类型,如果要支持cincout的标准输入输出,需要对<<>>进行重载
  3. 在线OJ中的输入和输出:
  • 对于IO类型的算法,一般都需要循环输入:
  • 输出:严格按照题目的要求进行,多一个少一个空格都不行
  • 连续输入时,vs系列编译器下在输入ctrl + Z时结束

代码语言:javascript

AI代码解释

// 单个元素循环输入 while (cin >> a) { // ... } // 多个元素循环输入 while (c >> a >> b >> c) { // ... } // 整行接收 while (cin >> str) { // ... }
  1. istream类型对象转换为逻辑条件判断值

代码语言:javascript

AI代码解释

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

实际上我们看到使用while(cin>>i)去流中提取对象数据时,调用的是operator>>,返回值是istream类型的对象,那么这里可以做逻辑条件值,源自于istream的对象又调用了operator booloperator bool调用时如果接收流失败,或者有结束标志,则返回false

代码语言:javascript

AI代码解释

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 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; } // C++ IO流,使用面向对象+运算符重载的方式 // 能更好的兼容自定义类型,流插入和流提取 int main() { // 自动识别类型的本质--函数重载 // 内置类型可以直接使用--因为库里面ostream类型已经实现了 int i = 1; double j = 2.2; cout << i << endl; cout << j << endl; // 自定义类型则需要我们自己重载<< 和 >> Date d(2022, 4, 10); cout << d; while (d) { cin >> d; cout << d; } return 0; }
3.2 C++文件IO流

C++的文件输入 / 输出(File I/O)通过标准库中的流类实现,主要涉及以下三个类:

  • ifstreamInput File Stream):用于从文件读取数据(输入)
  • ofstreamOutput File Stream):用于向文件写入数据(输出)
  • fstreamFile Stream):支持读写操作,兼具ifstreamofstream的功能
3.2.1 基本使用步骤
  1. 包含头文件

代码语言:javascript

AI代码解释

#include <fstream> // 文件流操作 #include <string> // 字符串操作(可选)
  1. 打开文件 使用构造函数或open()方法打开文件,需指定文件名和打开模式

打开模式(可选组合):

  • ios::in:读模式(默认用于ifstream
  • ios::out:写模式(默认用于ofstream,会清空文件)
  • ios::app:追加模式(不清空文件,在末尾写入,ios::out | ios::app:追加写入文件)
  • ios::binary:二进制模式(用于非文本文件,ios::in | ios::binary:以二进制模式读取文件)
  • ios::trunc:截断模式(打开时清空文件,默认与ios::out一起使用,ios::out | ios::trunc

🔥值得注意的是:ios::std的内部类,必须加上

代码语言:javascript

AI代码解释

// 方式1:使用构造函数 ifstream fin("input.txt"); // 读文件(默认模式为 ios::in) ofstream fout("output.txt"); // 写文件(默认模式为 ios::out) ofstream fapp("append.txt", ios::out | ios::app); // 追加模式 //创建文件的时候默认调用ios::out | ios::trunc // 方式2:使用 open() 方法(可先创建对象,后打开文件) fstream file; file.open("data.txt", ios::in | ios::out); // 读写模式
  1. 检查文件是否成功打开

代码语言:javascript

AI代码解释

if (!fin.is_open()) { // 或直接用 if (!fin) cerr << "无法打开文件!" << endl; return 1; // 退出程序 }
  1. 读写文件

写入文件:使用<<运算符(类似cout) 读取文件:使用>>运算符(类似cin)或getline()逐行读取

示例:

代码语言:javascript

AI代码解释

// 写入文件 fout << "Hello, World!" << endl; // 写入字符串和换行符 fout << 42 << " " << 3.14 << endl; // 写入数值 // 读取文件(按空格分隔) int num; double d; fin >> num >> d; // 从文件读取整数和浮点数 // 逐行读取文件 string line; while (getline(fin, line)) { // 每次读取一行,直到文件结束 cout << "读取的行:" << line << endl; }
  1. 关闭文件

文件操作结束后,使用close()方法关闭文件

注意:对象析构时会自动关闭文件,但显式调用close()是良好习惯

代码语言:javascript

AI代码解释

fin.close(); // 关闭输入文件 fout.close(); // 关闭输出文件
3.2.2 文件操作示例
  1. 写入文件(覆盖模式)

代码语言:javascript

AI代码解释

#include <fstream> #include <iostream> using namespace std; int main() { ofstream fout("data.txt"); // 打开文件(默认覆盖模式) if (!fout) { cerr << "无法打开文件!" << endl; return 1; } fout << "姓名:张三" << endl; fout << "年龄:20" << endl; fout << "成绩:95.5" << endl; fout.close(); // 关闭文件 return 0; }
  1. 读取文件(逐行读取)

代码语言:javascript

AI代码解释

#include <fstream> #include <iostream> #include <string> using namespace std; int main() { ifstream fin("data.txt"); // 打开文件用于读取 if (!fin) { cerr << "无法打开文件!" << endl; return 1; } string line; while (getline(fin, line)) { // 逐行读取 cout << line << endl; } fin.close(); // 关闭文件 return 0; }
  1. 追加写入文件

代码语言:javascript

AI代码解释

#include <fstream> #include <iostream> using namespace std; int main() { // 以追加模式打开文件(ios::app) ofstream fout("data.txt", ios:: | ios::app); if (!fout) { cerr << "无法打开文件!" << endl; return 1; } fout << "附加信息:优秀学生" << endl; fout.close(); return 0; }
  1. 二进制文件读写

使用write()read()方法操作二进制数据,需指定数据地址和长度

代码语言:javascript

AI代码解释

#include <fstream> using namespace std; struct Student { char name[20]; int age; double score; }; int main() { // 写入二进制文件 Student s = {"李四", 21, 89.5}; ofstream fout("student.bin", ios::binary); fout.write(reinterpret_cast<const char*>(&s), sizeof(Student)); fout.close(); // 读取二进制文件 Student readStudent; ifstream fin("student.bin", ios::binary); fin.read(reinterpret_cast<char*>(&readStudent), sizeof(Student)); fin.close(); return 0; }

4.stringstream

C语言中,如果想要将一个整形变量的数据转化为字符串格式,如何去做?

  1. 使用itoa()函数
  2. 使用sprintf()函数

但是两个函数在转化时,都得需要先给出保存结果的空间,那空间要给多大呢,就不太好界定,而且转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃

代码语言:javascript

AI代码解释

int main() { int n = 123456789; char s1[32]; _itoa(n, s1, 10); char s2[32]; sprintf(s2, "%d", n); char s3[32]; sprintf(s3, "%f", n); return 0; }

C++中,可以使用stringstream类对象来避开此问题

在程序中如果想要使用stringstream,必须要包含头文件。在该头文件下,标准库三个类:istringstreamostringstreamstringstream,分别用来进行流的输入、输出和输入输出操作,本文主要介绍stringstream

stringstream主要可以用来:

  1. 将数值类型数据格式化为字符串

代码语言:javascript

AI代码解释

#include<sstream> int main() { int a = 12345678; string sa; // 将一个整形变量转化为字符串,存储到string类对象中 stringstream s; s << a; s >> sa; // clear() // 注意多次转换时,必须使用clear将上次转换状态清空掉 // stringstreams在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit // 因此下一次转换是必须调用clear()将状态重置为goodbit才可以转换 // 但是clear()不会将stringstreams底层字符串清空掉 // s.str(""); // 将stringstream底层管理string对象设置成"", // 否则多次转换时,会将结果全部累积在底层string对象中 s.str(""); s.clear(); // 清空s, 不清空会转化失败 double d = 12.34; s << d; s >> sa; string sValue; sValue = s.str(); // str()方法:返回stringsteam中管理的string类型 cout << sValue << endl; return 0; }
  1. 字符串拼接

代码语言:javascript

AI代码解释

int main() { stringstream sstream; // 将多个字符串放入 sstream 中 sstream << "first" << " " << "string,"; sstream << " second string"; cout << "strResult is: " << sstream.str() << endl; // 清空 sstream sstream.str(""); sstream << "third string"; cout << "After clear, strResult is: " << sstream.str() << endl; return 0; }
  1. 序列化和反序列化结构数据

代码语言:javascript

AI代码解释

struct ChatInfo { string _name; // 名字 int _id; // id Date _date; // 时间 string _msg; // 聊天信息 }; int main() { // 结构信息序列化为字符串 ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧" }; ostringstream oss; oss << winfo._name << " " << winfo._id << " " << winfo._date << " " << winfo._msg; string str = oss.str(); cout << str << endl << endl; // 我们通过网络这个字符串发送给对象,实际开发中,信息相对更复杂, // 一般会选用Json、xml等方式进行更好的支持 // 字符串解析成结构信息 ChatInfo rInfo; istringstream iss(str); iss >> rInfo._name >> rInfo._id >> rInfo._date >> rInfo._msg; cout << "-------------------------------------------------------" << endl; cout << "姓名:" << rInfo._name << "(" << rInfo._id << ") "; cout << rInfo._date << endl; cout << rInfo._name << ":>" << rInfo._msg << endl; cout << "-------------------------------------------------------" << endl; return 0; }

注意:4.stringstream实际是在其底层维护了一个string类型的对象用来保存结果 5. 多次数据类型转化时,一定要用clear()来清空,才能正确转化,但clear()不会将stringstream底层的string对象清空 6. 可以使用s. str("")方法将底层string对象设置为""空字符串 7. 可以使用s.str()将让stringstream返回其底层的string对象 8.stringstream使用string类对象代替字符数组,可以避免缓冲区溢出的危险,而且其会对参数类型进行推演,不需要格式化控制,也不会出现格式化失败的风险,因此使用更方便,更安全

www.dongchedi.com/article/7598662619591098905
www.dongchedi.com/article/7598661663487148606
www.dongchedi.com/article/7598661165073383960
www.dongchedi.com/article/7598661590610706968
www.dongchedi.com/article/7598659598723203609
www.dongchedi.com/article/7598660331644518974
www.dongchedi.com/article/7598659182870970942
www.dongchedi.com/article/7598659511842849304
www.dongchedi.com/article/7598658577318265369
www.dongchedi.com/article/7598660363760206398
www.dongchedi.com/article/7598659848598962750
www.dongchedi.com/article/7598658231610884632
www.dongchedi.com/article/7598655027276071449
www.dongchedi.com/article/7598656521844949566
www.dongchedi.com/article/7598656663327261246
www.dongchedi.com/article/7598657570517058110
www.dongchedi.com/article/7598656249982550590
www.dongchedi.com/article/7598655008087196222
www.dongchedi.com/article/7598654082278408728
www.dongchedi.com/article/7598654850569667096
www.dongchedi.com/article/7598653079990911513
www.dongchedi.com/article/7598653503171052094
www.dongchedi.com/article/7598653873355948569
www.dongchedi.com/article/7598651016690975257
www.dongchedi.com/article/7598653584766632510
www.dongchedi.com/article/7598652418918056473
www.dongchedi.com/article/7598651546129203737
www.dongchedi.com/article/7598650859257397785
www.dongchedi.com/article/7598650664986001982
www.dongchedi.com/article/7598649187739517464
www.dongchedi.com/article/7598650458629997080
www.dongchedi.com/article/7598649332920975934
www.dongchedi.com/article/7598650344322925081
www.dongchedi.com/article/7598649267225477657
www.dongchedi.com/article/7598650803637043774
www.dongchedi.com/article/7598647318044754456
www.dongchedi.com/article/7598647158111552025
www.dongchedi.com/article/7598646871380263486
www.dongchedi.com/article/7598647318044721688
www.dongchedi.com/article/7598645874076008985
www.dongchedi.com/article/7598647443848675902

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1208204.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】模拟实现map和set

1. 调整之前实现的红黑树的insert 1.1 整体框架的搭建 新建两个头文件&#xff0c;Mymap.h 和 Myset.h &#xff0c;一个源文件 test.cpp &#xff0c;然后把之前实现的红黑树拷贝一份过来。 为了和库里面的一些东西区分开&#xff0c;我们还是把所有自己实现的内容都放在自己…

Cursor功能优化指南:理解限制机制与合规使用方案

Cursor功能优化指南&#xff1a;理解限制机制与合规使用方案 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your trial re…

模型微调前准备:DeepSeek-R1作为基座模型的适配性分析

模型微调前准备&#xff1a;DeepSeek-R1作为基座模型的适配性分析 在开始微调一个大语言模型之前&#xff0c;很多人会直接跳到“怎么改参数”“怎么写LoRA配置”&#xff0c;却忽略了最关键的第一步&#xff1a;这个模型本身&#xff0c;真的适合你的任务吗&#xff1f;它是不…

如何清除重新来?fft npainting lama重置按钮使用方法

如何清除重新来&#xff1f;FFT NPainting Lama重置按钮使用方法 1. 为什么需要“清除”功能&#xff1f; 在图像修复过程中&#xff0c;你可能遇到这些情况&#xff1a; 标注区域画错了&#xff0c;想从头开始上传了错误的图片&#xff0c;想换一张重新操作修复效果不理想&…

智谱开源Glyph体验分享:长文本变图像处理新思路

智谱开源Glyph体验分享&#xff1a;长文本变图像处理新思路 你有没有试过让大模型读完一篇3000字的产品说明书&#xff0c;再让它精准生成一张带完整文案的电商海报&#xff1f;传统方法要么卡在上下文长度限制里&#xff0c;要么文字糊成一团、错字连篇——直到我遇见Glyph。…

YOLO11参数详解:train.py关键配置解读

YOLO11参数详解&#xff1a;train.py关键配置解读 YOLO11并不是当前主流开源社区中真实存在的官方模型版本。截至2024年&#xff0c;Ultralytics官方发布的最新稳定版为YOLOv8&#xff0c;后续迭代包括实验性分支YOLOv9、YOLOv10&#xff08;由其他研究团队提出&#xff09;&a…

Llama3-8B省钱部署方案:单卡3060实现高性能推理案例

Llama3-8B省钱部署方案&#xff1a;单卡3060实现高性能推理案例 1. 为什么说Llama3-8B是“性价比之王” 你是不是也遇到过这样的困扰&#xff1a;想跑一个真正好用的大模型&#xff0c;但显卡预算只有几千块&#xff1f;RTX 4090太贵&#xff0c;A100租不起&#xff0c;连309…

工业自动化中RS485和RS232通信协议选型指南:全面讲解

以下是对您提供的博文《工业自动化中RS485和RS232通信协议选型指南:全面技术解析》的 深度润色与结构化重写版本 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹,语言更贴近一线工程师口吻与教学博主风格; ✅ 打破模板化标题(如“引言”“总结”),全文以自然逻…

汽车电子中I2C中断TC3配置:系统学习与实践指南

以下是对您原始博文的 深度润色与工程化重构版本 。全文已彻底去除AI生成痕迹&#xff0c;采用真实嵌入式工程师口吻写作&#xff1a;有经验判断、有踩坑总结、有设计权衡、有代码细节、有调试直觉——不再是“教科书式罗列”&#xff0c;而是 一位在TC3项目中调通过EEPROM校…

如何突破Cursor功能限制:专业级解决方案全解析

如何突破Cursor功能限制&#xff1a;专业级解决方案全解析 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your trial requ…

实测对比:传统方法 vs fft npainting lama修复效果差异

实测对比&#xff1a;传统方法 vs FFT LaMa修复效果差异 图像修复这件事&#xff0c;说简单也简单——把照片里不想看到的东西抹掉&#xff1b;说难也难——抹得自然、不露痕迹、颜色协调、纹理连贯&#xff0c;才是真功夫。市面上的修复工具不少&#xff0c;从Photoshop的“内…

YOLO26低成本部署方案:中小企业也能轻松上手的实战指南

YOLO26低成本部署方案&#xff1a;中小企业也能轻松上手的实战指南 你是不是也遇到过这样的问题&#xff1a;想用最新的YOLO26做目标检测&#xff0c;但一打开官方文档就看到密密麻麻的依赖安装、CUDA版本匹配、环境冲突报错……最后只能放弃&#xff1f;更别说还要自己配训练…

NewBie-image-Exp0.1影视预研案例:角色概念图自动化生成实战

NewBie-image-Exp0.1影视预研案例&#xff1a;角色概念图自动化生成实战 1. 为什么影视预研需要角色概念图自动化&#xff1f; 在动画、游戏、短剧等视觉内容的前期开发中&#xff0c;角色概念图是决定项目调性与制作方向的关键一环。传统流程依赖原画师手绘草稿、反复修改、…

STM32低功耗应用中I2C读写EEPROM代码优化技巧

以下是对您提供的技术博文进行 深度润色与结构重构后的专业级技术文章 。全文已彻底去除AI生成痕迹&#xff0c;采用资深嵌入式工程师第一人称视角撰写&#xff0c;语言自然、逻辑严密、节奏紧凑&#xff0c;兼具教学性、实战性与思想深度。所有技术细节均严格基于STM32官方参…

Qwen3-0.6B API调用超时?网络配置优化实战指南

Qwen3-0.6B API调用超时&#xff1f;网络配置优化实战指南 1. 为什么Qwen3-0.6B会频繁超时&#xff1f; 你刚部署好Qwen3-0.6B镜像&#xff0c;打开Jupyter Notebook&#xff0c;复制粘贴那段LangChain调用代码&#xff0c;满怀期待地敲下chat_model.invoke("你是谁&…

ESP32教程:使用Arduino IDE实现蓝牙通信实战案例

以下是对您提供的博文内容进行 深度润色与结构重构后的专业级技术文章 。全文已彻底去除AI生成痕迹&#xff0c;强化了工程师视角的实战逻辑、教学节奏与经验沉淀&#xff1b;摒弃模板化标题与刻板段落&#xff0c;代之以自然递进、层层深入的技术叙事&#xff1b;所有代码、…

低成本高效率:自建AI手机助理详细教程

低成本高效率&#xff1a;自建AI手机助理详细教程 摘要&#xff1a;本文手把手教你用一台普通电脑一部安卓手机&#xff0c;零成本搭建专属AI手机助理。无需云服务、不上传截图、不依赖API收费&#xff0c;所有计算在本地完成。从环境配置到真机操控&#xff0c;从基础指令到复…

2026年AI图像生成入门必看:Qwen开源模型+ComfyUI镜像实战

2026年AI图像生成入门必看&#xff1a;Qwen开源模型ComfyUI镜像实战 你是不是也试过在本地跑图像生成模型&#xff0c;结果卡在环境配置、依赖冲突、CUDA版本不匹配上&#xff1f;折腾三天&#xff0c;连第一张图都没出来&#xff1f;别急——这次我们不讲原理、不堆参数、不聊…

CAPL脚本中定时器在CAN测试中的使用:全面讲解

以下是对您提供的博文内容进行深度润色与结构重构后的技术文章。我以一位深耕汽车电子测试多年、兼具Vector工具链实战经验与AUTOSAR/UDS协议栈理解的一线测试架构师视角&#xff0c;对原文进行了全面重写&#xff1a;✅彻底去除AI腔调与模板化表达&#xff08;如“本文将从………

Sambert开发避坑指南:常见报错及解决方案汇总

Sambert开发避坑指南&#xff1a;常见报错及解决方案汇总 1. 镜像核心能力与适用场景 Sambert 多情感中文语音合成-开箱即用版&#xff0c;专为快速落地语音合成需求设计。它不是需要反复编译、调试依赖的“半成品”&#xff0c;而是经过深度打磨的生产就绪型镜像——你拉取即…