C++_IO与文件2-用cout进行输出
C++将输出流看作是字节流,在程序中,很多数据被组织成比字节更大的单位。
例如int类型由16位或者32位的二进制值表示;double值由64位的二进制数据表示;
但是在将字节流发送给屏幕时,希望每个字节表示一个字符。
举个例子:要在屏幕上显示数字-2.34时,需要5个字符(- 2 . 3 4)。
而不是这个值得内部浮点表示发送到屏幕上。
ostream类最重要的任务就是将数值类型转换为以文本形式表示的字符流。
ostream类将数据的内部表示(二进制位模式)转换为由字符字节组成的输出流。
//输出流是字节流,所以要显示的东西必须进行转换,转换成字符编码的字节流;
=====================================================
一、重载的<<运算符
ostream类重新定义了<<运算符,方法是将其重载为输出。该重载运算符能够识别C++中所有的基本类型;
<<运算符的默认含义是按位左移运算符。
例如:cout<<88对应于下面的方法原型:
ostream & operator<<(int);
operator<<(int)函数接受一个int参数,返回一个指向ostream对象的引用,这使得可以将输出连接起来,如下所示:
cout<<"I'm feeling sedimental over "<<boundary<<"\n";
1、输出和指针
ostream类为下面的指针类型提供了插入运算符函数:
const signed char *
const unsigned char *
const char *
void *
C++用指向字符串存储位置的指针来表示字符串。指针的形式可以是char数组名、显式的char指针或用引号括起的字符串。
方法使用字符串中的终止空字符来确定何时停止显示字符。
void * 指的是其他类型的指针,会打印地址的数值表示;如果要获得字符串的地址,则必须将其强制转换为其他类型:
char * amount = "dozen";
cout<<amount; //print the string "dozen"
cout<<(void *)amount; //prints the address of the "dozen" string
2、拼接输出
插入运算符的所有返回为ostream &,也就是说,原型的格式如下:
ostream & operator<<(type);
type是要显示的数据类型,ostream &意味着将返回一个指向ostream对象的引用。
指向哪个对象呢?函数定义指出,引用将指向用于调用该运算符的对象。
换句话说,运算符函数的返回值为调用运算符的对象。
例如:cout<<"potluck"返回的是cout对象。这种特性使得能够通过插入运算符来连接输出。
=====================================================
二、其他ostream方法
ostream类还提供了put()方法和write()方法;前者显示字符、后者用于显示字符串;
可以用类方法表示法来调用put:
cout.put('W'); //display the W character
cout是调用对象的方法、put是类成员函数。该函数也返回一个指向调用对象的引用,因此可以用它拼接输出;
write()方法显示整个字符串,其模板原型如下:
basic_ostream<char T, traits> & write(const char_type* s, streamsize n);
接下来看一个例子:
//write.cpp -- using cout.write()
#include <iostream>
#include <cstring> int main()
{
using std::cout;
using std::endl;
const char * state1 = "Florida";
const char * state2 = "Kansas";
const char * state3 = "Euphoria"; int len = std:strlen(state2);
cout<<"Increasing loop index:\n";
int i;
for (i = ; i<=len; i++)
{
cout.write(state2, i);
cout<<endl;
} //concatenate output
cout<<"Decreasing loop index:\n";
for(i = len; i>; i--)
cout.write(state2, i) <<endl; //exceed string length
cout<<"Exceeding string length:\n";
cout.write(state2, len+)<<endl; return ;
}
程序输出结果:
Increasing loop index:
K
Ka
Kan
Kans
Kansa
Kansas
Decreasing loop index:
Kansas
Kansa
Kans
Kan
Ka
K
另外,write()方法也可以用于数值数据,可以将数字的地址强制转换为char *,然后传递给它:
long val = 560031841;
cout.write((char *) & val, sizeof(long));
这不会将数字转换为相应的字符,而是传输内存中存储的位表示。
例如,4字节的long值(560031841)将作为4个独立的字节被传输。输出设备将把每个字节作为ASCII码进行解释。
因此在屏幕上,560031841将被显示为4个字符的组合,这很可能是乱码。
write()确实为将数值数据存储在文件中提供了一种简洁、准确的方式。
=====================================================
三、刷新输出缓冲区
缓冲区一般为512个字节或者其整数倍。
输出不会立即发送到目标地址,而是被存储在缓冲区中,直到缓冲区填满。
然后程序将刷新(flush)缓冲区,把内容发送出去,并清空缓冲区,以填充新的数据。
但是对于屏幕输出而言,填充缓冲区的重要性低很多。
所幸,在屏幕输出时,程序不必等到缓冲区被填满后才刷新缓冲区;
当换行符发送到缓冲区后,将刷新缓冲区。
cout<<"Hello, good-looking! "<<flush;
cout<<"Wait just a moment, please"<<endl;
控制符flush刷新缓冲区,而控制符endl也刷新缓冲区;
cout<<"Enter a number:";
float num;
cin>>num;
上面这段代码,没有刷新缓冲区,从而显示Enter a number: 字符,那样的话用户也就无法从屏幕感知到这个提示语来进行输入;
=====================================================
四、用cout进行格式化
1、修改显示时使用的计数系统
可以使用:hex(cout) 表示下面的函数调用将cout对象的计数系统格式状态设置为十六进制。
但通常的使用方法为:cout<<hex;
//manip.cpp -- using format manipulators
#include <iostream> int main()
{
using namespace std;
cout<<"Enter an integer: ";
int n;
cin>> n; cout<<"n n*n\n"; //set to hex mode
cout<<hex;
cout<<n << " ";
cout<<n*n<<" (hexdecimal)\n"; //set to octal mode
cout<<oct<<n<<" "<<n*n<<" (octal)\n"; //alternative way to call a manipulator
dec(cout);
cout<<n<<" "<<n*n<<" (decimal)\n"; return ;
}
运行结果为:
Enter an integer:13
n n*n
13 169(decimal)
d a9 (hexadecimal)
15 251(octal)
13 169(decimal)
2、调整字段宽度
先看一个例子:
cout<<'#';
cout.width(12);
cout<<12<<"#"<< 24<<"#\n";
显示结果:
# 12#24#
我们可以发现第一个12被设置为宽度12的字段,12这个字符被放到最右边,这被称为右对齐。
然后字段宽度恢复为默认值。
所以可知width()方法只影响接下来显示的一个项目,然后字段宽度将恢复为默认值。
另外注意一点,C++永远不会截短数据,因此如果试图在宽度为2的字段中打印一个7位值,C++将增宽字段,以容纳该数据。
C/C++的原则是显示所有数据比保持列的整洁更重要。
//width.cpp -- using the width method
#include <iostream> int main()
{
using std :: cout;
int w = cout.width();
cout<<"default field width =" << w <<" : \n";
cout.width();
cout<<"N"<<' : ';
cout.width();
cout<<"N*N"<<":\n"; for (long i = ; i<=; i*=)
{
cout.width();
cout<<i<<' : ';
cout.width();
cout<<i * i<<":\n";
} return ;
}
运行结果:
default field width = 0;
N: N * N:
1: 1:
10: 100:
100: 10000:
空格被插入到值的左侧,用来填充的字符叫做填充字符。右对齐是默认的。
默认字段宽度是0,因为C++总会增长字段,以容纳数据,因此这种值适用于所有数据。
3、填充字符
在默认情况下,cout用空格填充字段中未被使用的部分,可以用fill()成员函数来改变填充字符。
下面的函数调用将填充字符改为星号:
cout.fill(' * ');
注意,与字段宽度不同的是,新的填充字符将一直有效,直到更改它为止;
//fill.cpp -- changing fill character for fields
#include<iostream> int main()
{
using std::cout;
cout.fill('*');
const char * staff[] = {"Waldo Whipsnade", "Wilmarie Wooper"};
long bonus[] = {, }; for (int i = ; i < ; i++)
{
cout<<staff[i]<<" : $";
cout.width();
cout<<bonus[i]<<"\n";
}
return ;
}
运行结果:
Waldo Whipsnade: $****900
Wilmarie Wooper: $***1350
4、设置浮点数的显示精度
浮点数精度的含义取决于输出模式;
在默认模式下,它指的是显示的总位数;
在定点模式和科学模式下,精度指的是小数点后面的位数。
C++的默认精度为6位(但末尾的0将不显示)。
precision()成员函数使得能够选择其他值。
下面的语句将cout的精度设置为2:cout.precision(2)
与fill()类似,新的精度设置将一直有效,直到被重新设置。
//precise.cpp -- setting the precision
#include<iostream> int main()
{
using std::cout;
float price1 = 20.40;
float price2 = 1.9 + 8.0/9.0; cout<<"\"Fiery Friends\" is $"<<price1<<"!\n";
cout<<"\"Fiery Friends\" is $"<<price2<<"!\n"; cout.precision()
cout<<"\"Fiery Friends\" is $"<<price1<<"!\n";
cout<<"\"Fiery Friends\" is $"<<price2<<"!\n"; return ;
}
运行结果:
"Furry Friends" is 20.4!
"Furry Friends" is 2.78889!
"Furry Friends" is 20!
"Furry Friends" is 2.8!
5、打印末尾的0和小数点
对于有些输出,保留末尾的0将更为美观。
但ios_base类提供了一个setf()函数(用于set标记),能够控制多种格式化特性。
这个类还定义了很多常量,可用作该函数的参数;
例如,下面的函数调用使cout显示末尾小数点:
cout.setf(ios_base :: showpoint);
使用默认的浮点格式时,上述语句还将导致末尾的0倍显示出来。
如果使用默认精度(6位)时,cout不会将2.00显示为2,而是将它显示为2.000000。
//precise.cpp -- setting the precision
#include<iostream> int main()
{
using std::cout;
using std::ios_base; float price1 = 20.40;
float price2 = 1.9 + 8.0/9.0; cout.setf(ios_base::showpoints);
cout<<"\"Fiery Friends\" is $"<<price1<<"!\n";
cout<<"\"Fiery Friends\" is $"<<price2<<"!\n"; cout.precision()
cout<<"\"Fiery Friends\" is $"<<price1<<"!\n";
cout<<"\"Fiery Friends\" is $"<<price2<<"!\n"; return ;
}
运行结果:
"Fiery Friends" is $20.4000!
"Fiery Friends" is $2.78889!
"Fiery Friends" is $20.!
"Fiery Friends" is $2.8!
6、再谈setf()
ios_base类定义了代表位值的常量;//由于这些格式常量都在ios_base类中定义。因此使用它们时,必须加上作用域解析运算符;
ios_base : : boolalpha 输入和输出bool值,可以为true或false
ios_base : : showbase 对于输出,使用C++基数前缀(0, 0x)
ios_base : : showpoint 显示末尾的小数点
ios_base : : uppercase 对于16进制输出,使用大写字母,E表示法
ios_base : : showpos 在整数前面加上+
setf()函数由两个原型。第一个为:
fmtflags setf(fmtflags);
fmtflags 是bitmask类型的typedef名,用于存储格式标记。
bitmask类型是用来存储各个位值的类型。
//setf.cpp -- using setf() to control formatting
#include<iostream> int main()
{
using std::cout;
using std::endl;
using std::ios_base; int temperature = ;
cout<<"Today's water temperature: ";
cout.setf(ios_base :: showpos); //show plus signal
cout<< temperature << endl; cout<<"For our programming friends, that's\n";
cout<< std::hex << temperature << endl; //use hex
cout.setf(ios_base::uppercase); //use uppercase in hex
cout.setf(ios_base::showbase); //use 0X prefix for hex
cout<<"or\n";
cout<<temperature<<endl;
cout<<"How "<<true<<"! oops -- How ";
cout.setf(ios_base::boolappha);
cout<<true<<<<"!\n"; return ;
}
第二个setf()原型接受两个参数,并返回以前的设置:
fmtflags setf(fmtflags, fmtflags);
函数的这种重载格式用于设置由多位控制的格式选项。
第一个参数和以前一样,也是一个包含了所需设置的fmtflags值。
第二个参数指出要清除第一个参数中的哪些位。
setf(long, long)的参数
第二个参数 第一个参数 含义
ios_base::basefield ios_base::dec 使用基数10
ios_base::oct 使用基数8
ios_base::hex 使用基数16
ios_base::floatfield ios_base::fixed 使用定点计数法
ios_base::scientific 使用科学计数法
ios_base::adjustfield ios_base::left 使用左对齐
ios_base::right 使用右对齐
ios_base::internal 符号或基数前缀
7、标准控制符
使用setf()不是进行格式化的,对用户最友好的方法;
C++提供了多个控制符,能够调用setf(),并自动提供正确的参数;
一些标准控制符
控制符 调用
boolalpha setf(ios_base::boolalpha)
noboolalpha unsetf(ios_base::noboolalpha)
showbase setf(ios_base::showbase)
noshowbase unsetf(ios_base::showbase)
等等。。。
8、头文件iomanip
使用iomanip工具来设置一些格式值不太方便。
为了简化工作,C++在头文件iomanip中提供了其他一些控制符,它们能够提供前面讨论过的服务,但表示起来更方便。
3个最常用的控制符分别是:setprecision()、setfill()、setw();
它们分别用来设置精度、填充字符、字段宽度;
//iomanio.cpp -- using manipulators from iomanip
#include<iostream>
#include<iomanip>
#include<cmath> int main()
{
using namespace std;
cout<<fixed<<right; cout<<setw()<<"N"<<setw()<<"square root"<<setw()<<"fourth root\n"; double root;
for(int n =; n<=; n+=)
{
root = sqrt(double(n));
cout<<setw()<<setfill('.')<<n<<setfill(' ')
<<setw()<<setprecision()<<root
<<setw()<<setprecision()<<sqrt(root)
<<endl;
} return ;
}
C++_IO与文件2-用cout进行输出的更多相关文章
- C++_IO与文件5-文件的输入与输出
大多数计算机程序都使用了文件.文件本身是存储在某种设备上的一系列字节. 通常,操作系统管理文件,跟踪它们的位置.大小.创建时间等. 除非在操作系统级别上编程,否则通常不必担心这些事情. 真正需要的是将 ...
- C++输入cout与输出cin
输入和输出并不是C++语言中的正式组成成分.C和C++本身都没有为输入和输出提供专门的语句结构.输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的.C++的输出和输入是用" ...
- C++ cout格式化输出(转)
C++ cout格式化输出(转) 这篇文章主要讲解如何在C++中使用cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/pr ...
- 使用std::cout不能输出显示
在测试一行函数时,出现std::cout不能输出的情况,找不到原因. 1. 只好从main函数第一行,开始测试,直到发现一个函数 o_Initer.ekf_filter(filter, ...
- C++ cout格式化输出完全攻略
写算法题的时候突然发现自己忘记基本的C++:cout格式化输出了,赶紧拉出以前的C++学习笔记重新看一看. 部分内容来自教程:C语言中文网(一个很棒的网站) 有时希望按照一定的格式进行输出,如按十六进 ...
- std::cout彩色输出
Mac OS效果 Windows 效果 想写这个东西其实是因为最近要写个命令行的工具,但是有个问题是什么呢?就是传统的那个黑漆漆的窗口看起来很蛋疼.并且完全看不到重点,于是就想起 来这么一个东西.相对 ...
- python筛选特定文件的信息按照格式输出到txt
最近搞数据库,为了把图片文件的信息导入数据库表中,我开始研究python列出图片文件,其中发现因为IE临时文件里有非常多的不需要的图片,就需要筛选掉一些文件. 最终用python输出了所有需要的图片文 ...
- shell获取目录下所有文件夹的名称并输出
获取指定目录/usr/下所有文件夹的名称并输出: shell代码: #!/bin/bash #方法一 dir=$(ls -l /usr/ |awk '/^d/ {print $NF}') for i ...
- Python小代码_15_遍历指定路径下的所有文件和文件夹,并格式化输出文件路径文件名和文件夹名,文件大小,修改时间
遍历指定路径下的所有文件和文件夹,并格式化输出文件路径文件名和文件夹名,文件大小,修改时间 import osimport datetime def print_tree(dir_path): for ...
- (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql
http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...
随机推荐
- linux 压力测试工具 webbench
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 1. wget htt ...
- javascript实现新浪微博MID与地址转换
新浪微博每一条微博都会有一个mid,然后每条微博都有一个独立的地址,例如:http://www.weibo.com//Bw3SXzWzP 规律:地址中的黄色部分是用户id,绿色部分是微博的识别字符串, ...
- C++ 重载操作符- 01 简单的入门
重载操作符的定义 这篇博客是对 重载操作符 的一个概要性的介绍. 重载操作符是C++语言的高级功能,当我们写一个类的时候,可以根据需要学一个重载操作符,如果 不需要,我们可以不写. 大量的操作符都可以 ...
- Hyperledger Fabric开发
打开Hyperledger Fabric在线开发文档:https://hyperledger-fabric.readthedocs.io 建议在Mac或Linux环境下操作,因为文档基本上是按照Mac ...
- Part7-时钟初始化_lesson1
1.概念解析 1.1时钟脉冲信号 1.2时钟脉冲频率 1.3时钟源(提供时钟脉冲信号) a.晶振 b.锁相环PLL 2.时钟体系 2440: 晶振的频率.时钟体系有多少个PLL.这些PLL分别产生了哪 ...
- Part6-点亮指路灯_lesson1
1. 2.GPIO 查阅芯片手册:GPIO 代码: 3.外设基地址初始化 打开arm核手册, 基地址为0x70000000,去搜芯片手册6410, 把这个基地址告诉处理器,通过协处理器的cp15, 转 ...
- eclipse——Maven插件创建java工程
目录结构如下 注意默认JDK为1.5 更改默认JDK 方式一 右键工程 选中JRE1.5 Remove 双击JRE System Library 点击Finish 更改完成 方式二 配置maven ...
- 在IE11(Win8)中检查up6.2配置
1.按F12,打开调试模式 2.打开调试程序选项卡 说明:在调试程序选项卡中可看到IE加载的脚本信息是否正确.因为IE有缓存,导致脚本有时不是最新的. 3.打开脚本,up6.js ...
- .net Stream篇(四)
FileStream 目录: 如何去理解FileStream? FileStream的重要性 FileStream常用构造函数(重要) 非托管参数SafeFileHandle简单介绍 FileStre ...
- spring的介绍
Spring是什么: Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用!!! Spring是一个轻量级的控制反转(Io ...