【C++grammar】文件I/O流的基本用法

目录

  • 1、输入输出类介绍
    • 1.C/C++文件操作对比
    • 2.什么是流?
    • 3.C++ I/O流类层次
    • 4.带缓冲的输入输出
    • 5.gcc编译器cin.in_avail()
  • 2、向文件写入数据
    • 1.写文件小练习
    • 2.如何将信息同时输出到文件和屏幕?
  • 3、从文件读数据
    • 1.检测文件是否成功打开
    • 2.检测是否已到文件末尾
    • 3.读取文件小练习
    • 4.bad()函数能否用来判断文件流是否成功打开?

1、输入输出类介绍

1.C/C++文件操作对比

在这里插入图片描述

2.什么是流?

流是一个数据序列。
一个流是有两个端点的,一边是data source(数据源),一边是程序。
一个I / O流表示输入源或输出目的地。流可以表示许多不同种类的源和目标,包括磁盘文件,设备,其他程序和内存阵列。
流支持许多不同类型的数据,包括简单字节,原始数据类型,本地化字符和对象。一些流只是传递数据;其他则以有用的方式操纵和转换数据。
无论它们在内部如何工作,所有流都向使用它们的程序提供相同的简单模型:流是数据序列。
程序使用输入流从源中一次读取一项数据:
在这里插入图片描述

程序使用输出流将数据写入目的地,一次写入一项:
在这里插入图片描述
摘自:I / O流

3.C++ I/O流类层次

在这里插入图片描述

C++的流类主要有五类:

  1.  流基类(ios_base和ios)
    
  2.  标准输入输出流类(istream/ostream/iostream)
    
  3.  字符串流类(istringstream/ostringstream)
    
  4.  文件流类(ifstream/ofstream/fstream)
    
  5.  缓冲区类(streambuf/stringbuf/filebuf)
    

标准输入输出流对象 cin 和 cout 分别是类 istream 和 ostream 的实例

字符串流:将各种不同的数据格式化输出到一个字符串中,可以使用I/O操纵器控制格式;反之也可以从字符串中读入各种不同的数据。

4.带缓冲的输入输出

C++的I/O流是有内部缓冲区的。
c = cin.get(void)每次读取一个字符并把由Enter键生成的换行符留在输入队列中

#include<iostream>using namespace std;int main() {char c;int i = 0;do {c = cin.get();cout << ++i << " : " <<static_cast<int>(c) << endl;} while (c != 'q');return 0;}

在这里插入图片描述

本部分要展示的内容如下:
1、键盘输入一个字母后回车,实际进入缓冲区的是两个字符
2、使用cin输入信息后,有换行字符残留在缓冲区,从而导致return语句前的cin.get()不起作用

#include <iostream>int main()
{//拿到cin对象的缓冲区指针auto p = std::cin.rdbuf();//从键盘读入字符到缓冲区,保留所有字符在缓冲区auto x = std::cin.peek();std::cout << "x= " << x << std::endl;//显示缓冲区中的字符数量//由于每次读取返回值都不一样,所以先将初始值保存auto count = p->in_avail();std::cout << "There are " << count << "characters in the buffer." << std::endl;//把缓冲区的字符都取出来并显示for (int i = 0; i < count; i++){std::cout << i + 1 << ":" << std::cin.get() << std::endl;}std::cin.get();return 0;
}

5.gcc编译器cin.in_avail()

在使用gcc编译器的时候,存在这样一种意外的情况:

无论输入多少个字符, cin.in_avail()函数返回值永远是0。

这是由于GCC编译器中配套的libstdc++实现中的问题(可以看作是标准库gcc实现的一个bug,或者一个特性)。

解决办法是,在使用cin之前,插入下面一行代码

cin.sync_with_stdio(false);

简单解释原因:GCC的libstdc++默认是保证C++的cin与C的stdin同步的。

2、向文件写入数据

ofstrem可向文本文件中写数据.
输出数据的流程:
在这里插入图片描述
文件已存在,则直接清除内容。
Writing Data to a File – Auto type recognition (自动类型识别)

1.写文件小练习

本部分要展示的内容如下:
1、创建文件输出流
2、向文件写数据
output << “Lilei” << " " << 90.5 << endl;
output << “HanMeimei” << " " << 85 << endl;
3、关闭文件
4、用文本编辑器打开文件,对比代码语句检查结果

//std::c++latest
#include <fstream>
#include <iostream>
#include <filesystem>using std::ifstream;
using std::ofstream;
using std::cout;
using std::endl;
namespace fs = std::filesystem;int main()
{//第一步,关联文件fs::path p{ "scores.txt" };//第二步,创建一个流输出对象ofstream output{ p };double lileiScore{ 90.5 };int hanmeimeiScore{ 84 };output << "Lilei " << lileiScore << endl;output << "HanMeimei " << hanmeimeiScore << endl;output.close();cout << "size of " << p << " is " << fs::file_size(p) << endl;std::cin.get();return 0;
}

打开一个输出文件流的方法包括:
在这里插入图片描述

2.如何将信息同时输出到文件和屏幕?

在软件的调试技术中,很重要的一个技术是将软件运行过程中的一些信息写入到“日志文件”中。但是同时还要将信息显示到屏幕上,以方便程序员实时查看这些信息。
最简单的一种办法是这样的:

std::ofstream output("debug.log", ios::out);
output << __FILE__ << ":" << __LINE__ << "\t" << "Variable x = " << x;
cout << __FILE__ << ":" << __LINE__ << "\t" << "Variable x = " << x;

下面使用streambuf构造一个自己的类,来实现这个功能

#include <streambuf>
#include <iostream>
#include <fstream>//Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。
//tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。
class teebuf : public std::streambuf
{
public:// Construct a streambuf which tees output to both input// streambufs.teebuf(std::streambuf* sb1, std::streambuf* sb2): sb1(sb1), sb2(sb2){}
private:// This tee buffer has no buffer. So every character "overflows"// and can be put directly into the teed buffers.virtual int overflow(int c){if (c == EOF){return !EOF;}else{int const r1 = sb1->sputc(c);int const r2 = sb2->sputc(c);return r1 == EOF || r2 == EOF ? EOF : c;}}// Sync both teed buffers.virtual int sync(){int const r1 = sb1->pubsync();int const r2 = sb2->pubsync();return r1 == 0 && r2 == 0 ? 0 : -1;}
private:std::streambuf* sb1;std::streambuf* sb2;
};class teestream : public std::ostream
{
public:// Construct an ostream which tees output to the supplied// ostreams.teestream(std::ostream& o1, std::ostream& o2);
private:teebuf tbuf;
};teestream::teestream(std::ostream& o1, std::ostream& o2): std::ostream(&tbuf), tbuf(o1.rdbuf(), o2.rdbuf())
{
}int main()
{std::ofstream output("debug.log");//1、创建文件/屏幕输出流对象teeteestream tee(std::cout, output);auto x = 1.1;tee << __FILE__ << ":" << __LINE__ << "\t" << "Variable x = " << x;return 0;
}

效果:
在这里插入图片描述

3、从文件读数据

ifstrem可从文本文件中读数据,并检测文件是否成功打开。
在这里插入图片描述
了解数据格式
若想正确读出数据,必须确切了解数据的存储格式。
用流提取运算符从文件流中读数据,所读入的信息的长度与流提取运算符右侧的变量的类型有关。

1.检测文件是否成功打开

可能出现错误:

1、读文件时文件不存在
2、写文件时介质只读

检测文件是否正确打开的方法:

1、open()之后马上调用fail()函数
2、fail()返回true, 文件未打开

ofstream output("scores.txt");
if (output.fail())  {cout << R"(Can't open file "scores.txt"!)";}

2.检测是否已到文件末尾

若你不知道文件有多少行,还想把他们全读出来,用eof()函数检查是否是文件末尾
由于get函数返回值是int,所以需要强制类型转换再进行屏幕输出。

ifstream in("scores.txt");
while (in.eof() == false) {cout << static_cast<char>(in.get());
}

3.读取文件小练习

本部分要展示的内容如下:
1、创建文件输入流,打开文件score.txt
2、用>>从文件读取数据
3、使用fail()函数检测文件是否打开
4、将读文件语句放入循环中,使用eof()作为循环条件
5、关闭文件

//std::c++latest
#include <fstream>
#include <iostream>
#include <filesystem>
#include <string>
using std::ifstream;
using std::ofstream;
using std::cout;
using std::endl;
using std::string;
namespace fs = std::filesystem;int main()
{//第一步,关联文件fs::path p{ "scores.txt" };//第二步,创建一个流输入对象ifstream input{ p };//第三步使用fail判断流是否正常打开if (input.fail()){cout << "Can't open file " << p << endl;std::cin.get();return 0;}//第四步,定义一些变量去存这些数据string name{ "" };double score{ 0.0 };//读取文件中的姓名和分数//input >> name >> score;//cout << name << " " << score << endl;//input >> name >> score;//cout << name << " " << score << endl;while (input.eof() == false){cout << static_cast<char>(input.get());}std::cin.get();return 0;
}

在这里插入图片描述

4.bad()函数能否用来判断文件流是否成功打开?

在ifstream和ofstream类中,除了fail()函数之外,还有bad()函数。

那么我们能否用bad()函数取代fail()函数判断流是否成功打开?

不能,bad() 如果出现意外的问题,如文件受损或硬件故障,最后一次读取数据的时候发生了这样的问题,方法bad()将返回true.

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

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

相关文章

作业2 分支循环结构

书本第39页 习题2 1.输入2个整数num1和num2.计算并输出它们的和&#xff0c;差&#xff0c;积&#xff0c;商&#xff0c;余数。 //输入2个整数num1和num2.计算并输出它们的和&#xff0c;差&#xff0c;积&#xff0c;商&#xff0c;余数。//#include<stdio.h> int main…

十三、系统优化

系统整体框架图 程序运行进入纺织面料库存管理系统主页面 用户子系统功能演示&#xff1a; 1&#xff0c;点击用户登录进入用户登录页面&#xff0c;可以注册和找回密码 2&#xff0c;注册新用户&#xff0c;账号、密码、性别、手机号均有限制&#xff0c;用户注册需要按指定…

时间工具类[DateUtil]

View Code 1 package com.ly.util;2 3 import java.text.DateFormat;4 import java.text.ParseException;5 import java.text.SimpleDateFormat;6 import java.util.Calendar;7 import java.util.Date;8 9 /**10 * 11 * 功能描述12 * 13 * authorAdministrator14 * Date Jul 19…

leetcode 45. 跳跃游戏 II 思考分析

题目 给定一个非负整数数组&#xff0c;你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 示例: 输入: [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是 2。 从下标为 …

一、爬虫基本概念

一、爬虫根据使用场景分类 爬虫&#xff1a; 通过编写程序&#xff0c;模拟浏览器上网&#xff0c;让其去互联网上抓取数据的过程。 ① 通用爬虫&#xff1a;抓取系统重要的组成部分&#xff0c;抓取的是一整张页面的数据 ② 聚焦爬虫&#xff1a;建立在通用爬虫的基础之上&am…

经营你的iOS应用日志(二):异常日志

如果你去4S店修车&#xff0c;给小工说你的车哪天怎么样怎么样了&#xff0c;小工有可能会立即搬出一台电脑&#xff0c;插上行车电脑把日志打出来&#xff0c;然后告诉你你的车发生过什么故障。汽车尚且如此&#xff0c;何况移动互联网应用呢。 本文第一篇&#xff1a;经营你的…

Discuz 升级X3问题汇总整理

最近一段时间公司的社区垃圾帖数量陡然上涨&#xff0c;以至于社区首页的推荐版块满满都是垃圾帖的身影&#xff0c;为了进一步解决垃圾帖问题我们整整花了1天时间删垃圾贴&#xff0c;清除不良用户&#xff0c;删的手都酸了&#xff0c;可见垃圾帖的数量之多&#xff01;可耻的…

【C++grammar】格式化输出与I/O流函数

目录1、格式化输出1. setw manipulator(“设置域宽”控制符)2. setprecision manipulator(“设置浮点精度”控制符)3. setfill manipulator(“设置填充字符”控制符)4. Formatting Output in File Operation(在文件操作中格式化输入/输出)5.小练习2、用于输入/输出流的函数1. g…

三、实战---爬取百度指定词条所对应的结果页面(一个简单的页面采集器)

在第一篇博文中也提及到User-Agent&#xff0c;表示请求载体的身份&#xff0c;也就是说明通过什么浏览器进行访问服务器的&#xff0c;这一点很重要。 ① UA检测 门户网站服务器会检测请求载体的身份。如果检测到载体的身份表示为某一款浏览器的请求&#xff0c;则说明这是一…

硕士毕业后去国外读法学博士_法学硕士的完整形式是什么?

硕士毕业后去国外读法学博士法学硕士&#xff1a;豆科大法师(拉丁)/法学硕士 (LLM: Legum Magister (Latin)/ Master of Law) LLM is an abbreviation of Legum Magister. It is in term of Latin which states the masters degree of Law. In the majority, LLM is generally …

android:layout_weight属性的简单使用

效果&#xff1a; style.xml <style name"etStyle2"><item name"android:layout_width">match_parent</item><item name"android:layout_height">wrap_content</item><item name"android:background"…

一、环境配置安装

一、Anaconda Ⅰ下载 最新版的anaconda可能会需要各种各样的问题&#xff0c;python3.6版本比较稳定&#xff0c;建议使用。 老铁们可以通过&#xff0c;Anaconda以前版本所自带Python版本&#xff0c;查看Anaconda所带的python版本 我用的是这个&#xff0c;Anaconda3-5.2.0…

二、PyTorch加载数据

一、常用的两个函数 dir()函数可以理解为打开某个包&#xff0c;help()可以理解为返回如何使用某个具体的方法 例如&#xff1a;若一个A钱包里面有a&#xff0c;b&#xff0c;c&#xff0c;d四个小包&#xff0c;则可通过dir(A)&#xff0c;打开该A钱包&#xff0c;返回a&…

leetcode 1005. K 次取反后最大化的数组和 思考分析

题目 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09; 以这种方式修改数组后&#xff0c;返回数组可能…

三、TensorBoard

一、安装TensorBoard 管理员身份运行Anaconda Prompt&#xff0c;进入自己的环境环境 conda activate y_pytorch&#xff0c;pip install tensorboard 进行下载&#xff0c;也可以通过conda install tensorboard进行下载。其实通俗点&#xff0c;pip相当于菜市场&#xff0c;c…

详细讲解设计跳表的三个步骤(查找、插入、删除)

目录写在前面跳表概要查找步骤插入步骤删除步骤完整代码写在前面 关于跳表的一些知识可以参考这篇文章,最好是先看完这篇文章再看详细的思路->代码的复现步骤: Redis内部数据结构详解(6)——skiplist 关于跳表的插入、删除基本操作其实也就是链表的插入和删除&#xff0c;所…

php 类静态变量 和 常量消耗内存及时间对比

在对类执行100w次循环后&#xff0c; 常量最快&#xff0c;变量其次&#xff0c;静态变量消耗时间最高 其中&#xff1a; 常量消耗&#xff1a;101.1739毫秒 变量消耗&#xff1a;2039.7689毫秒 静态变量消耗&#xff1a;4084.8911毫秒 测试代码&#xff1a; class Timer_profi…

一个机器周期 计算机_计算机科学组织| 机器周期

一个机器周期 计算机机器周期 (Machine Cycle) The cycle during which a machine language instruction is executed by the processor of the computer system is known as the machine cycle. If a program contains 10 machine language instruction, 10 separate machine …

四、Transforms

transform是torchvision下的一个.py文件&#xff0c;这个python文件中定义了很多的类和方法&#xff0c;主要实现对图片进行一些变换操作 一、Transforms讲解 from torchvision import transforms#按着Ctrl&#xff0c;点击transforms进入到__init__.py文件中 from .transfo…

五、torchvision

一、下载CIFAR-10数据集 CIFAR-10数据集官网 通过阅读官网给的解释可以大概了解到&#xff0c;一共6w张图片&#xff0c;每张图片大小为3232&#xff0c;5w张训练图像&#xff0c;1w张测试图像&#xff0c;一共由十大类图像。 CIFAR10官网使用文档 torchvision.datasets.CIF…