C++Primer第20章 iostream库

第20章 iostream库

C++中的IO流是通过多继承和虚拟继承实现的,下面是它的关系.

image-20230506061623860

我们要学习的就是三个库,这里我会把重点的拿出来

  • iostream: 终端操作
  • fstream:文件操作
  • sstream:格式化操作

20.1 输出操作符<<

输出操作符可以接受任何内置数据类型的实参,包含我们的const char*,string,甚至是自定义类型.先说为何我们可以连续的经行打印,看下面的现象.

image-20230506063119605

这是因为计算的结果是左边的ostream 操作数也就是说表达式的结果是cout 对象自己于是通过这个序列它又被应用到下一个输出操作符上等等我们说操作符<<从左向右结合.那么这里我们就可以输入自定义类型了,不过我们需要重载一下这个运算符.

#include <iostream>

class Node
{
  public:                    
friend std::ostream& operator<<(std::ostream& out, const Node& n);        
  private:                   
    int _x = 0;              
    int _y = 1;              
};                           
                             
std::ostream& operator<<(std::ostream& out, const Node& n){       
  out << n._x << " " << n._y;
  return out;                    
}                            
                             
int main()                   
{                                                         
  Node n1;                   
  std::cout << n1 << std::endl;
  return 0;
}                            

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wBXfvifH-1683615802874)(https://qkj0302.oss-cn-beijing.aliyuncs.com/qkj/202305072337818.png)]

注意,由于我们把const char*解释成C语言的字符串,同时有支持地址的打印,这里就会出现一些不太舒服的现象.

int main()
{
  int a = 10;
  const char* str = "hello";
  std::cout << "&a: " << &a << std::endl;
  std::cout << str << std::endl;             
  return 0;
}

image-20230506064545369

z注意,书上给了解决方法,这里我不推荐,我也没有看.我们知道const char*可以打印字符串就可以了,至于指针,我们不是有C语言的printf函数吗?那个不是更爽.

下面有一道练习题,先把部分答案写出来,不过我们这里看到一个非常有趣的类,这个类叫做complex,那么它究竟是什么呢?他是一个复数类,大家搜一下就可以了.

#include <iostream>
#include <vector>  
#include <string>  
using namespace std;  
  
void print_addr(const char* p)
{                                                                                            
  printf("%p\n", p);                                                             
}                                                                                
                                                                                 
void max_num(int x, double d)                                                    
{                                                                                
  cout << (x < d ? x : d) << endl;                                               
}                                                                                
                                                                                 
int main()                                                                       
{     
  // 我把第一问给省了,注意是太麻烦,但是不难
  string robin( "christopher robin" );                                           
  const char *pc = robin.c_str();                                                
  int ival = 1024;                                                               
  double dval = 3.14159;                                                         
  print_addr(pc);                                                                
  max_num(ival, dval);
  return 0;
}

image-20230506070405400

20.2 输入操作符>>

输入主要由右移操作符>> 来支持的,我们已经用过了.不过这里提到了一个非常有趣的概念,我们知道cin是支持循环读取的,那么下面的代码编译器是如何知道我们读取应该结束了呢?

#include <iostream>    
#include <vector>    
#include <string>    
using namespace std;    
    
    
int main()    
{    
  int n = 0;    
  while(cin >> n)    
  {    
                                                                                                                                
  }        
  return 0;                         
}  

他给了两个解释,先看结论,后面解释.

  • 读到文件结束
  • 读到无效值,这个有趣的很

缺省情况下输入操作符丢弃任何中间空白空格制表符换行符走纸以及回车符,意思就是我们可以这样输入.不过大家用的时候还是规范一点吧,看个人喜好.

#include <iostream>
#include <string>
using namespace std;  
int main()
{
  int a = 0;
  int b = 0;
  int c = 0;
  cin >> a >> b >> c;
                                                               
  cout << "a: " << a << endl;
  cout << "b: " << b << endl;
  cout << "c: " << c << endl;
  return 0;       
}                            

image-20230506160116074

20.3 其他输入输出操作符

这里我们只谈两个成员函数,都是非常简单的,这本书谈的实在是太全了,一般我们都不会用到这么多的功能,当然也可能是见识有点少.我们上面说了,输入和输出的时候遇到某一些字符会出现问题,这里继续看例子.

#include <iostream>
#include <string>
using namespace std;

int main()
{
  string str;
  cin >> str;
  cout << str << endl;
  return 0;
}

image-20230507201911066

那么我们是不是可以找一个方法来解决这个问题呢?我们要求想空格也可以输入.这里看里面提供的函数.

  • get 从流中得到一个字符
  • put 向流中输送一个字符
#include <iostream>
#include <string>
using namespace std;

int main()
{
  string str;
  char ch = 0;
  while (cin.get(ch))
  {
    cout.put(ch);
  }

  return 0;
}

image-20230507202336239

那么我们该如何退出来呢?太简单了,看下面的

#include <iostream>
#include <string>
using namespace std;

int main()
{
  string str;
  char ch = 0;
  while (cin.get(ch))
  {
    cout.put(ch);
    if (ch == '\n')
      break;
  }

  return 0;
}

image-20230507202454538

我看书上说了我们在输入多行的时候可以使用ignore(),来去掉一个字符,就像我们的换行符,说实话我没有把它的原理看太懂,不过我们可以使用上面的方法来好好设计一下也是可以完成这样的功能而且成本也不高.

20.4 重载输出操作符<<

这里直接上代码,我们之前学过了.

#include <iostream>
#include <string>
using namespace std;

class Myclass
{
  friend ostream &operator<<(ostream &os, const Myclass &node);

private:
  int x = 0;
  int y = 1;
};

ostream &operator<<(ostream &os, const Myclass &node)
{
  os << node.x << " " << node.y;
  return os;
}

int main()
{
  Myclass node;
  cout << node << endl;
  return 0;
}

image-20230507203207749

20.5 重载输入操作符>>

这个更加简单.

#include <iostream>
#include <string>
using namespace std;

class Myclass
{
  friend ostream &operator<<(ostream &os, const Myclass &node);
  friend istream &operator>>(istream &os, Myclass &node);

private:
  int x = 0;
  int y = 1;
};

ostream &operator<<(ostream &os, const Myclass &node)
{
  os << node.x << " " << node.y;
  return os;
}
istream &operator>>(istream &in, Myclass &node)
{
  in >> node.x >> node.y;
  return in;
}

int main()
{
  Myclass node;
  cin >> node;
  cout << node << endl;
  return 0;
}

image-20230507203438634

20.6 文件输入和输出

这个已经来到一个比较常用的功能了,C++的文件IO非常好用.他的思想是把文件作为一个参数构造出一个对象,我们把这些对象作为流就可以进行操作了,多个不说,上代码.

打开一个我们读操作的流

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
  ifstream in("file.txt");
  if (!in.is_open())
    return -1;
  char ch = 0;
  while (in.get(ch))
  {
    cout << ch;
  }

  return 0;
}

image-20230507210440581

下面我们打开一个写的文件,我们这里直接追加.

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
  // std::ios::out 是 把原本内容清空,默认就是它
  ofstream out("file.txt", std::ios::app);
  if (!out.is_open())
    return -1;

  string str = "这是追加";
  out << str;
  return 0;
}

image-20230507210908263

有人感觉太麻烦,我们还要定义两个对象,这里我们直接用一个,然后传入我们是读还是写.来看代码.


#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
  fstream in_out;
  in_out.open("file.txt", std::ios::in);
  string str;
  while (std::getline(in_out, str))
  {
    cout << str;
    cout << endl;
  }

  in_out.close();
  in_out.open("file.txt", std::ios::out);
  str = "这是截断";
  in_out << str;
  in_out.close();

  return 0;
}

image-20230507211923488

20.7 条件状态

前面所谓的调节状态就是我们什么时候不能正确使用我们的流,我们这里直接看例子吧,为何我们把字符串给int类型会报错,我们知道他应该报错,可是编译器是如何检测出来的,我们有理由怀疑这里存在检测机制,实际上确实有,不过我这里不和大家分享了,我们规范使用就可以了.

int main()
{
  int val = 0;
  cin >> val;

  return 0;
}

image-20230507220056258

那么我们这里我们谈什么呢?老生重谈,我们这里你觉得如何?

int main()
{
  int val = 0;
  while (cin >> val)
  {
  }

  return 0;
}

请问cin>>val为何可以作为判断条件,我们知道cin返回的对象就是流,本质就类似我们自定义类型,那么如果我们自己写一下自定类型可以这样吗,它可以自己东的转换为bool吗?试一下.

struct Node
{
  int x;
};

int main()
{
  int val = 0;
  Node n;
  while (n)
  {
  }

  return 0;
}

image-20230507221632760

我们发现不行,不过我们要是这样做就可以了,看好了


#include <iostream>
#include <string>
#include <fstream>
using namespace std;

struct Node
{
  int x;
  operator bool()
  {
    return true;
  }
};

int main()
{
  int val = 0;
  Node n;
  while (n)
  {
    cout << "hello" << endl;
    break;
  }

  return 0;
}

image-20230507221833186

实际上cin对象所在的类型里面就重载了operator bool,这就是我们为何可以转换的原因,这里有两个问题要谈

  1. 可以转换成其他累心吗 – 可以
  2. cin 还是没有谈如何判断我们不能用

来我们测试其他的类型.


#include <iostream>
#include <string>
#include <fstream>
using namespace std;

struct Node
{
  int x;
  operator int()
  {
    return 1;
  }
};

int main()
{
  int val = 0;
  Node n;

  int ret = n;
  cout << ret << endl;

  return 0;
}

image-20230507222228564

我们来解释第二个问题,我们看下面的代码.

int main()
{
  int ret = 0;
  cin >> ret;
  while (!cin)
  {
    cout << "hello" << endl;
    break;
  }

  return 0;
}

image-20230507222511606

那么 operator bool()函数里面一定存在条件判断,那么就是这个就是我们书上这一小节谈的就是这个,具体的我们直接看看书就可以了.

20.8 string 流

来说我们我们第三个部分,就是我们所谓的格式化,看书上这段话.

ostringstream 类向一个string 插入字符,istringstream 类从一个string 对象读取字符而stringstream 类可以用来支持读和写两种操作.


#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
struct Node
{
  int x = 1;
  int y = 2;
};

int main()
{
  Node n;
  ostringstream out;
  out << "x: " << n.x << "\n"
      << "y: " << n.y << "\n";
  cout << out.str();
  return 0;
}

image-20230507224312369

下面我们来说反序列化,也是挺简单的.,注意,这里我们没有实际的场景,写的非常挫.

struct Node
{
  int x = 1;
  int y = 2;
};

istream &operator>>(istream &os, Node &n)
{
  os >> n.x >> n.y;
}

int main()
{
  string str = "10 20";
  istringstream in(str);
  Node n;
  in >> n;

  cout << n.x << " " << n.y << endl;
  return 0;
}

image-20230507225632881

20.9 格式状态

不谈,不如我们回来看printf,那里我们更加熟悉.

20.10 强类型库

iostream库是强类型的例如试图从一个ostream 读数据或者写数据到一个istream都会在编译时刻被捕获到并标记为类型违例,实际上我们不关心,最起码,我现在没有关心.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怎么搭建个人小型渲染农场?搭建渲染农场配置

渲染农场是众多机器组成的渲染集群&#xff0c;通常用来渲染你的单帧效果图或动画项目&#xff0c;我们借助渲染农场的力量&#xff0c;可以满足3D项目交期时间迫在眉睫的需求&#xff0c;当你试着在自己的机器上渲染一个复杂的动画项目时&#xff0c;可能需要几十小时的等待时…

车载软件架构——闲聊几句AUTOSAR BSW(四)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 我们并不必要为了和谐,而时刻保持通情达理;我们需要具备的是,偶尔有肚量欣然承认在某些方面我们可能会有些不可理喻。该有主见的时候能掷地有声地镇得住场…

大数据赛项|2023年广东省大学生计算机设计大赛初赛结果公示

2023年广东省大学生计算机设计大赛 暨第16届中国大学生计算机设计大赛 粤港澳大湾区赛初赛结果公示 根据《广东省教育厅关于做好2023年广东省本科高校大学生学科竞赛工作的通知》&#xff0c;广东外语外贸大学承办2023年“广东省大学生计算机设计大赛”。 在广大师生的热情…

达摩院开源多模态对话大模型mPLUG-Owl

miniGPT-4的热度至今未减&#xff0c;距离LLaVA的推出也不到半个月&#xff0c;而新的看图聊天模型已经问世了。今天要介绍的模型是一款类似于miniGPT-4和LLaVA的多模态对话生成模型&#xff0c;它的名字叫mPLUG-Owl。 论文链接&#xff1a;https://arxiv.org/abs/2304.14178…

实时操作系统内存管理-TLSF算法

内存管理-TLSF算法 前言TLSF算法&#xff1a;为什么内存又叫内存“块”&#xff1a;O(1)查找空闲块&#xff1a;确定fl&#xff1a;确定sl&#xff1a;提级申请&#xff1a;分割块&#xff1a; 空闲块如何串成链表&#xff1f;减少外部碎片&#xff1a;查找上下块&#xff1a; …

OpenGL 4.0的Tessellation Shader(细分曲面着色器)

细分曲面着色器&#xff08;Tessellation Shader&#xff09;处于顶点着色器阶段的下一个阶段&#xff0c;我们可以看以下链接的OpenGL渲染流水线的图&#xff1a;Rendering Pipeline Overview。它是由ATI在2001年率先设计出来的。 目录 细分曲面着色器细分曲面Patch细分曲面控…

Node.js对ES6 及更高版本的支持

目录 1、简介 2、默认情况下什么特性随着 Node.js 一起发布&#xff1f; 3、有哪些特性在开发中&#xff1f; 4、移除这个标记&#xff08;--harmony&#xff09;吗 5、Node.js 对应 V8 引擎 1、简介 Node.js 是针对 V8 引擎构建的。通过与此引擎的最新版本保持同步&…

【HMS Core】Health Kit想要查看数据是来自用户的哪个设备,如何查看?

【问题描述1】 如何查看运动健康数据是来自用户的哪个设备&#xff1f; 【解决方案】 可以通过返回的数据中携带的dataCollectorId来查询提供数据的设备信息&#xff1a; 请求示例&#xff08;以查询睡眠记录详情为例&#xff09;&#xff1a; 1、查询睡眠记录并关联睡眠状…

用友携国资国企走进浙江龙游,共探区县国资智慧监管新样板

近日&#xff0c;由龙游县国有资产经营有限公司指导&#xff0c;用友网络科技股份有限公司&#xff08;以下简称&#xff1a;用友网络&#xff09;主办的“成为数智企业 迈向高质量发展——2023走进龙游数智化观摩研讨会”在浙江龙游成功举办&#xff01;全国近百位国资国企负责…

操作系统学习02

&#xff01;&#xff01;&#xff01;由于感冒和出去玩&#xff0c;好几天没学这些计算机基础知识了&#xff01;&#xff01;&#xff01; 抓紧跟上嘿嘿嘿 1、内存管理主要做了什么 操作系统的内存管理非常重要&#xff0c;主要负责下面这些事情&#xff1a; 内存的分配与…

shell脚本--函数

目录 一&#xff1a;shell函数定义 1.函数的含义 2.函数的优点 3.函数的格式 4.函数返回值 &#xff08;1&#xff09;return输出 &#xff08;2&#xff09;echo输出 二&#xff1a;函数传参 1.情景一 2.情景二 3.情景三 4.情景四 三:递归函数 1.递归函数定义 2.通过…

ASEMI代理ADUM3223ARZ-RL7原装ADI车规级ADUM3223ARZ-RL7

编辑&#xff1a;ll ASEMI代理ADUM3223ARZ-RL7原装ADI车规级ADUM3223ARZ-RL7 型号&#xff1a;ADUM3223ARZ-RL7 品牌&#xff1a;ADI /亚德诺 封装&#xff1a;SOIC-16 批号&#xff1a;2023 安装类型&#xff1a;表面贴装型 引脚数量&#xff1a;16 工作温度:-40C~125…

利用MQ事务消息实现分布式事务

MQ事务消息使用场景 消息队列中的“事务”&#xff0c;主要解决的是消息生产者和消息消费者的数据一致性问题。 拿我们熟悉的电商来举个例子。一般来说&#xff0c;用户在电商 APP 上购物时&#xff0c;先把商品加到购物车里&#xff0c;然后几件商品一起下单&#xff0c;最后…

2路 QSFP,40G 光纤的数据实时采集(5GByte/s 带宽)板卡设计原理图 -PCIE732

板卡概述 PCIE732 是一款基于 PCIE 总线架构的高性能数据传输卡&#xff0c;板卡具有 1 个 PCIex8 主机接口、2 个 QSFP40G 光纤接口&#xff0c;可以实现 2 路 QSFP 40G 光纤的数据实时采集、传输。板卡采用 Xilinx 的高性 能 Kintex UltraScale 系列 FPGA 作为实时处理器…

qiankun 微前端 demo(Vue2)

前言 这是我最近刚开始学微前端&#xff08;qiankun框架&#xff09;做的一个小demo&#xff0c;做的时候还是遇到很多问题的&#xff0c;在网上也是看了很多别人的Blog&#xff0c;最后也是磨出来了&#x1f602;&#x1f602;&#x1f602;&#xff1b;这篇文章总统分为分为…

windows 编译 opencv

编译需要的基础工具 #cmake是配置构建工具&#xff0c;mingw是编译工具 cmake CMake是一款跨平台的编译管理工具&#xff0c;可以自动生成各种不同编译环境&#xff08;如Makefile、Visual Studio Solution等&#xff09;&#xff0c;从而实现在不同平台上进行代码编译的目的…

Qwik 1.0 发布,全栈式 Web 框架

Qwik 是一个全栈式 Web 框架&#xff0c;Qwik 基于 React、Angular 和 Vue 等其他 Web 框架的概念&#xff0c;但以 JavaScript 流等更新的方法脱颖而出&#xff0c;允许以高性能向用户交付复杂的 Web 应用程序。 随着 Web 应用程序变得越来越大&#xff0c;它们的启动性能会下…

强烈推荐:一款中文AI问答、创作、绘画工具

前言 相信很多人已经听过ChatGPT这款人工智能机器人了&#xff0c;它能够根据用户输入的内容&#xff0c;自动生成智能回复。它使用自然语言处理技术&#xff0c;通过学习大量的文本资料&#xff0c;能够模拟人类的对话行为。它是由OpenAI开发的&#xff0c;一家非常伟大的人工…

Http知识

一、http协议 目前存在HTTP1.1&#xff08;当前广泛运用的版本&#xff09;、HTTP2.0和HTTP3.0协议&#xff0c;有以下的优点和缺点 1. HTTP1.1 优点&#xff1a;默认支持长连接&#xff0c;即在一个TCP连接上可以传送多个HTTP请求和响应&#xff0c;减少了建立和关闭连接的…

Flutter框架:从入门到实战,构建跨平台移动应用的全流程解析

第一章&#xff1a;Flutter框架介绍 Flutter框架是由Google推出的一款跨平台移动应用开发框架。相比其他跨平台框架&#xff0c;Flutter具有更高的性能和更好的用户体验。本章将介绍Flutter框架的概念、特点以及与其他跨平台框架的比较&#xff0c;以及Flutter开发环境的搭建和…