C++格式化输入和输出

news2025/1/13 14:21:14

格式化输入与输出

除了条件状态外,每个iostream对象还维护一个格式状态来控制IO如何格式化的细节。

格式状态控制格式化的某些方面,如整型值是几进制、浮点值的精度、一个输出元素的宽度等。

标准库定义了一组操纵符来修改流的格式状态。

一个操纵符是一个函数或是一个对象,会影响流的状态,并能用作输入或输出运算符的运算对象。类似输入和输出运算符,操纵符也返回它所处理的流对象,因此我们可以在一条语句中组合操纵符和数据。

我们已经在程序中使用过一个操纵符——endl,我们将它“写”到输出流,就像它是一个值一样。但endl不是一个普通值,而是一个操作:它输出一个换行符并刷新缓冲区。

很多操纵符改变格式状态

操纵符用于两大类输出控制;控制数值的输出形式以及控制补白的数量和位置。

大多数改变格式状态的操纵符都是设置/复原成对的;

一个操纵符用来将格式状态设置为一个新值,而另一个用来将其复原,恢复为正常的默认格式。

当操纵符改变流的格式状态时,通常改变后的状态对所有后续IO都生效

当我们有一组IO操作希望使用相同的格式时,操纵符对格式状态的改变是持久的这特性很有用。

实际上,一些程序会利用操纵符的这一特性对其所有输入或输出重置一个成多个格式规则的行为。在这种情况下,操纵符会改变流这一特性就是满足要求的了。

但是,很多程序(而且更重要的是,很多程序员)期望流的状态符合标准库正常的默认设置。在这些情况下,将流的状态置于一个非标准状态可能会导致错误。因此,通常最好在不再需要特殊格式时尽快将流恢复到默认状态。

控制整型格式

控制布尔值的格式

操纵符改变对象的格式状态的一个例子是 boolalpha 操纵符。

默认情况下,bool值打印为1或0。一个true值输出为整数1,而false输出为0,我们可以通过对流使用booialpha操纵符来覆盖这种格式:

cout << "default bool values: " << true << " " << false;
cout<< "\nalpha bool values: " << boolalpha<< true << " " << false << endl;


执行这段程序会得到下面的结果:

default bool values: 1 0
alpha bool values: true false

一旦向cout“写入”了boolalpha,我们就改变了cout打印bool值的方式。后续打印bool值的操作都会打印true或false而非1或0。

为了取消cout格式状态的改变,我们使用noboolalpha:

cout << boolalpha //设置cout的内部状态
	<< true 
	<< endl
	<< noboolalpha//将内部状态恢复为默认格式
	<< true << endl;



指定整型值的进制

默认情况下,整型值的输入输出使用十进制。

我们可以使用操纵符hex、oct和dec将其改为十六进制、八进制或是改回十进制:

cout << "default: " << 20 << " " << 1024 << endl;
cout << "octal: " << oct << 20 << " " << 1024 << endl;
cout << "hex: " << hex << 20 << " " << 1024 << endl;
cout << "decimal: " << dec << 20 << " " << 1024 << endl;

当编译并执行这段程序时,会得到如下输出:

注意,类似boolalpha,这些操纵符也会改变格式状态。它们会影响下一个和随后所有的整型输出,直至另一个操纵符又改变了格式为止。

操纵符hex、oct和dec只影响整型运算对象,浮点值的表示形式不受影响

在输出中指出进制

默认情况下,当我们打印出数值时,没有可见的线索指出使用的是几进制。

例如,20是十进制的20还是16的八进制表示?

当我们按十进制打印数值时,打印结果会符合我们的期望。

如果需要打印八进制值或十六进制值,应该使用showbase 操纵符。

当对流应用showbase 操纵符时,会在输出结果中显示进制,它遵循与整型常量中指定进制相同的规范:

  1. 前导0x表示十六进制。
  2. 前导0表示八进制。
  3. 无前导字符串表示十进制。

我们可以使用showbase修改前一个程序:

cout << showbase;// 当打印整型值时显示进制
	cout << "default: " << 20 << "    " << 1024 << endl;
cout << "in octal: " << oct << 20 << "   " << 1024 << endl;
cout << "in hex: " << hex << 20 << "   " << 1024 << endl;
cout << "indecimal: " << dec << 20 << "   " << 1024 << endl;

cout << noshowbase; //恢复流状态


修改后的程序的输出会更清楚地表明底层值到底是什么:

操纵符noshowbase恢复cout的状态,从而不再显示整型值的进制。

默认情况下,十六进制值会以小写打印,前导字符也是小写的x。我们可以通过使用uppercase操纵符来输出大写的X并将十六进制数字a-f以大写输出:

cout << uppercase << showbase << hex
<< "printed in hexadecimal: " << 20 << " " << 1024
<<nouppercase << noshowbase << dec << endl;


这条语句生成如下输出:

printed in hexadecimal; 0X14 0X400


我们使用了操纵符nouppercase、noshowbase和dec来重置流的状态。

控制浮点数格式

我们可以控制浮点数输出三个种格式:

  1. 以多高精度(多少个数字)打印浮点值
  2. 数值是打印为十六进制,定点十进制还是科学记数法形式
  3. 对于没有小数部分的浮点值是否打印小数点

默认情况下,浮点值按六位数字精度打印;

cout << 3.1111111111 << endl;

 

如果浮点值没有小数部分,则不打印小数点。

cout << 3.0000000000 << endl;

根据浮点数的值选择打印成定点十进制或科学记数法形式。

标准库会选择一种可读性更好的格式:非常大和非常小的值打印为科学记数法形式,其他值打印为定点十进制形式。

指定打印精度

默认情况下,精度会控制打印的数字的总数。

当打印时,浮点值按当前精度舍入而非截断。

因此,如果当前精度为四位数字,则3.14159将打印为3.142,如果精度为三位数字,则打印为3,14。
 

我们可以通过调用IO对象的precision成员或使用setprecision操纵符来改变精度。

precision成员是重载的。

  1. 一个版本接受一个int值,将精度设置为此值,并返回旧精度值。
  2. 另一个版本不接受参数,返回当前精度值。

setprecision操纵符接受一个参数,用来设置精度。

操纵符 setprecision和其他接受参数的操纵符都定义在头文件 iomanip中。

下面的程序展示了控制浮点值打印精度的不同方法:

// cout.precision返回当前精度值
	cout << "Precision: " << cout.precision()
		<< ", Value:" << sqrt(2.0) << endl;
	
	// cout.precision(12)将打印精度设置为12住数字
	cout.precision(12);
	
	cout << "Precision:" << cout.precision()
		<< ", Value:" << sqrt (2.0) << endl;
	
	// 另一种设置精度的方法是使用setprecision操纵符
	cout << setprecision(3);
	
	cout << "Precision:" << cout.precision()
		<< ", Value:" << sqrt(2.0) << endl;


编译并执行这段程序,会得到如下输出:

此程序调用标准库sqrt函数,它定义在头文件cmath中。

sqrt函数是重载的,不同版本分别接受一个float、double或long double参数,返回实参的平方根。

定义在iostream的操纵符
注意:*表示默认流状态
boolalpha将true和false输出为字符串
* noboolalpha将true和false输出为1,0
showbase对整型值输出表示进制的前缀
* noshowbase不生成表示进制的前缀
showpoint对浮点值总是显示小数点
*noshowpoint只有当浮点值包含小数部分时才显示小数点
showpos对非负数显示+
*noshowpos对非负数不显示+
uppercase在十六进制值中打印0X,在科学记数法中打印E
*nouppercase在十六进制值中打印0x, 在科学记数法中打印e
*dec整型值显示为十进制
hex整型值显示为十六进制
oct整型值显示为八进制
left在值的右侧添加填充字符
right在值的左侧添加填充字符
lnternal在符号和值之间添加填充字符
fixed浮点值显示为定点十进制
scientific浮点值显示为科学记数法
hexfloat浮点值显示为十六进制(C++11新特性)
defaultfloat重置浮点数格式为十进制(C++11新特性)
unitbuf每次输出操作后都刷新缓冲区
*nounitbuf恢复正常的缓冲区刷新方式
*skipws输入运算符跳过空白符
noskipws输入运算符不跳过空白符
flush刷新ostream缓冲区
ends插入空字符,然后刷新ostream缓冲区
endl插入换行,然后刷新ostream缓冲区

指定浮点数记数法

除非你需要控制浮点数的表示形式(如,按列打印数据或打印表示金额或百分比的数据),否则由标准库选择记数法是最好的方式。

通过使用恰当的操纵符,我们可以强制一个流使用科学记数法、定点十进制或是十六进制记数法。

  • 操纵符scientific改变流的状态来使用科学记数法。
  • 操纵符fixed改变流的状态来使用定点十进制。
  • 在新标准库中,通过使用hexfloat 也可以强制浮点数使用十六进制格式。
  • 新标准库还提供另一个名为defaultfloat的操纵符,它将流恢复到默认状态——根据要打印的值选择记数法。

这些操纵符也会改变流的精度的默认含义。

在执行 scientific、fixed或hexfloat后,精度值控制的是小数点后面的数字位数,而默认情况下精度值指定的是数字的总位数——既包括小数点之后的数字也包括小数点之前的数字。

使用fixed或scientific令我们可以按列打印数值,因为小数点距小数部分的距离是固定的:

cout << "default format: " << 100 * sqrt(2.0) << '\n'
	<< "scientific: " << scientific << 100 * sqrt(2.0) << '\n'
	<< "fixed decimal: " << fixed << 100 * sqrt(2.0) << '\n'
	<< "hexadecimal: " << hexfloat << 100 * sqrt(2.0) << '\n'
	<< "use defaults: " << defaultfloat << 100 * sqrt(2.0);


此程序会生成下面的输出:

默认情况下,十六进制数字和科学记数法中的e都打印成小写形式,我们可以用uppercase操纵符打印这些字母的大写形式。

打印小数点

强制打印小数点:
默认情况下,当一个浮点值的小数部分为0时,不显示小数点。showpoint 操纵符

cout << 10.0 << endl;// 打印10
cout << showpoint << 10.0 //打印10.0000
<< noshowpoint << endl; //恢复小数点的默认格式

操纵符noshowpoint恢复默认行为。下一个输出表达式将有默认行为,即,当浮点值的小数部分为0时不输出小数点。

输出补白

当按列打印数据时,我们常常需要非常精细地控制数据格式。

标准库提供了一些操纵符帮助我们完成所需的控制:

  1. setw指定下一个数字或字符串值的最小空间。
  2. left表示左对齐输出。
  3. right表示右对齐输出,右对齐是默认格式。
  4. internal控制负数的符号的位置,它左对齐符号,右对齐值,用空格填满所有中间空间。
  5. setfill允许指定一个字符代替默认的空格来补白输出。

setw类似endl,不改变输出流的内部状态。它只决定下一个输出的大小。
下面程序展示了如何使用这些操纵符:

	int i = -16;
	double d = 3.14159;
	//补白第一列,使用输出中最小12个位置
		cout << "i:" << setw(12) << i << "next col" << '\n'
		<< "d: " << setw(12) << d << "next col" << '\n';
	
		//补白第一列,左对齐所有列
		cout << left
			<< "i: " << setw(12) << i << "next col" << '\n'
			<< "d: " << setw(12) << d << "next col" << '\n'
			<< right; //恢复正常对齐
		
		//补白第一列,右对齐所有列
		cout << right
		<< "i: " << setw(12) << i << "next col" << '\n'
        << "d: " << setw(12) << d << "next col" << '\n';
		
		//补白第一列,但补在域的内部
	   cout << internal
		<< "i:" << setw(12)<< i << "next col" << '\n'
		   << "d: " << setw(12)<< d << "next col" << '\n';
	
	   //补白第一列,用#作为补白字符 符。
	   cout << setfill('#')
		   << "i: " << setw(12) << 1 << "next col" << '\n'
		   << "d: " << setw(12) << d << "next col" << '\n'
		   << setfill(' ');//恢复正常的补白字符

执行这段程序,会得到下面的输出:

定义在iomanip的操作符
setfill(ch)用ch填充空白
setprecision(n)将浮点精度设置为n
setw(w)读或写值的宽度为w个字符
setbase(b)将整数输出为b进制


控制输入格式

默认情况下,输入运算符会忽略空白符(空格符、制表符、换行符、换纸符和回车符)。

下面的循环

char ch;
while (cin >> ch)
cout << ch;


当给定下面输入序列时

a b         c
d

循环会执行4次,读取字符a到d,跳过中间的空格以及可能的制表符和换行符。

此程序的输出是

abcd

操纵符 noskipws会令输入运算符读取空白符,而不是跳过它们。为了恢复默认行为,我们可以使用skipws操纵符:

cin >> noskipws;// 设置cin 读取空白符
while (cin >> ch)
cout << ch;
cin >> skipws; //将cin恢复到默认状态,从而丢弃空白符


给定与前一个程序相同的输入,此循环会执行7次,从输入中既读取普通字符又读取空白符。此循环的输出为

a b        c
d


 

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

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

相关文章

【进程IO】详细讲解文件描述符fd

文章目录 前言什么叫文件描述符FILE与fd的关系 再次理解文件为什么要有文件的方法列表呢&#xff1f; 进程和struct file的关系再次理解open操作 前言 C语言的关于文件操作的各种函数实际上是对系统调用的封装。那么从进程的角度看&#xff0c;一个文件到底是如何被描述的呢&a…

Postwoman 安装

Postwoman作为Postman的女朋友&#xff0c;具有免费开源、轻量级、快速且美观等特性&#xff0c;是一款非常好用的API调试工具。能帮助程序员节省时间&#xff0c;提升工作效率。 Github地址&#xff1a;GitHub - hoppscotch/hoppscotch: &#x1f47d; Open source API devel…

Qt/QML编程之路:画线及倒车影响(48)

前言: 倒车影像中有一个属性比较实用,那就是倒车线,这条线很明显会在视频图像上叠加显示,或者说在视频上面一个图层画的线。这里有一个画线的Qt示例,用于在一个scene上画一个对角线: #include "mainwindow.h" #include <QApplication> #include <QtW…

ES6 学习(一)-- 基础知识

文章目录 1. 初识 ES62. let 声明变量3. const 声明常量4. 解构赋值 1. 初识 ES6 ECMAScript6.0(以下简称ES6)是JavaScript语言的下一代标准&#xff0c;已经在2015年6月正式发布了。它的目标&#xff0c;是使得」JavaScript语言可以用来编写复杂的大型应用程序&#xff0c;成为…

关系网络c++

题目&#xff1a; 代码&#xff1a; #include<bits/stdc.h>using namespace std;int n,x,y;struct node{int num;//编号 int t;//步数 node(){}node(int sum,int tt){numsum;ttt;} }; int mp[101][101];//图 bool flag[101];//标记 queue<node> q; void bfs() {q…

FLASH的读取与写入

FLASH的写入 结合HAL库所给参数&#xff1a; 查阅具体使用芯片的参考手册。 就不在详细解释&#xff0c;英文自行翻译。具体代码如下&#xff1a; /*FLASH写入程序*/ void WriteFlashTest(uint32_t L, uint32_t addr, uint32_t *Data,int Page) {int i0;/* 1/4解锁FLASH*/HAL…

【Anaconda】Linux下Anaconda安装和虚拟环境配置

Linux下Anaconda安装和虚拟环境配置 一、安装anaconda二、conda虚拟环境管理三、jupyter相关启动部署四、遇到问题 下面介绍整体流程&#xff0c;遇到问题优先看“遇到问题章节”&#xff01; 一、安装anaconda 1.下载anaconda安装包 &#xff08;1&#xff09;可以选择在官网…

文件名目录名或卷标语法不正确:数据恢复策略与预防措施

一、文件名目录名或卷标语法不正确的现象 在日常使用电脑或移动设备时&#xff0c;我们经常会遇到“文件名目录名或卷标语法不正确”的错误提示。这种错误通常发生在尝试访问、修改或删除文件、目录或卷标时&#xff0c;系统会提示无法完成操作&#xff0c;因为文件名、目录名…

JavaScript高级 —— 学习(二)

目录 一、深入对象 &#xff08;一&#xff09;创建对象三种方式 1.利用对象字面量创建 2.利用 new Object() 创建 3.利用构造函数创建 &#xff08;二&#xff09;利用构造函数创建对象 1.构造函数介绍 2.约定 3.实例化执行过程 &#xff08;三&#xff09;实例成员…

动态规划之子序列(一)

300.最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序…

Oracle数据库——子查询五

14.1子查询语法 子查询 (内查询) 在主查询之前一次执行完成。子查询的结果被主查询(外查询)使用 。范例一:谁的工资比 Abel 高? 第一:查询Abel的工资是多少。第二:比较大于这个工资的人数。 注意事项: 子查询要包含在括号内。将子查询放在比较条件的右侧。</

docker部署-RabbitMq

1. 参考 RabbitMq官网 docker官网 2. 拉取镜像 这里改为自己需要的版本即可&#xff0c;下面容器也需要同理修改 docker pull rabbitmq:3.12-management3. 运行容器 docker run \ --namemy-rabbitmq-01 \ -p 5672:5672 \ -p 15672:15672 \ -d \ --restart always \ -…

基于opencv的SVM算法的车牌识别系统设计与实现

基于opencv的SVM算法的车牌识别系统设计与实现 车牌识别技术是智能交通系统中的一项关键技术&#xff0c;它能够自动识别车辆的车牌号码。本文将详细介绍如何使用Python编程语言结合OpenCV库和SVM算法来实现车牌识别系统。 系统架构 车牌识别系统主要包括以下几个模块&…

STM32的简介

内存 一般MCU包含的存储空间有FLASH和RAM,&#xff08;RAM和flash又有片上和片外的区别&#xff0c;片上表示mcu自带的&#xff0c;已经封装在MCU内部的&#xff0c;片外表示外挂的&#xff0c;当项目中需要做一些复杂的应用&#xff0c;会存在资源不足的情况&#xff0c;这时…

【C语言】贪吃蛇【附源码】

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 一、游戏说明&#xff1a; 一个基于C语言链表开发的贪吃蛇游戏&#xff1a; 1. 按方向键上下左右&#xff0c;可以实现蛇移动方向的改变。 2. 短时间长按方向键上下左右其中之一&#xff0c;可实现蛇向该方向的短时间…

flutter生成二维码并截图保存到图库

引入库&#xff1a;flutter_screenutil、image_gallery_saver、qr_flutter弹窗布局 import dart:async; import dart:typed_data; import package/generated/l10n.dart; import package:jade/configs/PathConfig.dart; import package:jade/utils/ImageWaterMarkUtil.dart; im…

三、强一致性介绍

这里写自定义目录标题 三、强一致性介绍3.1 基本理解3.2 DTP模型3.3 落地协议XA3.4 ⼆阶段提交模型3.5 ⼆阶段提交的问题3.6 navicat操作xa 三、强一致性介绍 3.1 基本理解 相关特点 强⼀致性解决⽅案要求在任何时间点&#xff0c;任何时刻查询&#xff0c;参与全局事务的各个…

ROS 2边学边练(7)-- 何为动作(actions)

概念 我们先来看一张动图&#xff0c;下文再围绕这张图对动作作简单阐释和说明。 如上图所示&#xff0c;动作的复杂度比之前提到的几种通信方式&#xff08;主题、服务&#xff09;要大一点&#xff0c;但是几者之间也有着千丝万缕的关系&#xff0c;动作糅合了主题和服务的机…

【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

常用技术-Stream流

目录 Stream流是什么&#xff1f; 认识Stream流 流和集合的区别 Stream流的操作 中间操作 Filter(过滤) Map(转换) Sorted(排序) Distinct(去重) Limit(限制) Skip(跳过) Peek(展示) 终止操作 forEach(循环) Collect(收集) Count(计数) Reduce(聚合) 使用Strea…