C++Primer第20章 iostream库

news2024/11/15 14:03:46

第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都会在编译时刻被捕获到并标记为类型违例,实际上我们不关心,最起码,我现在没有关心.

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

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

相关文章

HTTP第六讲——键入网址再按下回车,后面究竟发生了什么?

使用 IP 地址访问 Web 服务器 首先我们运行 www 目录下的“start”批处理程序&#xff0c;启动本机的 OpenResty 服务器&#xff0c;启动后可以用“list”批处理确认服务是否正常运行。 然后我们打开 Wireshark&#xff0c;选择“HTTP TCP port(80)”过滤器&#xff0c;再鼠标…

接口自动化测试神器:Python+Requests+Unittest让你的测试用例飞起来

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠 随着互联网的发展&#xff0c;越来越多的应用程序采用了分布式架构&#xff0c;并通过API接口进行数据交换。因此&#xff0c;接口自动化测试已经成为了保证软件质…

git简介和使用、基础命令

文章目录 一、git的安装与配置二、Git工作区原理三、Git的使用和仓库的创建四、Git的常用操作五、配置公钥六、IDEA中配置Git 一、git的安装与配置 https://tortoisegit.org/ 下载对应版本安装即可 注意&#xff1a;配置中输入邮箱和密码一定要和自己的git账户一致 git的配置…

Seqkit-2.2.0 移植指南(openEuler 20.03 LTS SP3)

1.软件介绍 seqkit是一种跨平台的、极快的&#xff0c;全面的fasta/q处理工具。seqkit为所有的主流操作系统提供了一种可执行的双元文件&#xff0c;包括Windows&#xff0c;Linux&#xff0c;MacOS X&#xff0c;并且不依赖于任何的配置或预先配置就可以直接使用。 关于seqk…

C++类与对象—中

我们本期继续来学习C的类与对象&#xff0c;没有看过往期的同学建议先看看之前的 (11条消息) C类与对象—上_KLZUQ的博客-CSDN博客 目录 类的6个默认成员函数 构造函数 析构函数 拷贝构造函数 运算符重载 赋值运算符重载 日期类的实现 const成员 取地址及const取地址操作…

RabbitMQ启动失败的一系列尝试

一. 背景 在三台 CentOS 7.x上部署了RabbitMQ集群&#xff0c;如下&#xff1a; 服务器IPhostname节点说明端口管控台地址192.168.31.101masterrabbitmq master5672http://192.168.11.71:15672192.168.31.102slave1rabbitmq slave5672http://192.168.11.72:15672192.168.31.10…

centos7 安装 oceanbase 单机版测试

1&#xff1a; 说明 虚拟机&#xff1a;4核8G&#xff0c; 60G硬盘要求。 用的是社区版 官网地址&#xff1a; https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001692850 下载地址&#xff1a; https://www.oceanbase.com/softwarecenter 2&#…

基于Linux系统在线安装RabbitMQ

一、前言 二、Erlang下载安装 三、RabbitMQ下载安装 三、RabbitMQ Web界面管理 一、前言 本次安装使用的操作系统是Linux centOS7。 二、Erlang下载安装 在确定了RabbitMQ版本号后&#xff0c;先下载安装Erlang环境。下面演示操作过程&#xff1a; Erlang下载链接&#…

JDBC基础

1、JDBC概述 在开发中使用的是java语言&#xff0c;那么势必要通过java语言操作数据库中的数据。这就是接下来要学习的JDBC。 1.1 JDBC概念 JDBC 就是使用Java语言操作关系型数据库的一套API 全称&#xff1a;( Java DataBase Connectivity ) Java 数据库连接 我们开发的同一…

【Linux】7. 环境变量

1. 环境变量的引入 先描述一个现象&#xff0c;我们在执行二进制可执行程序的时候&#xff0c;是需要找到其所在位置的(程序要运行必须先加载到内存&#xff0c;是因为冯诺依曼体系结构规定CPU只能从内存中读取数据)&#xff0c;所以这也就是为什么我们在运行前带上./的原因&a…

java http get post 和 发送json数据请求

浏览器请求效果 HttpUtils 工具类 package com.bysen.common.utils.http;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ConnectException; impo…

一次业务系统无法使用对应的oracle数据库性能分析过程

一、问题概述 自助机系统及其它HIS等相关业务程序从3日早上8:20分左右出现使用异常&#xff0c;通过关闭自助机应用服务器及现场工程师KILL相关锁进程后正常。后续数据库工程师通过远程方式接入数据库环境进行问题排查&#xff0c;通过对相关日志等信息的深入分析&#xff0c;…

教育单位启动网络安全排查,查询IP地址能做什么?

近日&#xff0c;南京教育局主办了一场“网安2023”教育行动&#xff0c;各级教育单位都将开始教育系统网络安全责任制&#xff0c;做实各项教育网络安全工作&#xff0c;提升教育系统网络安全防护能力。 本次行动采取远程安全检查与现场检查相结合方式对各级教育单位进行网络…

Java爬取壁纸图片

Java爬取壁纸图片 前言依赖爬取图片工具类 -- WallHavenDownloadToDir.java 测试 前言 自己写了一个项目 想加一个功能&#xff1a;自动爬取壁纸发送给用户。说干就干&#xff0c;Python能干的&#xff0c;Java也能干&#xff01; 参考文章&#xff1a; jsoup的使用 Java爬虫…

STL-Vector容器

vector数据结构和数组非常相似&#xff0c;也称为单端数组 vector与普通数组区别&#xff1a; 数组是静态空间&#xff0c;而vector可以动态扩展 vector容器的迭代器是支持随机访问的迭代器 目录 创建vector容器 vector 容器赋值 vector容器的大小 vector插入和删除 ve…

java计算矩形的面积和周长的方法

在生活中&#xff0c;我们常常需要计算某个矩形的面积和周长&#xff0c;如我们经常用的计算器就是个不错的选择&#xff0c;它可以计算出任意一个矩形的面积和周长。那么&#xff0c;如果你想使用 Java编程语言来计算矩形的面积和周长&#xff0c;你该如何做呢&#xff1f;今天…

基于WiFi做呼吸频率检测-python版

一、概述 本Demo无需机器学习模型&#xff0c;Demo功能涉及的理论主要参考了硕士学位论文《基于WiFi的人体行为感知技术研究》&#xff0c;作者是南京邮电大学的朱XX&#xff0c;本人用python复现了论文中呼吸频率检测的功能。Demo实现呼吸速率检测的主要过程为&#xff1a; …

C# 对PdfiumViewer工具栏进行自定义,实现放大缩小,首页, 尾页,上一页等功能。

文章目录 前言PdfiumViewer工具栏扩展1 创建winform工程&#xff0c;UI界面2 打印预览3 放大功能4 缩小功能5 按比例缩放6 全屏7 首页和尾页8 上一页和下一页9 页码输入框10 显示当前预览的页码 小结 前言 关于PdfiumViewer的介绍 C# 使用PdfiumViewer实现对PDF文档打印预览&a…

【论文学习】ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation

ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation 目录 ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation摘要1 介绍2 DNN说话人识别系统2.1 Extended-TDNN x-vector2.2 基于ResNet的r-vector 3 提出的ECAPA-TDNN架构3.1 依赖于…

【Unity之c#专题篇】—核心章题单实践

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…