C++ IO首先建立在为Unix环境开发的原始库函数上;ANSI C正式承认这个库时,将其称为标准输入/输出包;
IO相关类定义在头文件iostream和fstream,这些类不是正式语言定义的组成部分,cin,istream都不是关键字。
(1)流简介:
(2)管理输入:
(3)管理输出:
(4)缓冲区简介
缓冲区就是一块存储空间,它是为了匹配程序处理速度和外设处理速度;比如程序一次处理1byte,但是磁盘一次读取512bytes;又或者程序一次处理1byte,可以1byte地从磁盘读取,但是由于硬件读取一次数据复杂且操作慢,因此使用缓冲区可以加快程序处理速度。
flushing the buffer:刷新缓冲区就是清空缓冲区地内容以备下次使用。
修改标准输入和标准输出关联的工具。(比如输出到文件,而不是显示器)
当创建cout类时会自动打开一个流,创建一个缓冲区,并将流和缓冲区联系起来
C++在输出时将数据看作字符流。
各种char字符可以直接显示,但是对于各种数据包括int,long,float,double就无法直接解析为字符了
C++中将使用cout的<<称为插入操作符,意味着将右侧的信息流传递到左侧(因为<<是左移运算符,相当于给了个方便记忆的解释)
因此cout类重载了<<操作符,重载了适合多种数据类型的<<操作符成员函数,将数据类型转换为文本形式的字符流;以下数据类型皆被重载:unsigned char、signed char、char、short、unsigned short、int、unsigned int、long、unsigned long、long long (C++11)、unsigned long long (C++11)、float、double、long double
重载原型为:ostream & operator<<(type);
ostream为const signed char *、const unsigned char *、const char *、void *重载了<<操作符,因此,可以使用cout<<输出显示字符串;这个方法使用\0来判断是否停止显示字符。
如果要显示字符串的地址,由于传递指针输出了整个字符串,因此将其强制转换为void *类型可以显示字符串的地址。
举例:
cout << "输出与指针*********************************************************************" << endl;
int eggs = 12;
const char* amount = "dozen";
cout << &eggs; // prints address of eggs variable
cout << amount; // prints the string "dozen"
cout << (void*)amount<<endl; // prints the address of the "dozen" string
运行结果:
输出与指针*********************************************************************
008FFD9Cdozen0041BC80
ostream & operator<<(type);
根据上述函数原型可以知道,返回值是ostream类型的引用,这就可以使得cout<<实现输出连接
cout << “We have " << count << " unhatched chickens.\n”;
举例:
cout << "输出连接***********************************************************************" << endl;
cout << "We have " << eggs << " unhatched chickens.\n";
运行结果:
输出连接***********************************************************************
We have 12 unhatched chickens.
原型:
template <class type>//type为char或wchar_t
ostream & put(type);
当传递的实参不是char或wchar_t时,会执行自动转换将其转换为char或wchar_t类型,这个很适合早期发行版本2.0,在那些版本中,使用int值表示字符。
cout << 'W';//在早期发行版本2.0,这个会输出W的ASCII码,当前版本会输出字符W
cout.put('W');//在早期发行版本2.0,这个会输出W字符,当前版本会输出W字符
一些编译器为char, unsigned char, and signed char重载了put(),但是这会给自动转换int实参带来歧义,因为int可以转换为其中任何一个。
举例:
cout << "cout.put()*********************************************************************" << endl;
cout.put('W'); // display the W character
cout.put('I').put('t'); // displaying It with two put() calls
cout.put(65); // display the A character
cout.put(66.3); // display the B character
cout.put(65); // display the A character
cout.put(66.3) << endl; // display the B character
运行结果:
cout.put()*********************************************************************
WItABAB
原型:
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
第一个参数提供了需要显示的字符串地址,第二个参数指示了显示几个字符;cout.write()成员函数不会判断字符串是否结尾,指定显示几个字符就显示几个,即使它过界了。返回值为cout,说明支持输出连接
针对write非char类型的数据,程序根据8bit存储空间的内容来决定显示为哪个字符,超过8bit的数据类型,则分为几个字符显示。
举例:
cout << "cout.write()*******************************************************************" << 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 = 1; i <= len; i++)
{
cout.write(state2, i);
cout << endl;
}
// concatenate output
cout << "Decreasing loop index:\n";
for (i = len; i > 0; i--)
cout.write(state2, i) << endl;
// exceed string length
cout << "Exceeding string length:\n";
cout.write(state2, len + 5) << endl;
long val = 560031841;
cout.write((char*)&val, sizeof(long))<<endl;
运行结果:
cout.write()*******************************************************************
Increasing loop index:
K
Ka
Kan
Kans
Kansa
Kansas
Decreasing loop index:
Kansas
Kansa
Kans
Kan
Ka
K
Exceeding string length:
KansasEup
aha!
缓存一般是512bytes或者其倍数。 举例: 运行结果: (1)char:占用一个字符的位置 举例: 运行结果: ios_base是ios的基类,ios是一个模板类包含了char和wchar_t的专门化,ios_base包含了非模板的特征 举例: 运行结果: 两种原型: 举例: 运行结果: 默认情况下,将空格字符作为填充字符,可以使用fill()函数更改填充字符。 这对于打印支票很有用,因为这样就不能随意在填充部分随意加数字了。 举例: 运行结果: 默认情况下是显示六位有效数字;可以使用precision()设置精度; 举例: 运行结果: ios_base类中有一个受保护的数据成员,这个数据成员的各位控制着格式化的各个方面(这些位置1则打开该模式); setf原型1:形参为1个 self原型2:形参为两个 应用: 可以传递的参数为以下表格: 注意事项:在C++标准中,混合模式和科学计数法模式都有两个特征: 取消设置: 函数原型为: 举例: 运行结果: 实质上就是各种函数,可以直接使用cout<<流操纵符;即可设置相应的位置。 举例: iomanip头文件为precision() fill() width()准备的流操纵符(更方便使用) 举例: 运行结果:
在显示器输出时,三种情况可清空缓存
1.发送一个新行给缓冲器,endl
2.当输入挂起时
3.使用工具 flush()函数
使用方法:flush(cout);或者cout<cout << "清空输出缓存*******************************************************************" << endl;
cout << "Enter a number: ";
float num;
cin >> num;
cout << "Hello, good-looking! " << flush;
cout << "Wait just a moment, please." << endl;
清空输出缓存*******************************************************************
Enter a number: 99
Hello, good-looking! Wait just a moment, please.
2.7 cout针对不同数据类型的输出格式
(2)整形:占用足够显示它的字符位置数(十位数占用两个字符位置,个位数占用一个字符位置),如果是负数要在前面加一个-号
(3)字符串:占用字符串长度的字符位置数
(4)浮点型:显示的有效位数为6位,尾部的0不显示
注意事项:不同地区可能有不同的格式:比如欧洲的小数点用,表示而不是.表示;数据之间需要手动添加间隔符将两个数字分开,否则会连续显示。cout << "cout针对不同数据类型的输出格式***************************************************" << endl;
cout << "12345678901234567890\n";
char ch = 'K';
int t = 273;
cout << ch << ":\n";
cout << t << ":\n";
cout << -t << ":\n";
double f1 = 1.200;
cout << f1 << ":\n";
cout << (f1 + 1.0 / 9.0) << ":\n";
double f2 = 1.67E2;
cout << f2 << ":\n";
f2 += 1.0 / 9.0;
cout << f2 << ":\n";
cout << (f2 * 1.0e4) << ":\n";
double f3 = 2.3e-4;
cout << f3 << ":\n";
cout << f3 / 10 << ":\n";
cout针对不同数据类型的输出格式***************************************************
12345678901234567890
K:
273:
-273:
1.2:
1.31111:
167:
167.111:
1.67111e+06:
0.00023:
2.3e-05:
2.8 cout以不同进制显示整数
流操纵符dec,hex,oct:ios_base中有工具dec,hex,oct使得数据以不同进制显示;dec(),hex(),oct()是函数,并且重载了<<操作符;这几个工具在std命名空间中
注意事项:
1.无法使用二进制显示;
2.在更改进制显示方式之后,系统默认后面使用该方式显示数据,如果有显示为其他进制形式的需要重新设置进制显示方式
三种格式:
hex(cout);
cout<
显示bool类型:
cout.setf(ios_base::boolalpha);//true显示位true,false显示位falsecout << "cout以不同进制显示整数***********************************************************" << endl;
/*cout以不同进制显示整数*/
i = 90;
cout << "以十进制显示i:" << dec << i << endl;//以十进制显示
cout << "以八进制显示i:" << oct << i << endl;//以八进制显示
cout << "以16进制显示i:" << hex << i << endl;//以16进制显示
//如需更改为十进制显示方式,则可以使用以下方式
cout.setf(ios_base::dec);
cout << "以十进制显示i:" << i << endl << endl;
/*bool数据类型显示*/
cout << "bool数据类型显示" << endl;
bool is_true = true;
cout.setf(ios_base::boolalpha);//可以显示为true或false
cout << "is_true = " << is_true << endl;
is_true = false;
cout << "is_true = " << is_true << endl << endl;
cout以不同进制显示整数***********************************************************
以十进制显示i:90
以八进制显示i:132
以16进制显示i:5a
以十进制显示i:90
bool数据类型显示
is_true = true
is_true = false
2.9 设置当前字段宽度cout.width()
int width();//返回当前字段宽度
int width(int i);//将字段宽度设置为i,并且返回之前的字符宽度,以备返回上一步的字段宽度。
使用格式:
cout<
1.width()只影响下一次的cout,然后字段宽度将恢复默认值
2.显示为右对齐,多余的字段位置将使用空格填充
3.C++不会截断数据,因此如果视图在宽度为2个字段中打印一个7位数,C++将增宽字段,以容纳该数据。cout << "width()***************************************************************************" << endl;
int w = cout.width(30);
cout << "default field width = " << w << ":\n";
cout.width(5);
cout << "N" << ':';
cout.width(8);
cout << "N * N" << ":\n";
for (long i = 1; i <= 100; i *= 10)
{
cout.width(5);
cout << i << ':';
cout.width(8);
cout << i * i << ":\n";
}
cout.width(5);
cout << 9.888889999 << endl;//将不会截断
width()***************************************************************************
default field width = 0:
N: N * N:
1: 1:
10: 100:
100: 10000:
9.88889
2.10 更改填充字符cout.fill()
cout.fill('*');
注意事项:在更改填充字符之后,系统默认后面使用该填充字符,如果有显示为其他填充字符的需要重新设置填充字符cout << "更改填充字符****************************************************************************" << endl;
cout.fill('*');
const char* staff[2] = { "Waldo Whipsnade", "Wilmarie Wooper" };
long bonus[2] = { 900, 1350 };
for (int i = 0; i < 2; i++)
{
cout << staff[i] << ": $";
cout.width(7);
cout << bonus[i] << "\n";
}
更改填充字符****************************************************************************
Waldo Whipsnade: $****900
Wilmarie Wooper: $***1350
2.11 更改浮点数显示精度cout.precision()
cout.precision(2);
注意事项:
1.在设置精度后,后面会一直使用这个精度直到下一次更改精度
2.当有效数字位数小于整数有效数字位数时,使用科学计数法显示cout << "设置小数显示精度:precision()***********************************************************" << endl;
double j = 3333.1415926;
/*设置显示有效数字位数*/
cout << "默认情况显示(6位):" << j << endl;//输出浮点数时,默认情况下保留六位有效数字
cout.precision(9);//可以使用cout.precision(n)设置输出浮点数时保留n位有效数字
cout << "设置有效数字位数为9位时:" << j << endl;
cout.precision(3);//当有效数字位数小于整数有效数字位数时,使用科学计数法显示
cout << "设置有效数字位数为3位时:" << j << endl << endl;
设置小数显示精度:precision()***********************************************************
默认情况显示(6位):3333.14
设置有效数字位数为9位时:3333.14159
设置有效数字位数为3位时:3.33e+03
2.12 ios_base成员函数setf()的使用
ios_base类中定义了各种常量指向该受保护数据成员的各个类,称为bitmask类型,每个bitmask位都是可单独访问的并且有自己的含义,iostream软件包使用bitmask来存储状态信息
ios_base::boolalpha
true显示为true,false显示为false
ios_base::showbase
输出时使用前缀 OX,ox(进制缩写)等等
ios_base::showpoint
输出小数点和无效0(就尾巴上的0)
ios_base::uppercase
输出16进制时使用大写,输出使用科学计数法时使用大写E
ios_base::showpos
在正数前面加+号,只适用于十进制,其他进制不用显示+号
fmtflags setf(fmtflags);//输入参数为bitmask类型,指出要设置哪一位;返回值为bitmask类型,指出以前的设置
fmtflags setf(fmtflags , fmtflags );//第一个参数为bitmask类型,指出要设置哪一位;第二个参数为bitmask类型,指出要清除第一个参数中的哪些位;返回值为bitmask类型,指出以前的设置
cout.setf(ios_base::hex, ios_base::basefield);//取消ios_base::basefield原来的设置,将其设置为hex
Second Argument
First Argument
Meaning
ios_base::basefield
ios_base::dec
使用十进制
ios_base::oct
使用八进制
ios_base::hex
使用十六进制
ios_base::floatfield
ios_base::fixed
使用混合显示模式
ios_base::scientific
使用科学计数法显示模式
ios_base::adjustfield
ios_base::left
左对齐
ios_base::right
右对齐
ios_base::internal
符号左对齐,数字右对齐
1.精度是指小数点后面的数据位数
2.尾部的0自动显示
恢复旧格式:ios_base::fmtflags old = cout.setf(ios::left, ios::adjustfield);
cout.setf(old, ios::adjustfield);
方法1:保存旧设置,然后重置设置
方法2:unsetf()void unsetf(fmtflags mask);//mask是一个位,如果setf()将mask位设置为1,则unsetf()将mask位设置为0
cout << "ios_base成员函数setf()的使用***********************************************************"<< endl;
cout << "一个参数的setf():********************************" << endl;
int temperature = 63;
cout << "Today's water temperature: ";
cout.setf(ios_base::showpos); // show plus sign
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::boolalpha);
cout << true << "!\n";
cout << "两个参数的setf():*********************************" << endl;
cout << dec;
// use left justification, show the plus sign, show trailing
// zeros, with a precision of 3
cout.fill(' ');
cout.setf(ios_base::left, ios_base::adjustfield);
cout.setf(ios_base::showpos);
cout.setf(ios_base::showpoint);
cout.precision(3);
// use e-notation and save old format setting
ios_base::fmtflags old = cout.setf(ios_base::scientific,
ios_base::floatfield);
cout << "Left Justification:\n";
long n;
for (n = 1; n <= 41; n += 10)
{
cout.width(4);
cout << n << "|";
cout.width(12);
cout << sqrt(double(n)) << "|\n";
}
// change to internal justification
cout.setf(ios_base::internal, ios_base::adjustfield);
// restore default floating-point display style
cout.setf(old, ios_base::floatfield);
cout << "Internal Justification:\n";
for (n = 1; n <= 41; n += 10)
{
cout.width(4);
cout << n << "|";
cout.width(12);
cout << sqrt(double(n)) << "|\n";
}
// use right justification, fixed notation
cout.setf(ios_base::right, ios_base::adjustfield);
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << "Right Justification:\n";
for (n = 1; n <= 41; n += 10)
{
cout.width(4);
cout << n << "|";
cout.width(12);
cout << sqrt(double(n)) << "|\n";
}
cout << "unsetf():*********************************" << endl;
cout << boolalpha;
cout << true << endl;
cout.unsetf(ios_base::boolalpha); // display 1, 0
cout << true << endl;
//将小数显示模式设置为默认状态,默认状态即为混合模式和科学计数法模式都未设置
cout.setf(0, ios_base::floatfield); // go to default mode
ios_base成员函数setf()的使用***********************************************************
一个参数的setf():********************************
Today's water temperature: +63
For our programming friends, that's
3f
or
0X3F
How true! oops -- How true!
两个参数的setf():*********************************
Left Justification:
+1 |+1.000E+00 |
+11 |+3.317E+00 |
+21 |+4.583E+00 |
+31 |+5.568E+00 |
+41 |+6.403E+00 |
Internal Justification:
+ 1|+ 1.00|
+ 11|+ 3.32|
+ 21|+ 4.58|
+ 31|+ 5.57|
+ 41|+ 6.40|
Right Justification:
+1| +1.000|
+11| +3.317|
+21| +4.583|
+31| +5.568|
+41| +6.403|
unsetf():*********************************
true
+1
2.13 标准流操纵符
Manipulator
Calls
boolalpha
setf(ios_base::boolalpha)
noboolalpha
unset(ios_base::noboolalpha)
showbase
setf(ios_base::showbase)
noshowbase
unsetf(ios_base::showbase)
showpoint
setf(ios_base::showpoint)
noshowpoint
unsetf(ios_base::showpoint)
showpos
setf(ios_base::showpos)
noshowpos
unsetf(ios_base::showpos)
uppercase
setf(ios_base::uppercase)
nouppercase
unsetf(ios_base::uppercase)
internal
setf(ios_base::internal,ios_base::adjustfield)
left
setf(ios_base::left,ios_base::adjustfield)
right
setf(ios_base::right,ios_base::adjustfield)
dec
setf(ios_base::dec, ios_base::basefield)
hex
setf(ios_base::hex, ios_base::basefield)
oct
setf(ios_base::oct, ios_base::basefield)
fixed
setf(ios_base::fixed,ios_base::floatfield)
scientific
setf(ios_base::scientific,ios_base::floatfield)
cout<<otc;
2.14 iomanip头文件
ostream & setprecision(int);//设置精度
ostream & setfill(char);//设置填充符
ostream & setw(int);//设置宽度
//返回值使得可以实现输出连接
cout << "iomanip头文件************************************************************************" << endl;
cout << noshowpos;
// use new standard manipulators
cout << fixed << right;
// use iomanip manipulators
cout << setw(6) << "N" << setw(14) << "square root"
<< setw(15) << "fourth root\n";
double root;
for (int n = 10; n <= 100; n += 10)
{
root = sqrt(double(n));
cout << setw(6) << setfill('.') << n << setfill(' ')
<< setw(12) << setprecision(3) << root
<< setw(14) << setprecision(4) << sqrt(root)
<< endl;
}
iomanip头文件************************************************************************
N square root fourth root
....10 3.162 1.7783
....20 4.472 2.1147
....30 5.477 2.3403
....40 6.325 2.5149
....50 7.071 2.6591
....60 7.746 2.7832
....70 8.367 2.8925
....80 8.944 2.9907
....90 9.487 3.0801
...100 10.000 3.1623
3 完整测试代码
/*
Project name : _1cout_usage
Last modified Date: 2022年3月12日11点52分
Last Version: V1.0
Descriptions: cout的常用用法
*/
#include