C++输入输出流 cin/cout 及格式化输出简介
C++ 可通过流的概念进行程序与外界环境( 用户、文件等 )之间的交互。流是一种将数据自源( source )推送至目的地( destination )的管道。在 C++ 中,与标准输入/输出相关的流可通过头文件 <iostream> 使用,与文件读写相关的流可以通过头文件 <fstream> 使用。这里即主要介绍 C++ 中与标准输入/输出相关的流 cin / cout .
头文件与命令空间
引入头文件
在 C++ 中,想要使用相应的标准库功能,需要包括对应的库的头文件。故而想要使用标准输入/输出,程序中首先需要包含对应的头文件 iostream.
#include <iostream> //包含对应的头文件
iostream 头文件中主要包括 4 个流对象的声明( 注意是对象而不是类型,实际是这些流对象的 extern 声明 )。在包含 iosteam 头文件后,用户可以直接使用标准输入流 cin、标准输出流 cout 、标准错误流 cerr 和标准日志流 clog. 其中 cin 为输入流对象,后三个为输出流对象。上述流对象在标准库中已经定义,故而后续用户在程序中可以直接使用上述对象进行操作而不需要另行定义。这里主要介绍的是标准输入/输出流( 即 cin / cout )的使用。
引入名字
C++ 中使用命名空间的概念加强程序的作用域和命名管理能力,标准库定义的所有名字都在命令空间 std 中( 只有声明命名空间后才能使用 )。若在程序中直接使用 cin 和 cout 进行输入输出操作而不包含对应的命名空间声明,在编译过程中会因无法找到对应的名字而报错。C++ 中使用 cin / cout 时有以下几种方法。
1.在程序开始处( 头文件之后 )直接引入整个命名空间中的名字。所有 C++ 标准库的名字均位于命名空间 std 中,包括 cin 和 cout 。如下所示的语句即导入了命名空间 std 中的所有名字。则后续程序中可以直接使用命名空间 std 中所定义的名字,包括可以直接使用 cin 和 cout 进行输入/输出操作。直接导入整个命名空间中的所有名字书写起来十分简单,但在较复杂的程序中可能需要解决由于所有命名空间中名字的引入所产生的与其他已有名字的冲突问题。这种方法推荐在较为简单的程序设计/练习中使用。
using namespace std; //使得命令空间 std 中的名字均可直接使用
2.在程序开始处( 头文件之后 )一次引入一个命名空间中的一个成员。通过 using 关键字 + 命名空间 :: 成员名字 的方式一次引入一个指定命名空间中的成员。若后续程序中需要同时使用标准输入和输出流,则需要分别引入这两个名字,如下所示。注意在这种方法中,每引入一个名字,均需要一条单独的语句。
using std::cin; //引入命名空间 std 中的名字 cin,后续可以直接使用名字 cin 进行操作
using std::cout; //引入命名空间 std 中的名字 cout,后续可以直接使用名字 cout 进行操作
3.直接在程序中通过 命名空间 :: 成员名字 的方式去引用某个名字,而不需做额外的声明。如在程序中需要使用 cin,则可以直接使用如下语句。其缺点在于程序中每一次使用 cin ,均要通过 std::cin 的方式进行使用。
std::cin >> value ; //直接通过 命名空间::名字 的方式使用 cin
后续的示例中,均默认已经导入了对应的头文件并使用上述方法2的方式引入了对应的名字,后续不再重复。
基本输入/输出操作
输入/输出运算符
与流相关的输入输出操作通过操作符 "<<" 和 ">>" 完成。
>> : 输入运算符,其左侧应该为输出流( ostream )类型的对象,右侧为需读取的数据,运算符的操作结果( 可理解为语句的返回值 )为左侧的流对象;
<< : 输出运算符,其左侧应该为输入流( istream )类型的对象,右侧为需输出的数据,运算符的操作结果( 可理解为语句的返回值 )为左侧的流对象;
这里需要说明的是,cin 实际上即为 istream 类型的对象,而 cout 即为 ostream 类型的对象。故而 cin 和 cout 可以直接通过上述的输入/输出运算符进行输入/输出操作。cin/cout 的类型关系可以参考这里。
基本运算
通过输入/输出运算符可以进行基本的输入/输出操作,cin / cout 可自动对 C++ 的基本数据类型如数值类型、字符(串)类型进行支持。下列示例即读入一个整型数据,并将其输出。这里注意,代码中的 endl 并不代表实际的数据,而是起到结束该行( 从而换行 )的作用.
int value ; //存放数据的整形
cin >> value ; //从标准输入读取一个整型,并存储在变量 value 中,输入使用 cin 和 >> 运算符
cout << value << endl ; //将 value 的值输出至标准输出,并结束该行,输出使用 cout 对象和 << 运算符
输入/输出运算符也可以进行连续的输入/输出操作。以输入为例,可通过如下语句读取两个输入整型。
int a, b;
cin >> a >> b; //将读取的数据分别存储在 a 和 b 中
这里主要解释第二行的语句。语句由左向右执行,首先执行 "cin >> a" 部分,读取一个整型数据至变量 a 中,由于 ">>" 运算符的返回值为其左侧对象,即返回 cin ,则后续继续执行的语句等价于 "cin >> b",即读取另外一个整型数据至变量 b 中。
使用 cin 读取键盘输入时,其与 c 中实现的 scanf 类似,一般采用行缓冲的方式处理用户数据。当缓冲区 stdin 中存在数据时,cin 直接从 stdin 中读取数据,而当 stdin 中没有数据时,cin 即等待用户的输入。具体而言,用户的键盘的输入首先被存储在临时缓冲区中,当临时缓冲区满或用户输入回车键,则上述输入数据被缓冲至 stdin 中,cin 即可从 stdin 中获取数据,未被读取的数据会一直存放在该缓冲区中,在下一次 cin 读取时,会直接从上述非空的 stdin 中读取数据,而不再等待用户输入。当 stdin 为空时,cin 会再次等待用户的输入。
另注,cin 在读取目标数据时,会自动略过有效数据之前的空白字符( 回车、换行、制表符等 )。如用户输入为 " 32",通过 cin 读取到的整形为 32.在读取有效数据时,遇到第一个空白字符即认为当前读取的数据结束,如用户输入"32 ",cin 在读取数据 32 后遇到空格,即认为当前输入的整型数据为 32 。
输入错误处理
在类型匹配的情况下,cin 可通过 ">>" 运算符方便地针对不同的数据类型进行输入操作。如上面的例子中,cin 可以将用户输入的整型数据提取到整型变量 value 中。但当出现 a)数据类型不匹配,b)数据读取至结束位置( 用户输入的结束标记时 ) ,cin 会进入错误的状态。如程序中需要通过语句 cin >> value 将数据读取至整型的变量 value 中,而用户实际输入为一个字符串"abc"时,会产生输入错误。具体而言,会有以下几个问题:
1.使用的输入流 cin 会进入错误状态,流的错误状态可以通过 fail() 方法进行检测。当流进入错误状态时,cin.fail() 返回值为 true .
int value;
cin >> value;
if( !cin.fail() ) //确保读取过程正确,再进行输出
{
cout << value << endl; //output
}
流对象本身也可以用作判断条件,当 cin 成功读取数据时,cin 在判断条件中表现为 true,当 cin 进入错误状态时,其在判断条件中表现为 false .例如,通过如下语句读取用户输入的任意多的数据.只要用户输入合法的整型值,cin 即可正确读取,>> 运算符返回的是其左侧的对象,也就是 cin .成功读取的 cin 在条件判断中的表现为 true,则可以进一步进行处理操作。当用户在终端中输入结束标记时( Linux 下的 Ctrl + d , Windows 下的 Ctrl + z 加回车 ),cin 即进入错误状态,从而使得 while 循环的条件为假,程序不再进行后续操作。
int value;
while( cin >> value )
{
//process value
}
2.处于错误状态的流对象( 这里即 cin )会使得后续使用该流的语句的结果均无法预料。除对流对象状态的检测外,若后续程序流程中仍然使用了同一个流对象,则程序首先需对错误进行处理( 报告错误、清空缓冲区数据等 ),之后通过 clear 方法将流对象恢复至正常状态,后续即可继续使用。注意 clear 方法并不会清除缓冲区中的数据。如例子中,由于 "abc" 和整型不匹配的错误所造成的问题,字符串"abc"仍留在缓冲区中,若不做任何处理直接通过 cin.clear() 恢复流的状态,后续通过 cin 的读取会直接读取缓冲区中的 "abc" ,进而影响后续的程序执行流程.
格式化输出
与 C 语言提供的输出函数类似,除基本的数据交互功能外,C++ 的输出流还可通过输入/输出操作符( input/output manipulators )来满足数据输出的格式化需求。
结束当前行——endl
默认情况下,将数据输出时并不会自动换行,需要显式的通过 endl 来进行数据的换行。输出 endl 的效果是结束当前行( 也就是换行),并将设备管理的缓冲区中的内容刷新到设备中( 也就是保证数据真正的输出了,而不是停留在内存等缓冲位置中 )。 另外转义字符 '\n' 也可以满足换行的功能。下列代码均在数据输出后进行了换行,不同的是 endl 会保证将数据刷新到目的设备中( 而不是暂存在缓冲区中 )。
cout << "hello world!" << '\n';
cout << "hello world!" << endl;
设置输出间距( 宽度 )——setw
需包含头文件 <iomanip> . setw 函数以一个整型( int )作为参数,设置进行输出时的流的宽度。默认情况下,使用流进行输出操作时流的宽度为0,亦即保持数据的原始长度。使用 setw( n ) 设置流宽度后,输出的数据至少会占有 setw( n ) 所设置的字节数 n。具体而言,当数据宽度不足 n 时,即通过填充( 默认使用空格填充 )使其宽度保持为 n 。注意,setw 函数的设置在调用 "<<" 或 ">>" 运算符后即恢复默认,也就是仅在其设置后的下一次输出操作中起作用。( setw 可设置输出流进行输出的数据的最小字节宽度,也可在输入流中设置进行输入的最大字节宽度 )
int value = ;
cout << setfill( 'c' ) << setw( ) << value << endl; //输出的 45 将占用 10 个字节的宽度,使用 'c' 填充 => "cccccccc32"
设置默认填充字符——setfill
需包含头文件 <iomanip> . setfill 函数仅用于输出流中,其使用一个字符作为参数,并将其设置为输出流的填充字符( 默认为空格 )。在调用了 setfill 函数后,后续所有需要进行填充的场合( 如使用 setw 设置了输出的最小字节宽度 )均使用设置的字符进行填充。与 setw 函数不同的是,setfill 在设置完成后一直有效,除非重新设置。
cout << setfill( '-' ) << setw( ) << "" << endl; //输出空字符串,由于输出的最小宽度经过 setw 设置为 10 ,故输出连续十个 ‘-’ => "----------"
cout << setfill( ' ' ) //恢复填充为空格
设置填充字符位置——left / right
设置经过填充后,原始数据的位置。设置为 left / right 时,原始数据位于填充后数据的左/右侧( 默认输出为 right ).
int value = ;
cout << left << setfill( 'c' ) << setw( ) << value << endl; //输出宽度为 10,数据位于输出的左侧 => "32cccccccc"
参考 :
Input/Output —— cppreference.com
Input/output manipulators —— cppreference.com
C++输入输出流 cin/cout 及格式化输出简介的更多相关文章
- C++学习 cout的格式化输出
cout的格式化输出 1.常用: ①double 输出到小数点后n位:(保留精度 n位) #include <iostream> #include <iomanip> usin ...
- -2.输入加速(cin,cout)
+ ios::sync_with_stdio(false);//加速几百毫秒 cin.tie(0); // 接近scanf cout.tie(0);
- C++ STL——输入输出流
[TOC] 注:原创不易,转载请务必注明原作者和出处,感谢支持! 注:内容来自某培训课程,不一定完全正确! 一 缓冲区 (1)标准输入:从键盘输入数据到程序(input) (2)标准输出:程序数据输出 ...
- C++ cout格式化输出(转)
C++ cout格式化输出(转) 这篇文章主要讲解如何在C++中使用cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/pr ...
- C++ cout格式化输出完全攻略
写算法题的时候突然发现自己忘记基本的C++:cout格式化输出了,赶紧拉出以前的C++学习笔记重新看一看. 部分内容来自教程:C语言中文网(一个很棒的网站) 有时希望按照一定的格式进行输出,如按十六进 ...
- python学习笔记(基础二:注释、用户输入、格式化输出)
注释 单行:# 多行:上下各用3个连续单引号或双引号 3个引号除了多行注释,还可以打印多行 举例: msg = ''' name = "Alex Li" name2 = name ...
- cout 格式化输出
一直习惯于C语言的printf函数来打印,突然有一天要用cout来打印,发现有点不适应. 原来cout也是有格式化输出的. 首先要引入头文件 #include<iostream> // 在 ...
- python学习道路(day1note)(变量,注释,用户输入,格式化输出,if,while,for循环并扩展练习)
python是一门动态解释性的强类型定义语言,其应用范围非常之广 1:进入python语言 #!/usr/bin/env python #_*_coding:utf-8_*_ print(" ...
- [转载] c++ cout 格式化输出浮点数、整数及格方法
C语言里可以用printf(),%f来实现浮点数的格式化输出,用cout呢...? 下面的方法是在网上找到的,如果各位有别的办法谢谢留下... iomanip.h是I/O流控制头文件,就像C里面的格式 ...
随机推荐
- 【神经网络与深度学习】DCGAN及其TensorFlow源码
上一节我们提到G和D由多层感知机定义.深度学习中对图像处理应用最好的模型是CNN,那么如何把CNN与GAN结合?DCGAN是这方面最好的尝试之一.源码:https://github.com/Newmu ...
- 建造(Builder)模式
建造模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象. 摘自EffectiveJava:当构造方法参数过多时使用建造者模式. 产品的内部表象 ...
- Feign实现自定义错误处理
关键操作 实现ErrorDecoder接口 问题和背景 最近项目中在大量使用Feign和OkHttp作为http客户端使用,开发效率得到显著的提升.但也面临一些问题,比如每个下游系统的异常返回方式不同 ...
- 解决新版本R3.6.0不能加载devtools包问题
首先是看到下面这个文章想试着练习一下,结果第一步就卡住了,无法加载devtools包,繁体字都冒出来了......汗!(没有截图,但过程痛苦不堪~) https://www.sohu.com/a/12 ...
- IDEA——配置代码检测
一.问题 利用idea安装代码检查机制,完成bug的检测.内容分为两部分:1.完成工具的安装2.完成代码的审核 二.解决1.工具的安装由于idea这个ide具有的性质,所以具有两种不同的安装方式.1) ...
- Java学习:数组的使用和注意事项
数组 数组的概念:是一种容器,可以同时存放多个数据值 数组的特点: 数组是一种引用数据类型 数组当中的多个数据,类型必须统一 数组的长度在程序运行期间不可以改变 数组的初始化:在内存当中创建一个数组, ...
- Oracle查询所有字段另加两个拼接字段的操作
Oracle查询所有字段,再加两个字段拼接, select a.*,(SNO||SNAME) from TEST_STUDENT a; 同理,查询所有字段,其中两个字段求和:(SNO和SAGE都是NU ...
- 在Eclipse中使用Beyond Compare做为比较工具
1.下载org.eclipse.externaltools-Update-0.8.9.v201003051612.zip插件包 接下来,要下载Beyond Compare的插件,http://beyo ...
- JAVA8的java.util.function包 @FunctionalInterface
1 函数式接口java.util.function https://www.cnblogs.com/CobwebSong/p/9593313.html 2 JAVA8的java.util.functi ...
- 排序算法Java代码实现(一)—— 选择排序
以下几篇随笔都是记录的我实现八大排序的代码,主要是贴出代码吧,讲解什么的都没有,主要是为了方便我自己复习,哈哈,如果看不明白,也不要说我坑哦! 本片分为两部分代码: 常用方法封装 排序算法里需要频繁使 ...