C/C++语言基础--C++IO流、输入输出流、文件流、字符串流、重定向流等详解

devtools/2024/10/9 8:34:50/

本专栏目的

  • 更新C/C++的基础语法,包括C++的一些新特性

前言

  • 流思想,我认为在计算机中是一个很重要的思想,因为计算机、编程无非就是获取数据,然后对数据进行操作;
  • C++给主要给我们提供了3种流,输入输出流、文件流、字符串流,这篇就是小编的学习笔记,希望大家能够批评指正。

文章目录

    • IO流
    • 标准输入输出流
      • 类和流对象
      • 标准输入流
        • >>读取
        • cin.get()
        • cin.getine()
        • cin.ignore
      • 标准输出流
    • 文件流
      • 简介
      • 使用
        • 打开文件
        • 读取文件
          • 使用>>读取
          • 使用read()读取
          • 使用std::getline读取
        • 写入文件
          • 使用<<写入
          • 使用write写入
      • 打开模式
      • 文件位置指针
      • 文件操作的一些函数
    • 字符串流
      • 打开字符串流
      • 从string反格式化
    • 重定向流
      • 代码实重定向
        • C语言方式
        • C++方式

IO流

咱已经学过了 C 语言,所以都知道,C语言有有一整套完成数据读写(I/O)的解决方案:

  • 使用 scanf()、gets() 等函数从键盘读取数据,使用 printf()、puts() 等函数向屏幕上输出数据;
  • 使用 fscanf()、fgets() 等函数读取文件中的数据,使用 fprintf()、fputs() 等函数向文件中写入数据。
  • 使用sscanf() 读取格式化的字符串中的数据,使用sprintf()把格式化的数据写入到字符串

要知道,C 语言的这套 I/O 解决方案也适用于 C++ 程序,但 C++ 自己独立开发了一套全新的 I/O 解决方案,其中就包含大家一直使用的 cin 和 cout,但是要注意,cin、cout是类,printf、scanf是函数调用。

C++标准流,提供了一下三个方面的内容:

  1. 系统指定的标准设备的输入和输出。即从键盘输入数据,输出到显示器屏幕,简称标准I/O。
  2. 外存磁盘文件为对象进行输入和输出,简称文件I/O。
  3. 内存中指定的空间进行输入和输出,,简称串I/O。

流的概念:数据传输,输入、输出像水一样,故将这个过程定义为流。

标准输入输出流

类和流对象

重点关注前两个即可。

流类预定义流对象描述
istreamcin(常用)标准输入流
ostreamcout(常用)标准输出流
ostreamcerr标准错误流(不缓冲数据,直接显示)
ostreamclog标准日志流(缓冲数据)

标准库定义了 4 个 IO 对象。

  • 处理输入时使用命名为cin的 istream 类型对象,称为标准输入。

  • 处理输出时使用命名为cout的 ostream 类型对象,称为标准输出。

  • 标准库还定义了另外两个 ostream 对象,分别命名为 cerr 和 clog,cerr 对象又叫作标准错误,通常用来输出警告和错误信息给程序的使用者。

  • 而 clog 对象用于产生程序执行的一般信息。

标准输入流

cin本身是会略过所有空格、回车、tab的,然后开始读入,遇到空格、回车、tabl停止读入,光标会停留在这些字符之前,意思就是下一次读入也会从空格后开始读取。

>>读取

C++给我们提供了方便的输入方法,直接使用>>即可,但是遇到空格会被截断

cin.get()

读取一个字符,也可以连续读取

char c;
char buf[20],buf1[20];
//读取一个字符
c = cin.get();	//<==> cin.get(c);
//读取字符串
cin.get(buf, 20);
//读取字符串,遇到指定的字符终止读取
cin.get(buf1, 20, '#');
cout << c << " " << buf<<" "<< buf1;
cin.getine()

读取一行

char buf[20];
cin.getline(buf, 20);
cin.getline(buf, 20, '#');
cin.ignore

忽略

std::string str;
//忽略所有\n
while (cin.peek() == '\n')
{cin.ignore(1);
}	
std::getline(cin, str,'#');
// 输出
cout << str << endl;
/*
输入:
\n
\n
123#
输出:
123
*/

标准输出流

C++格式化输出3种使用方式:

  1. 通过流成员函数进行输入输出格式控制
// 设置输出内容宽度
cout.width(30);
// 设置填充内容
cout.fill('*');
// 设置对其方式
cout.setf(ios::left);
// 用科学计数法展示
cout.setf(ios::scientific);// 八进制格式输出
cout << oct << 0xA << endl;
// 十进制格式输出
cout << dec << OxA << endl;
// 大写形势展示十六进制中字母
cout.self(ios::uppercase);
// 十六进制格式显示
cout << hex << OxA << endl;// 取消科学计数法使用
cout.unself(ios::scientific);
// 设置浮点数显示前N位
cout.precision(3);
cout << 3.1415 << endl;  // 输出 3.142,最后一位四舍五入// ………………………… 还有很多,现用现查即可。

这里有些设置会全局生效,所以有还需要关闭,时候很不方便。

  1. 通过#include 提供的控制符,进行输入输出格式控制,如下:
控制符作用
setbase(n)设置整数为n进制
setfill(n)设置字符填充
setprecision(n)设置浮点数有效位
setw()设置字段宽度
setiosflags(ios::fixed)设置浮点数固定小数位输出
setiosflags(ios::scientific)浮点数以科学计数法表示
setiosflags(ios::left)左对齐
setiosflags(ios::right)右对齐

当然还有很多,先用现查即可。

案例

cout << setw(30) << setfill('*') << setiosflags(ios::left) << 1.2222233 << endl;// 输出: 1.22222***********************

而且这个具有临时性,不会影响后面输出。

  1. 运用C语言的API

可以用C语言的scanf进行格式化输出。

文件流

简介

文件:字节流,即如何从文件读取流和向文件写入流。

C++ 给操作文件提供了一个标准库 fstream,它定义了三个新的数据类型:

在这里插入图片描述
在这里插入图片描述

使用

其实任何语言文件操作都差不多,打开、关闭、读取与写入(字节、一行、二进制等)

打开文件
fstream file("maye.txt");

可以通过构造函数指定文件名,并打开;默认就是以可读可写的方式打开的,但是文件不存在会打开失败!

file.open("maye.txt", ios::in | ios::out | ios::trunc);

也可以使用open函数打开文件,使用open必须传递打开模式ios::in为可读,ios::out为可写,ios::trunc为文件不存在时创建,存在则清空所有内容(ios::trunc必须与ios::out搭配使用)。

if (!file)	//if (!file.is_open())	//两种判断方式都可以
{cout << "open error:" << strerror(file.rdstate());
}
else
{cout << "open successed";
}file.close();

注意: 使用完毕之后并不需要手动关闭文件,但是如果想提前关闭可以使用close()函数。

读取文件

文件打开之后,就可以进行读写了,注意打开模式,ios::in为可读,ios::out为可写。

创建stu.txt文件,并写入以下内容,并测试读取!

123 wy 男
456 lt 男
789 wgs 男
110 lyp 男

如果乱码,则将文件存为ansi(win11中记事本)

使用>>读取
std::string buf;
while (!file.eof())  // 判断是否读到了文件最后
{file >> buf;		//读成功返回truecout << buf << " ";if (file.peek() == '\n'){cout << endl;}
}

注意,使用>>读取,遇到空格会截断,所以需要循环的去读取,而且还需要自己判断是不是\n。

使用read()读取
char buf[200] ={0};
file.read(buf, 200);
cout << buf;

注意:我们并不知道文件有多大,所以并不能很好的指定读取的大小,从而一次性把文件读取完成。可以先获取文件大小然后再读取

file.seekp(0,ios::end);
int64_t len = file.tellp();   // 获取文件大小
file.seekp(0,ios::beg);char* buf = new char[len + 1] {0};       //及其重要
file.read(buf, len);
cout << buf;delete[] buf;
使用std::getline读取

如果想直接读取到std::string里面,则需要使用std::getline。

std::string buf;
std::getline(file, buf);
cout << buf;

这样读取只能读取一行,如果想要读取多行,则需要使用循环。

std::string buf;
while (!file.eof())
{std::getline(file, buf);cout << buf << endl;
}
写入文件
  • 如果想要追加写入文件,请添加打开模式ios::app

  • 如果想要二进制读写,请添加打开模式ios::binary

使用<<写入
使用write写入

打开模式

模式标记适用对象作用
ios::inifstream fstream打开文件用于读取数据。如果文件不存在,则打开出错。
ios::outofstream fstream打开文件用于写入数据。如果文件不存在,则新建该文件;如果文件原来就存在,则打开时清除原来的内容。
ios::appofstream fstream打开文件,用于在其尾部添加数据。如果文件不存在,则新建该文件。
ios::ateifstream打开一个已有的文件,并将文件读指针指向文件末尾(读写指 的概念后面解释)。如果文件不存在,则打开出错。
ios:: truncofstream打开文件时会清空内部存储的所有数据,单独使用时与 ios::out 相同。
ios::binaryifstream ofstream fstream以二进制方式打开文件。若不指定此模式,则以文本模式打开。
ios::in | ios::outfstream打开已存在的文件,既可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。
ios::in | ios::outofstream打开已存在的文件,可以向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。
ios::in | ios::out | ios::truncfstream打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件。

文件位置指针

istream 和 ostream 都提供了用于重新定位文件位置指针的成员函数。这些成员函数包括关于 istream 的 seekg(“seek get”)和关于 ostream 的 seekp(“seek put”)。

seekg 和 seekp 的参数通常是一个长整型。第二个参数可以用于指定查找方向。
查找方向:

  • ios::beg 默认的,从流的开头开始定位
  • ios::cur 从流的当前位置开始定位
  • ios::end 从流的末尾开始定位

案例

#include <iostream>
#include <fstream>
using namespace std;struct Gril {int age;string name;
};int main()
{Girl mygirl[3] = {18, "w", 19, "y", 10, "l"};// 打开文件fstream file("./test.txt", ios::in | ios::out | ios::binary | ios::trunc);if(!file) {cerr << "file open failed" << endl;}// 写入文件file.write((char*)mygirl, sizeof(mygirl));// 文件指针移动到开头file.seekg(ios::beg);  //读Girl temp[3];file.read((char*)temp, sizeof(temp));for(auto& it : temp) {cout << it.age << " " << it.name << endl;}file.close();return 0;
}

文件操作的一些函数

这张图是当时我学《C++ prime》这本书的时候在博客找的,我感觉还是很清晰的讲解了文件操作相关的函数

在这里插入图片描述

字符串流

在C语言中,我们使用sscanf和sprintf来对字符串进行格式化,格式控制非常不方便,在C++中有了更方便的操作。

使用头文件添加对字符串流的支持。

我感觉,这个最大的作用就是,格式化与反格式化

打开字符串流

stringstream stream(ios::out | ios::in);

如果支持格式化和反格式化,则需要指定打开模式ios:inios::out

stream << 1 <<" " << "234"s <<" "<< 5.20;

使用stream对象,把需要的数据全部格式化,这里每个数据之间用空格隔开,方便等会反格式化。(反格式化以空格为分割字符)

cout << stream.str()<<endl;

当然在反格式化之前,我们使用stream.str()查看已经格式化的数据

int a;
float b;
string s;

首先我们定义三个对象,来接受从stream中反格式化的数据。

stream >> a >> s >> b;
cout << a <<" " << s << " " << b << endl;  // 反格式化的意思就是,输出的时候按照不同的数据类型自动识别,不受输入影响

从string反格式化

stringstream对象还可以绑定一个string对象,直接对string进行操作。

string buf = "1 234 5.20";
stringstream stream(buf);

先准备一个string对象,然后构造stringstream,默认以可读可写方式打开。

int a;
float b;
string s;
stream >> a >> s >> b;
cout << a << " " << s << " " << b << endl;   // 反格式化

如果在反格式化之后需要写入内容,是写入不了的,需要调用stream.clear()对格式进行清除,代码如下:

// 清除操作
stream.clear();
stream << "@@" << " ##";
cout << stream.str();

如果这个时候像着追加继续写,则只需要在构造stringstream对象的时候,添加上ios::app以追加的模式写入即可,如下:

stringstream stream(buf,ios::app | ios::in | ios::out);   

重定向流

重定向流:我们一般输入输出一般都是在屏幕、键盘上操作,键盘输入,屏幕输出,重定向流就是可以指定输出位置,比如说输出到文件,不输出到屏幕

代码实重定向

C语言方式

C语言方式可以通过freopen函数实现:

freopen("in.txt","r",stdin);	//stdin重定向到in.txt
//...
freopen("CON","r",stdin);		//恢复重定向freopen("out.txt","w",stdout);freopen("CON","w",stdout);
C++方式

C语言方式可以通过cin.rdbuf函数实现:

fstream fin("in.txt");
streambuf* oldbuf = cin.rdbuf();
cin.rdbuf(fin.rdbuf());
//...
cin.rdbuf(oldbuf);

http://www.ppmy.cn/devtools/123288.html

相关文章

遗传算法与深度学习实战(16)——神经网络超参数优化

遗传算法与深度学习实战&#xff08;16&#xff09;——神经网络超参数优化 0. 前言1. 深度学习基础1.1 传统机器学习1.2 深度学习 2. 神经网络超参数调整2.1 超参数调整策略2.2 超参数调整对神经网络影响 3. 超参数调整规则小结系列链接 0. 前言 我们已经学习了多种形式的进化…

聚观早报 | 苹果重磅更新;OpenAI推出ChatGPT Canvas

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 10月1日消息 苹果重磅更新 OpenAI推出ChatGPT Canvas Meta发布Movie Gen iQOO 13影像规格曝光 华为HarmonyOS N…

如何使用 Puppeteer 和 Browserless 运行自动化测试?

Puppeteer&#xff1a;什么是 Puppeteer 及其功能 Puppeteer 是一个 Node.js 库。使用 Puppeteer&#xff0c;您可以在所有基于 Chromium 的浏览器上测试您的网站&#xff0c;包括 Chrome、Microsoft Edge Chrome 和 Chromium。此外&#xff0c;Puppeteer 可用于网页抓取、自动…

c++primer第十三章 类继承

本章内容&#xff1a;单个类就可以提供用于管理对话框的全部资源。通常&#xff0c;类库是以源代码的方式提供的&#xff0c;这意味着可以对其进行修改&#xff0c;以满足需求。但是&#xff0c;C-提供了比修改代码更好的方法来扩展和修改类。这种方法叫作类继承(class inheria…

奇异值分解SVD

文章目录 奇异值是什么&#xff1f;1 奇异值的定义2 奇异值的性质3 特征值与奇异值的关系4 奇异值的重要性 奇异值分解 奇异值是什么&#xff1f; 1 奇异值的定义 对于任意一个 m n m \times n mn 的矩阵 A A A&#xff0c;存在三个矩阵 U U U&#xff0c; V V V和 Σ \Si…

供应链管理师案例分析题4

1.上个世纪80 年代初&#xff0c;我国某印刷企业引入了一套计算机排版系统。由于新系统的采用&#xff0c;对企业的管理能力和信息利用能力提出了更高的要求。在此情况下&#xff0c;企业引入了MRPⅡ系统&#xff0c;以此来替代使用多年、但存在重大缺陷的闭环MRP 系统。 根据以…

PHP魔幻(术)方法

PHP中的魔幻方法&#xff0c;也被称为魔术方法&#xff08;Magic Methods&#xff09;&#xff0c;是一组具有特殊功能的方法。这些方法在PHP中有固定的名称&#xff0c;并且会在特定的时机自动被PHP调用&#xff0c;而无需开发者显式调用。它们通常用于执行一些特殊的操作&…

电子摄像头分割系统源码&数据集分享

电子摄像头分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-DWR&#xff06;yolov8-seg-C2f-ContextGuided等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Glob…