《C++ primer plus》第十七章 输入、输出和文件(一):输入和输出 学习笔记

来源:互联网 发布:ubuntu mxnet 编辑:程序博客网 时间:2024/05/16 17:09

一、C++输入和输出概述

1.C++把输入和输出看成字节流,缓冲区是用于终结的内存块,用于临时储存数据,使用缓冲区可以更高效地处理输入和输出
2.一些I/O类
streambuf类为缓冲区提供了内存,并提供了用于填充缓冲区、访问缓冲区内容、刷新缓冲区和管理缓冲区内存的类方法
ios_base类表示流的一般特征,如是否可读取,是二进制流还是文本流等。包含一些非模板的性质
ios类基于ios_base,其中包括了一个指向streambuf对象的指针成员。包含的是模板的性质
ostream类从ios类派生而来的,提供了输出方法
istream类从ios类派生而来,提供了输入方法
iostream类基于istream和ostream类的,继承了输入输出方法
3.C++的iostream类库中包含很多细节,如在程序中包含iostream文件将自动创建8个流对象(4个用于窄字符,4个用于宽字符)
cin(wcin),cout(wcout),cerr(用于显示错误消息,这个流没有缓冲,wcerr),clog(wclog,也对应着标准错误流,这个流被缓冲)
4.重定向能够改变标准输入和标准输出
假设C盘中有文件test.exe,则打开一个MD-DOS窗口(Linux/Dos/Unix能自动识别这种语法)
输入:C>test <1.txt >2.txt
此时,程序将从文件1.txt中读取输入(而不是键盘),输出到2.txt中,而不是显示屏

二、使用cout进行输出

C++将输出看成是字节流,ostream类最重要的任务之一是将数值类型转换成以文本形式表示的字节流

1.<<输出与指针

对于字符串的指针,C++自动打印出字符串,对于其他类型的指针,C++将其对应于void*,并打印地址的数值表示,如果要获得字符串的地址,需要将其强制转化为void*

2.其他ostream方法

(1)put()用于显示字符:cin.put('W').put('a');
还可以用数值型参数(如int)让函数自动转化参数为对应的char值,如:cin.put(65) //输出结果为:A
(2)write()方法用于显示真格字符串,模板原型:
basic_ostream<charT,traits>& write(const char_type* s,streamsize n)
第一个参数为要显示字符串的地址,第二个参数为要显示多少个字符,同样,cout.write也可以拼接

3.刷新缓冲区

(1)刷新缓冲区常见的几种情况:
<1>填满缓冲区,缓冲区一般为512个字节或是其整数倍
<2>在输入即将发生时刷新缓冲区
<3>控制符flush刷新缓冲区,endl刷新缓冲区并插入一个换行符
事实上,控制符也是函数,可以直接调用flush来刷新缓冲区,如flush(cout)
不过ostream类对<<进行了重载,使得可以用cout << flush 代替flush(cout)

4.用cout进行格式化

(1)默认情况下的浮点类型显示为6位,末尾的0不显示,显示的数字位数和数字被储存时的精度没有任何关系,一般来讲,当指数大于等于6或小于等于-5时,将使用科学记数法,另外,字段宽度恰好容纳数字和负号,默认的行为对应fprintf的%g

(2)修改显示时的记数系统:dec(十进制),hex(十六进制),oct(八进制)
注:控制符不是成员函数
(3)调整字段宽度:width()是成员函数,只能用cout.width(int)进行调用,如cout.width(12)
注:width只影响显示的一个项目,之后将宽度恢复为默认值
如果在宽度为2的字段中打印一个7位值C++将增宽字段
(4)填充字符:在默认情况下,C++将使用空格填充字符,使用fill()成员函数进行改变,如:cout.fill('*')
注:与width不同的是,fill直到更改为止,该填充字符一直有效
(5)设置浮点数的精度:默认值为6,可以使用precision()成员函数进行改变,如:cout.precision(2)
注:precision直到更改为止,一直有效
(6)打印末尾的0和小数点:cout.setf(ios_base::showpoint)(因为showpoint为ios_base类定义的静态常量,所以要使用::)
此时cout不会将2.00显示为2,而是2.00000
警告:如果编译器使用的头文件为iostream.h,则有可能在setf()中使用ios参数,而不是ios_base
(7)再谈setf
setf的一种原型为:fmtflags setf(fmtflags);
fmtflags是bitmask类型的typedef名,用于储存格式标记,该名称是在ios_base类中定义的
注:bitmask类型是一种用来储存各个位值的类型;

ios_base::boolalpha 输出bool值时为true和falseios_base::showpoint 显示末尾的小数点ios_base::showbase对于输出,使用C++基数前缀(0x)ios_base::uppercase 对于16进制输出,使用大写字母,E表示法ios_base::showpos在正数前面加上+

由于这些常量是在ios_base类中定义的,因此使用它们,必须使用::


第二个setf的原型:fmtflags setf(fmtflags,fmtflags),该函数返回以前的设置
第一个参数和第一个一样,包含了所需设置的fmtflags位,第二个参数指出要清除第一个参数中的哪些位

setf的参数第二个参数 第一个参数含义ios_base::basefieldios_base::dec十进制 ios_base::oct八进制 ios_base::hex十六进制ios_base::floatfieldios_base::fixed定点记数法 ios_base::scientific科学记数法ios_base::adjustfieldios_base::left左对齐 ios_base::right右对齐 ios_base::internal符号或基数前缀左对齐,值右对齐
如:cout.setf(ios_base::hex,ios_base::basefield)
由于该函数返回以前的设置,因此,要回复以前的设置,可以
ios:base old = cout.setf(ios_base::oct,ios_base::basefield);
cout.setf(old,ios_base::basefield);
使用setf的效果可以通过unsetf()消除
void unsetf(fmtflags mask);
如cout.setf(ios_base::boolalpha);
unsetf(ios_base::boolalpha);

(8)iomanip提供的一些标准控制符

boolalpha             setf(ios_base::boolalpha)noboolalpha           setf(ios_base::noboolalpha)showbase              setf(ios_base::showbase)noshowbase            setf(ios_base::noshowbase)showpoint             setf(ios_base::showpoint)noshowpoint           setf(ios_base::noshowpoint)showpos               setf(ios_base::showpos)noshowpos             setf(ios_base::noshowpos)uppercase             setf(ios_base::uppercase)nouppercase           setf(ios_base::nouppercase)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::base_field)hex                   setf(ios_base::hex, ios_base::base_field)oct                   setf(ios_base::oct, ios_base::base_field)fixed                 setf(ios_base::fixed, ios_base::floatfield)scientific            setf(ios_base::scientific, ios_base::floatfield)

三、使用cin进行输入

1.流状态

可以使用hex、oct和dec控制符与cin一起使用
(1)cin和cout包含一个流状态,从ios_base里继承。流状态被定义为iostate类型,而iostate是一种bitmask类型
(2)
成员描述enfbit如果到文件尾,设置为1 badbit如果流被破坏,则设置为1;例如,文件读取错误failbit如果输入操作未能读取预期的字符或输出操作没有写入预期的字符,则设置为1goodbit另一种表示0的方法good()如果流可以使用(所有的位都被清除),则返回trueeof()如果eofbit被设置,则返回truebad()如果badbit被设置,则返回truefail()如果badbit或failbit被设置,则返回truerdstate()返回流状态exceptions()返回一个位掩码,支出哪些标记导致异常被引发exceptions(isostate ex)设置哪些状态将导致clear()引发异常,例如,如果ex是eofbit,则如果eofbit被设置,clear()将引发异常clear(iostate s)将流状态设置为s,s的默认值为0(goodbit);如果(restate()& exceptions())!= 0,则引发异常basic_ios::failuresetstate(iostate s)调用clear(rdstate() | s)。这将设置与s中设置的位对应的流状态位,其他流状态为保持不变
(3)设置状态
clear()和setstate()都可以重置状态,但是采取的方法不同
clear()默认参数为0,将清除全部状态位(eofbit,badbit,failbit)
而clear(eofbit)将状态设置为eofbit,另外两个状态位被清除
而setstate(eofbit)将不会影响其他的状态位
(4)I/O和异常
exceptions(isostate ex),设置哪些状态将导致clear()引发异常,例如,如果ex是eofbit,则如果eofbit被设置,clear()将引发异常,使用位操作符OR | 可以指定多位
// cinexcp.cpp -- having cin throw an exception#include <iostream>#include <exception>int main(){    using namespace std;    // have failbit cause an exception to be thrown    cin.exceptions(ios_base::failbit);    cout << "Enter numbers: ";    int sum = 0;    int input;    try {        while (cin >> input)        {            sum += input;        }    } catch(ios_base::failure & bf)    {        cout << bf.what() << endl;        cout << "O! the horror!\n";    }    cout << "Last value entered = " << input << endl;    cout << "Sum = " << sum << endl;    return 0;}

2.其他istream类方法

(1)单字符输入
cin.get(ch)赋给参数ch,返回为istream对象的引用,到达文件尾时返回值为false
ch = cin.get(),返回值为字符编码int值,到达文件尾时返回值为EOF(这里的ch最好声明为int,而不是char,因为EOF可能不能用char表示)
(2)字符串输入
istream& get(char*,int,char = '\n');
istream& getline(char*,int,char = '\n');
istream& ignore(int = 1,int = EOF)(第一个是读取的最大字符,第二个为分界符,用于读取并丢弃)
补充:getline()与string
template< class CharT, class Traits, class Allocator >
std::basic_istream<CharT,Traits>& getline( std::basic_istream<CharT,Traits>&& input,
                                           std::basic_string<CharT,Traits,Allocator>& str,
                                           CharT delim );
(3)意外字符串的输入
getline()如果没有读取任何字符(但换行符被视为读取了一个字符)或读取了最大数目的字符,且行中还有其他字符,则设置failbit
get(char*,int)如果没有读取任何字符,则设置faileof

3.其他istream方法

(1)read()
istream& read( char_type* s, int count );与getline和get不用的是,read函数不会在输入后加上'\0',因此不能用于将输入转化为字符串
read()常与ostream.wirte()结合使用,用于完成文件的输入和输出
(2)peek()
能够查看输入流的下一个字符,但是并不抽取字符
#include <sstream>#include <iostream>int main(){    std::istringstream s1("Hello, world.");    char c1 = s1.peek();    char c2 = s1.get();    std::cout << "Peeked: " << c1 << " got: " << c2 << '\n';}/*输出结果为:Peeked: H got: H */
(3)gcount()返回非格式化抽取字符方法读取的字符数,即get(),getline(),ignore(),read(),但是效率较慢
(4)putback()将一个字符插入到字符串中,被插入的字符将是输出流的第一个字符
#include <sstream>#include <iostream> int main(){    std::stringstream s1("Hello, world"); // IO stream    s1.get();    if (s1.putback('Y')) // modifies the buffer        std::cout << s1.rdbuf() << '\n';    else        std::cout << "putback failed\n";     std::istringstream s2("Hello, world"); // input-only stream    s2.get();    if (s2.putback('Y')) // cannot modify input-only buffer        std::cout << s2.rdbuf() << '\n';    else        std::cout << "putback failed\n";     s2.clear();    if (s2.putback('H')) // non-modifying putback        std::cout << s2.rdbuf() << '\n';    else        std::cout << "putback failed\n";}/*输出结果为:Yello, worldputback failedHello, world */



0 0
原创粉丝点击