C++ primer 第八章复习

简介: C++ primer 第八章复习

C++ primer 第八章

8.1 IO类

IO 库类型和头文件


头文件 类型
IOStream IStream 从流中读取,OStream 向流中写入
Fstream Ifstream 从文件中读取,Ofstream 向文件中写入
Sstream Istringstream 从string对象读取,Ostringstream 向对象写入


IO 对象不可拷贝或赋值


std::ofstream out1, out2;
out2 = out1;//错误,流对象不能赋值
std::ofstream print(out1);//错误,流对象不能拷贝,形参和返回值类型不能为流

读写一个IO对象会改变其状态,故传递和返回一个IO对象的引用不能为 const


IO 类所定义的函数和标志,可帮助控制流状态


便于理解,iostate 为一个对象,包含以下的位集合


goodbit = 0X0;
eofbit  = 0X1;
failbit = 0X2;
badbit  = 0X4;



有时候我们需要知道流为什么失败


iostate 类型提供了表达流状态的完整功能,这个类型应作为一个位集合来使用


//用以说明,流的状态是可以像变量一样保存的
auto old_state = std::cin.rdstate(); //记录当前cin状态
std::cin.clear(cin.);;//将所有的条件状态复位,使流有效
process_input(cin);//do something 使用cin
std::cin.setstate(old_state);//将cin置为原来状态
//复位failbit和badbit,其它标志位保持不变(没懂)
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

每个输出流都管理一个缓冲区


操作系统会利用缓冲机制在需要时将程序的多个输出操作合并,提升性能


std::cout << std::cin.rdstate() << std::endl;
std::cout << "HI" << std::endl; //输出HI和换行,然后刷新缓冲区
std::cout << "HI" << std::flush;//输出HI,然后刷新缓冲区
std::cout << "HI" << std::ends;//输出HI和一个空字符,然后刷新缓冲区
//通过设置unitBuf操作符来控制是否立即刷新
std::cout << std::unitbuf; //所有输出操作会立即刷新缓冲区
std::cout << std::nounitbuf;//回到正常的缓冲方式

如果程序崩溃,输出缓冲区不会被刷新


每个流同时最多关联到一个流,但多个流可以同时关联到一个 ostream


如下例,std::cin 与 std::cout 绑定(关联)


int ival;
std::cout << "请输入一个整数 : ";
std::cin >> ival;
std::cin.tie(&std::cout);//标准库内置
std::ostream* old_tie = std::cin.tie(nullptr);//cin不再与其它流关联
std::cin.tie(&std::cerr);//读取cin将会刷新cerr的缓冲区
std::cin.tie(old_tie);//重新将cin和cout关联


8.2 文件输入输出fstream

除继承 iostream 之外的操作



std::ifstream in("E:/2.txt");//构造一个ifstream并打开指定文件
std::ofstream out;//输出文件流,未关联到任何文件
out.open("E:/2.txt");//打开指定文件
if (out){ //检查是否open成功
  std::cout << "HI" << std::endl; 
}
in.close();//关闭文件


cin >> 内存 写入 ,内存 >> cout 读出


//写入(从内存读出)
int ar[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, br[10];
ofstream ofile;
ofile.open("E:/TEST.txt", ios::out);
if (ofile)
{
for (int t =0; t<sizeof(ar) / sizeof(int); ++t)
      ofile << ar[t] << " ";//向文件内写入
}
ofile.close();
//读取(向内存写入)
ifstream ifile;
ifile.open("E:/TEST.txt", ios::in);
if (ifile)
{
for (int t =0; t<10; ++t)
      ifile >> br[t];//从文件内读出并写入br中 
}
ifile.close();



自动构造和析构


虽然 input 同名,但却不是同一个输出流,在离开作用域后,流将被自动析构


//argv main函数的参数 argc 参数个数
for( auto p = argv+1; p!= argv+argc; ++P){
  ifstream input(*p);//创建输出流
if(input){
      process(input);
    }else{
      std::cerr << "can not open : "+ std::string(*p);
    }
}


每个流都有一个关联的文件模式 (file mode)



以 out 模式打开的文件会丢弃已有数据,保留 ofstream 打开文件已有数据的方法是指定 app 或 in 模式


ofstream out1("E:/TEST1.txt"); //隐含以输出模式打开并截断文件
ofstream out2("E:/TEST2.txt", ofstream::out);//隐含截断文件
ofstream out2("E:/TEST3.txt", ofstream::out | ofstream::trunc);//按位或
//为了保留文件内容,必须显式指定app模式
ofstream app1("E:/TEST1.txt", ofstream::app);//隐含输出模式
ofstream app2("E:/TEST2.txt", ofstream::out | ofstream::app);
ofstream out4;//未指定打开模式
out4.open("E:/TEST4.txt");//模式隐含为输出和截断
out4.close();
out4.open("E:/TEST4.txt", ofstream::app);//模式为输出和追加
out4.close();


8.3 string 流

String 流


从 string 读写数据,就像 string 是一个 IO 流一样



struct PersonInfo{
  string name;
    vector<string> phones;
}
string line,word;//分别用来保存输入的一行和单词
vector<PersonInfo> people;//保存所有的输入记录
while(getline(cin,line)){
    PersonInfo info;
    istringstream record(line);
    record >> info.name;
while(record >> word){
        info.phones.push_back(word);
    }
    people.push_back(info);
}
/*
  istringstream 向内存写入,ostringstream 从内存输出
*/
for(const auto& entry : people){
    ostringstream formatted,badNums;
for(const auto& nums : entry.phones){
if(!valid(nums)){
            badNums << " " << nums;//将数以字符串的形式存入
        }else{
            formatted << " " << format(nums);//将格式化的数字存入
        }
    }
if(badNums.str().empty()){ //没有错误的数
        //打印名字和格式化的数字
        cout << entry.name << " " <<  formatted.str() << endl;
    }else{
      cerr <<  entry.name << " " <<  badNums.str() << endl;
    }
}
将格式化的数字存入
        }
    }
if(badNums.str().empty()){ //没有错误的数
        //打印名字和格式化的数字
        cout << entry.name << " " <<  formatted.str() << endl;
    }else{
      cerr <<  entry.name << " " <<  badNums.str() << endl;
    }
}



相关文章
|
6月前
|
编译器 C++
c++primer plus 6 读书笔记 第十章 对象和类
c++primer plus 6 读书笔记 第十章 对象和类
|
6月前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
6月前
|
C++
C++ Primer Plus (第6版)中文版 (使用XMind整理)
C++ Primer Plus (第6版)中文版 (使用XMind整理)
C++ Primer Plus (第6版)中文版 (使用XMind整理)
|
6月前
|
C++
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
|
6月前
|
C++
c++primer plus 6 读书笔记 第十一章 使用类
c++primer plus 6 读书笔记 第十一章 使用类
|
6月前
|
编译器 C++
c++primer plus 6 读书笔记 第八章 函数探幽0
c++primer plus 6 读书笔记 第八章 函数探幽0
|
6月前
|
编译器 vr&ar C++
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
|
6月前
|
SQL 人工智能 算法
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
|
6月前
|
程序员 C++
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
|
6月前
|
存储 IDE 编译器
c++primer plus 6 读书笔记 第九章 内存模型和名称空间
c++primer plus 6 读书笔记 第九章 内存模型和名称空间