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进行输出的更多相关文章

  1. C++_IO与文件5-文件的输入与输出

    大多数计算机程序都使用了文件.文件本身是存储在某种设备上的一系列字节. 通常,操作系统管理文件,跟踪它们的位置.大小.创建时间等. 除非在操作系统级别上编程,否则通常不必担心这些事情. 真正需要的是将 ...

  2. C++输入cout与输出cin

    输入和输出并不是C++语言中的正式组成成分.C和C++本身都没有为输入和输出提供专门的语句结构.输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的.C++的输出和输入是用" ...

  3. C++ cout格式化输出(转)

    C++ cout格式化输出(转) 这篇文章主要讲解如何在C++中使用cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/pr ...

  4. 使用std::cout不能输出显示

    在测试一行函数时,出现std::cout不能输出的情况,找不到原因. 1.         只好从main函数第一行,开始测试,直到发现一个函数 o_Initer.ekf_filter(filter, ...

  5. C++ cout格式化输出完全攻略

    写算法题的时候突然发现自己忘记基本的C++:cout格式化输出了,赶紧拉出以前的C++学习笔记重新看一看. 部分内容来自教程:C语言中文网(一个很棒的网站) 有时希望按照一定的格式进行输出,如按十六进 ...

  6. std::cout彩色输出

    Mac OS效果 Windows 效果 想写这个东西其实是因为最近要写个命令行的工具,但是有个问题是什么呢?就是传统的那个黑漆漆的窗口看起来很蛋疼.并且完全看不到重点,于是就想起 来这么一个东西.相对 ...

  7. python筛选特定文件的信息按照格式输出到txt

    最近搞数据库,为了把图片文件的信息导入数据库表中,我开始研究python列出图片文件,其中发现因为IE临时文件里有非常多的不需要的图片,就需要筛选掉一些文件. 最终用python输出了所有需要的图片文 ...

  8. shell获取目录下所有文件夹的名称并输出

    获取指定目录/usr/下所有文件夹的名称并输出: shell代码: #!/bin/bash #方法一 dir=$(ls -l /usr/ |awk '/^d/ {print $NF}') for i ...

  9. Python小代码_15_遍历指定路径下的所有文件和文件夹,并格式化输出文件路径文件名和文件夹名,文件大小,修改时间

    遍历指定路径下的所有文件和文件夹,并格式化输出文件路径文件名和文件夹名,文件大小,修改时间 import osimport datetime def print_tree(dir_path): for ...

  10. (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql

    http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...

随机推荐

  1. git获取网上的项目

    这里是从coding.net上下载项目至本地phpstorm并配置好相关环境. 这里url地址正是项目路径.获取的地方是: 下面那个url直接复制粘贴. 自己选择一个目录,然后clone. 下面便是前 ...

  2. SQL CLR学习

    SQL CLR (SQL Common Language Runtime) 是自 SQL Server 2005 才出现的新功能,它将.NET Framework中的CLR服务注入到 SQL Serv ...

  3. Python3.7安装PyQt5的方法

    一.系统环境 操作系统:Win7 64位 Python Version:3.7 二.安装参考 方法1:pip install PyQt5 方法2:下载whl安装包安装 a.下载网址:https://p ...

  4. Part5核心初始化_lesson3---关闭看门狗

    1.看门狗---作用 2.看门狗工作方式 3.原理图 时钟源来自于PCLK经过分频器,经过选择器,输出到作为看门狗定时器,WTDAT为一个预载值,当它计数为零的时候,还没有给WTDAT赋值,那么它会发 ...

  5. hdu 4741 Save Labman No.004 (异面直线的距离)

    转载学习: #include <cstdio> #include <cstdlib> #include <cstring> #include <algorit ...

  6. Python 面向对象class(2)

    Python 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触过 ...

  7. Git教程--廖雪峰

    Git简介 1.Git是目前世界上最先进的分布式版本控制系统(没有之一) 2.集中式和分布式版本控制系统有什么区别呢?      区别在于历史版本维护的位置:Git本地仓库包含代码库还有历史库,在本地 ...

  8. How Tomcat Works(二十)

    要使用一个web应用程序,必须要将表示该应用程序的Context实例部署到一个host实例中.在tomcat中,context实例可以用war文件的形式来部署,也可以将整个web应用拷贝到Tomcat ...

  9. Ubuntu16.04修改静态ip地址

    https://blog.csdn.net/mdw5521/article/details/79270035

  10. easyui datagrid deleteRow(删除行)的BUG

    有时候想临时保存一些数据,等确定好后在批量一次提交,但EasyUI  datagrid 用的时候添加可以正常,如果从中间删除那行号就全乱了.导致删除的时候有可能删除上一行数据. function ad ...