C++Prime Plus(7)

article/2025/9/14 4:09:07

目录

  • 96.输入输出概述
  • 97.使用cout输出(1)ostream基本功能
  • 98.使用cout输出(2)格式化输出
  • 99.使用cin输入
  • 100.文件(1)简单的文件IO
  • 101.文件打开的进一步讨论
  • 102.二进制文件访问
  • 103.随机读写

96.输入输出概述

C++的输入输出是由库iostream中提供的一组类实现的;


C++把输入输出看成字节流,每个字节可以由程序解释成一个字符,或者只是一个二进制位构成的串;

输入流:外围设备流向输入缓冲区,Input对象从输入缓冲区读数据再流向内存;
输出流:内存流向Output对象,Output对象处理后传送给输出缓冲区,再流向外围设备;

通常,输入对象来自类istream,输出对象来自类ostream。

C++在命名空间std下预定义了一些输入对象和输出对象:

  • cin对象:类istream的对象,与标准输入设备(通常指键盘)关联在一起;
  • cout对象:类ostream的对象,与标准输出设备(通常指显示器)关联在一起;
  • cerr对象:类ostream的对象,与标准错误输出设备(通常指显示器)关联在一起,不经过缓冲区;
  • clog对象:类ostream的对象,与标准错误输出设备(通常指显示器)关联在一起,经过缓冲区;

语句的解释:cout<<对象1<<对象2;

首先确保对象1和对象2的类中,有定义运算符<<的重载(通常是类中的友元,回顾60.友元),cout<<对象1 返回ostream类的对象(其实还是cout,因为cout作为参数传入,在调用结束后返回cout对象),所以变成cout<<对象2 继续输出。


重定向标准输入输出
如果我们在命令行界面执行可执行文件,只要在命令行提示符后面输入可执行文件名,程序中的输入部分都是从键盘读,输出都是显示在显示器。

我们可以在命令行执行可执行文件时,重定向输入:

可执行文件名 < 文本文件名 #从文本文件读数据

重定向输出:

可执行文件名 > 文本文件名 #将数据输出到文本文件

同时重定向输入和输出,从文本文件1读数据,将处理后的数据输出到文本文件2:

可执行文件名 < 文本文件名1 > 文本文件名2

97.使用cout输出(1)ostream基本功能

假设有:

int x=-1;
cout<<x;

编译器执行整型类的operator<<函数,从x的地址开始取4个字节,将其转换成字符串”-1”,发送到显示器

operator<<函数的返回值是ostream&,所以允许拼接输出,比如:

cout<<x<<"abc";

ostream类的成员函数:put和write
put:输出一个字符
函数原型ostream& put(char),返回ostream类的对象本身

cout.put('a'); //输出字符a
cout.put('a').put('b'); //先输出字符a,再输出字符b,cout.put('a')返回对象cout

write函数:输出指定字符数的字符串

const char* tmp="abcdefg";
cout.write(tmp,5); //输出abcde

98.使用cout输出(2)格式化输出

C++提供了用于执行格式化 输入输出 的流操作算子(本质上是<<运算符的参数,是函数对象)和成员函数(ostream类的成员函数)

设置整型数的基数
输入输出流中的整型数默认为十进制表示,若要设置其他数制,可以用流操作算子(使用任何带参数的流操作算子,都必须包含头文件iomanip):
fig1
基数值只有被显式更改时才会变化,否则一直沿用原有的基数

示例
fig2
设置浮点数的精度
浮点数的精度指实数的有效位数,设置方法:

  • 流操作算子:setprecision(位数)
  • cout成员函数:precision(位数)

一旦设置了精度,将影响所有输出的浮点数精度,直到下一个设置精度的操作出现为止

示例
fig3
设置域宽
域宽是数据所占的字符数,设置方法为:

  • 流操作算子:setw(宽度)
  • 成员函数:width(宽度)

比如a=123, b=456,输出cout<<a<<b123456,但是如果cout<<setw(5)<<x<<set(5)<<y会输出:\n\n123\n\n456

99.使用cin输入

cin是istream类的对象,>>运算符的返回值还是cin,>>以空白字符(空格,回车,TAB)作为输入流(输入缓冲区)中的分隔符,或者在读缓冲区时,遇到与接收变量类型不符合的数据时,本次>>输入结束(即使用类型不符合的数据作为分隔符)。
fig4
利用cin>>时,会自动丢弃空白字符;使用类型不符合的数据作为分隔符时,不丢弃该数据;

输入错误的处理
如果输入数据不能转换成接收变量的类型,或者输入了EOF,cin>>变量 表达式返回0,变量的值也变成0;
fig5
输入错误的分类

  • cin.eof():读到EOF;
  • cin.bad():IO失败或者无法诊断的错误;
  • cin.fail():没能读到预期类型的数据;

fig6
遇到错误时,程序不会继续读输入缓冲区,我们可以调用cin.clear()清除错误,让程序可以从输入缓冲区读数据。示例如下:
fig7
其他输入方法

  • ch=cin.get():读入一个字符,可以是任意字符,包括空白字符和EOF
  • cin.getline(字符数组名,数组规模)
  • cin.get(字符数组名,数组规模)

cin.getline(字符数组名,数组规模)cin.get(字符数组名,数组规模)以回车字符或达到数组规模结束输入,区别:getline将回车的换行符丢弃,get会将换行符留在缓冲区放在下一次输入的最开始位置。

在早期C语言没有getline时候,只能使用get,但是get对于读入回车的处理会让人们对字符文本的逻辑容易出错,为了让get每次都只输入一行,并让回车不放在下一次输入的行中,我们使用无参数的cin.get()cin.get()读入任意一个字符,包含回车。

100.文件(1)简单的文件IO

文件读写需要我们定义流对象,并与文件相关联;

文件流类(从标准输入输出流类派生,被定义在头文件fstream中):
ifstream:输入文件流
ofstream:输出文件流
fstream:输入输出文件流

文件流对象关联文件(两种方式):
1.使用open成员函数:

ofstream outfile;
outfile.open(“file_name”);

2.在定义对象时,向构造函数传递参数(参数为文件名):

ifstream infile(“file_name”);

标准输入输出流对象在控制台和内存之间交流,文件流对象在文件和内存之间交流:

infile>>x; //将infile关联的文件内容读到变量x
outfile<<123<<3+5; //将字符串”123”和int数值8保存到outfile关联的文件

切断文件流对象与文件的关联:
使用close成员函数:infile.close();

简单文件访问示例:
fig8
上述示例会在当前工程目录下创建名为pythag的文件,并将内容写入,我们也可以用记事本查看文件中的内容。

101.文件打开的进一步讨论

首先回顾关联文件与文件流对象的两种方式:
1.open成员函数
2.流的构造函数(向构造函数传递参数)

文件打开时可以指定打开方式:

文件流对象.open(文件名, 打开模式);
文件流类 文件流对象(文件名, 打开模式);

常用打开模式如下:

  • ios_base::in,含义:打开文件,做读操作,这是ifstream的默认参数(如果指定路径没有文件,不会创建);
  • ios_base::out,含义:打开文件,做写操作,这是ofstream的默认参数(1.如果指定路径中并没有包含该文件,会创建一个新的;2.每次写入的内容会覆盖以前的内容,暗含了std::ios_base::truc);
  • ios_base::app,含义:在每次写操作前,找到文件尾,即append(如果指定路径不包含该文件,会创建一个新的);
  • ios_base::ate,含义:打开文件后,立刻定位到文件尾(如果指定的路径不存在该文件不会创建)
  • ios_base::truc,含义:打开文件时,清空文件(如果指定的路径不存在该文件不会创建)
  • ios_base::binary,含义:以二进制模式进行输入输出操作(如果指定的路径不存在该文件不会创建)

打开方式组合:以添加方式打开二进制文件

ofstream outfile(“file1”, ios_base::app | ios_base::binary);

关于文本文件
文件中的信息是合法字符,用<<向文件写数据时,数据被转换成字符串,用>>从文件读数据时,字符串被转换成接收变量的类型。

关于二进制文件
存储的数值是机器表示,比如将一个double类型数值写入二进制文件,文件存储的是64位表示。

对比:将整型-1写入文件
文本文件:占用2个字符,分别是’-’和’1’
二进制文件:在文件中占4字节,是-1的补码表示

检查文件打开是否成功
1.检查文件流对象:打开文件失败时,流对象返回false;
2.fail成员函数:打开文件失败时,fail函数返回true;
3.is_open成员函数:文件打开成功后,is_open函数返回true。

102.二进制文件访问

对于文本文件,只要文件与文件流对象建立关联(也就是打开了文件),文件的访问方式和控制台一样,只是换了一种流对象而已。

但对于二进制文件的访问,我们人是看不懂二进制文件的,但是二进制文件相对于文本文件有一个优点:数据在文件中占用的空间与数据类型有关,与具体的值无关,这便于随机访问。

假设我们在文本文件中写入一组整数,我们要获取第1000个整数的值,我们只能从文本文件中一个一个读,直到读到第1000个整数才能获得值。但对于二进制文件,由于整型都是只占有4字节,我们可以不用读前999个数,我们可以直接锁定到第1000个数的地址,然后取值。(这就是随机访问)

二进制文件读写
对于二进制文件的读写,我们不能使用>>和<<(因为>>和<<会自动在内存表示与人能看懂的字符串之间进行转换),而二进制文件要求:我们直接将内存表示写到二进制文件,或者直接将二进制文件读到内存中。

写文件:

write(char*, 长度); 
//类型转为char,因为char占1个字节,方便计数信息长度;

当我们要把内存的信息写到文件,我们要告诉机器两件事情:1.这块信息在机器中的地址是多少,2.这块信息的长度是多少。

读文件:

read(char*, 长度); 
//char* 用于指明将文件中的数据读到机器中的char*所指位置,并且有多大长度的信息要读入内存。

判断读文件结束:
eof()read函数的返回值
在读文本文件时候,如果用>>去读,操作结果返回fin,如果fin.eof()为true可以判断读文件结束。对于二进制文件的读,也是一样的,也是看输入文件流对象的eof()。
读二进制文件判断结束也可以看read函数的返回值(读到文件结束,read返回false)。

比如:

int x=5;
fout.write((char*)&x, sizeof(int));int y;
fin.read((char*)&y, sizeof(int));

二进制文件读写示例(把一组结构体类型信息写到一个二进制文件中,便于随机访问)
fig9
fig10
fig11
提前说明一个内容:在代码的最后几行里看到
fig12
并且发现分别打印了两行:
fig13
这是因为在读或写二进制文件时,有一个指针,当文件流对象关联文件后,指针默认指向文件开始位置,当读入或写入一定长度信息后,指针停留在 文件起始位置+该长度偏移 的位置。下次对文件的操作就从指针当前位置开始执行。

103.随机读写

我们可以手动设置读写文件的位置
设置读文件的位置:seekg(偏移量, 起始位置); //操作位置=起始位置+偏移量
设置写文件的位置:seekp(偏移量, 起始位置);

对于参数 起始位置

  • ios_base::beg 文件开始处,是函数参数的默认值
  • ios_base::cur 当前位置
  • ios_base::end 文件尾

102.二进制文件访问中的例子继续演示

首先显示原文件的内容:
fig14
修改某一条记录:由于是二进制文件,我们可以很容易去定位
fig15
显示修改后的文件新内容:
fig16
执行结果如下:
fig17


http://chatgpt.dhexx.cn/article/g5Ahairp.shtml

相关文章

E-Prime软件包及安装

E-Prime软件包及安装 1 版本问题2 安装过程3 注意事项4 唠唠叨叨 Hello&#xff0c; 这里是行上行下&#xff0c;我是喵君姐姐~ 众所周知&#xff0c;E-Prime是实验设计的执行者。 当我们提出一个想法&#xff0c;则需要一个具体的软件来实现它。 而E-Prime相对于Matlab和Py…

Prime Sample

又发现了个框架 但没有代码啊~~ 还是搬来了&#xff0c;重要样本关注机制&#xff0c;一种新颖的目标检测框架 上论文 论文地址&#xff1a; https://arxiv.org/pdf/1904.04821.pdf 在目标检测框架中&#xff0c;平等对待所有样本并以平均性能最大化目标是一种常见的范例。在…

Prime Factors

此题需要使用到质因子分解的算法&#xff0c;可以参考以下链接&#xff1a; https://blog.csdn.net/qq_42410605/article/details/100150140 题目描述&#xff1a; Given any positive integer N,you are supposed to find all of prime factors,and write them in the form…

SpringBoot实现分布式锁

SpringBoot实现分布式锁 先了解一下线程数&#xff1a; 线程锁 线程锁&#xff1a;主要用来给类&#xff0c;方法&#xff0c;代码加锁&#xff0c;当某个方法或者某块代码使用synchronize关键字来修饰&#xff0c;那么在同一时刻最多只能有一个线程执行该代码&#xff0c;如…

深入理解ConcurrentHashMap原理分析以及线程安全性问题

在之前的文章提到ConcurrentHashMap是一个线程安全的&#xff0c;那么我么看一下ConcurrentHashMap如何进行操作的。 ConcurrentHashMap与HashTable区别&#xff1f; HashTable put()源代码 我们来看一下put 操作&#xff1a; 方法体 被 同步锁标记&#xff0c;由于同步锁的…

Redis分布式锁到底安全吗?

若有收获,请记得分享和转发哦 这篇文章我想和你聊一聊&#xff0c;关于 Redis 分布式锁的「安全性」问题。 Redis 分布式锁的话题&#xff0c;很多文章已经写烂了&#xff0c;我为什么还要写这篇文章呢&#xff1f; 因为我发现网上 99% 的文章&#xff0c;并没有把这个问题真正…

Java线程安全

前段时间有测试一个后端对账单和话单采集服务,在测试过程中有涉及到数据库读写逻辑和并发的场景,所以结合经验针对系统技术架构设计了部分并发场景结合数据库读写时可能出现的一些问题的用例,也确实出现了一些测试环境容易忽视,线上环境确确实实可能出现的问题,当然最后还是得到…

线程安全之 - ThreadLocal

ThreadLocal的底层原理 ThreadLocal是Java中所提供的线程本地存储机制&#xff08;线程内共享&#xff09;&#xff0c;可以利⽤该机制将数据缓存在某个线程内部&#xff0c; 该线程可以在任意时刻、任意⽅法中获取缓存的数据&#xff1b;ThreadLocal底层是通过ThreadLocalMap…

线程锁(ReentrantLock、synchronized)为何不能用作分布式锁

为什么使用分布式锁 分布式锁实现目前有三种&#xff1a; 数据库乐观锁&#xff1b;ZooKeeper的分布式锁;Redis的分布式锁&#xff1b; 在以前单体架构Web应用场景下&#xff0c;我们可以使用ReentrantLock或synchronized进行上锁&#xff0c;保证资源安全&#xff0c;现如今大…

Redis分布式锁真的安全吗?

大家好&#xff0c;今天我们来聊一聊Redis分布式锁。 首先大家可以先思考一个简单的问题&#xff0c;为什么要使用分布式锁&#xff1f;普通的jvm锁为什么不可以&#xff1f; 这个时候&#xff0c;大家肯定会吧啦吧啦想到一堆&#xff0c;例如java应用属于进程级&#xff0c;…

ThreadLocal能解决线程安全问题?胡扯!本文教你正确的使用姿势【享学Java】

跟对领导很重要&#xff1a;愿意教你的&#xff0c;并且放手让你做的领导要珍惜。 目录 前言正文ThreadLocal是什么&#xff1f;ThreadLocal怎么用&#xff1f;局限性InheritableThreadLocal向子线程传递数据开源框架使用示例 ThreadLocal不能解决共享变量的线程安全问题Thread…

Java线程安全详细总结

以下是我的PPT文档&#xff0c;不知道怎么复制到博客&#xff0c;只能一个一个插入图片发上来了。感觉总结的不错&#xff0c;分享一下。 文档地址&#xff1a;http://download.csdn.net/detail/csujiangyu/9526641

分布式系统详解--基础知识(线程)

分布式系统详解--基础知识&#xff08;线程&#xff09; 一、导读 前面跟大家讲了一下 分布式系统详解--基础知识&#xff08;概论&#xff09; &#xff0c;可以稍微了解一下大体上分布式是怎么一回事了。这片篇文章主要是讲述一下线程的问题分别介绍一下&#xff0c;什么线…

分布式项目线程安全问题(电商扣减库存的安全问题1)

电商减库存存在的安全问题 Override public void deductStock(Map<Long, Integer> skuMap) {for (Map.Entry<Long, Integer> entry : skuMap.entrySet()) {Long skuId entry.getKey();Integer num entry.getValue();// 查询skuSku sku getById(skuId);// 判断…

分布式项目中 如何保证线程安全问题?-------ZooKeeper

前沿&#xff1a; 上篇文章我们聊到了在解决分布式项目中线程安全问题&#xff0c;提到解决方案还有其他的&#xff0c;那么在此提出 基于 zookeeper 解决分布式项目中的线程安全问题 也是目前市面上比较流行的。做为一个高级开发工程师也是必须要学习的。 ZooKeeper是什么东…

分布式线程安全(redis、zookeeper、数据库)

https://blog.csdn.net/u010963948/article/details/79006572 Q:一个业务服务器&#xff0c;一个数据库&#xff0c;操作&#xff1a;查询用户当前余额&#xff0c;扣除当前余额的3%作为手续费 synchronized lock db lock Q&#xff1a;两个业务服务器&#xff0c;一个数据库&…

分布式集群中如何保证线程安全?

目录 分布式集群中的线程安全问题 解决方法 串行化 分布式锁 Redis如何实现呢&#xff1f; 问题&#xff1a;setnx刚好获取到锁&#xff0c;业务逻辑出现异常&#xff0c;导致锁无法释放 问题&#xff1a;可能会释放其他服务器的锁。 问题&#xff1a;删除操作缺乏原子…

java outlook 发送邮件_基于java使用JavaMail发送邮件

一、邮件的相关概念 邮件协议。主要包括&#xff1a; SMTP协议&#xff1a;Simple Mail Transfer Protocol&#xff0c;即简单邮件传输协议&#xff0c;用于发送电子邮件 POP3协议&#xff1a;Post Office Protocol 3&#xff0c;即邮局协议的第三个版本&#xff0c;用于接收邮…

java 发邮件(有正文,有图片,有附件)

一 需求: 1 java实现邮件发送 2 发送内容: ① 正文: 图片说明和图片 ② 附件一: 图片作为附件发送 ③ 附件二: Excel表格 二 思路: 1首先创建一个 Java 工程&#xff0c;把下载好的 javax.mail.jar 作为类库加入工程 2邮件创建步骤: 配置连接邮件服务器的参数( 邮件服务器SM…

java接收邮件_Java实现邮件收发

一. 准备工作 1. 传输协议 SMTP协议-->发送邮件: 我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器) POP3协议-->接收邮件: 我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器) 2. 邮件收发原理 闪电…