《C++ Primer Plus》第17章:输入、输出和文件(6)

文章详细阐述了C++中的流概念,包括输入输出流、缓冲区的作用,以及如何通过iostream和fstream库进行文件I/O操作。提到了标准输入输出流如cin和cout,以及fstream类如何用于文件读写。还讨论了不同文件模式,如文本和二进制模式,并介绍了随机访问文件的方法。
摘要由CSDN通过智能技术生成

总结

流是进出程序的字节流。缓冲区是内存中的临时存储区域,是程序与文件或其他 I/O 设备之间的桥梁。信息在缓冲区和文件之间传输时,将使用设备(如磁盘驱动器)处理效率最高的尺寸以大块数据的方式进行传输。信息在缓冲区之间传输时,是逐字节传输的,这种方式对于程序中的处理操作更为方便。C++ 通过将一个被缓冲流同程序及其输入源相连来处理输入。同样,C++ 也通过将一个被缓冲流与程序及其输出目标相连来处理输出。iostrea 和 fstream 文件构成了 I/O 类库,该类库定义了大量用于管理流的类。包含了 iostream 文件的 C++ 程序将自动打开 8 个流,并使用 8 个对象管理它们。cin 对象管理标准输入流,后者默认与标准输入设备(通常为键盘)相连;cout 对象管理标准输出流,后者默认与标准输出设备(通常为显示器)相连;cerr 和 clog 对象管理与标准错误设备(通常为显示器)相连的未被缓冲的流和被缓冲的流。这 4 个对象都有用于宽字符的副本,它们是 wcin、wcout、wcerr 和 wclog。

I/O 类库提供了大量有用的方法。istream 类定义了多个版本的抽取运算符(>>),用于识别所有基本的 C++ 类型,并将字符输入转换为这些类型。get() 方法族和getline() 方法为单字符输入和字符串输入提供了进一步的支持。同样,ostream 类定义了多个版本的插入运算符(<<),用于识别所有的 C++ 基本类型,并将它们转换为相应的字符输出。put() 方法对单字符输出提供了进一步的支持。wistream 和 wostream 类对宽字符提供了类似的支持。

使用 ios_base 类方法以及文件 iostream 和 iomanip 中定义的控制符(可与插入运算符拼接的函数),可以控制程序如何格式化输出。这些方法和控制符使得能够控制计数系统、字段宽度、小数位数、显示浮点变量时采用的计数系统以及其他元素。

fstream 文件提供了将 iostream 方法扩展到文件 I/O 的类定义。ifstream 类是从 istream 类派生而来的。通过将 ifstream 对象与文件关联起来,可以使用所有的 istream 方法来读取文件。同样,通过将 ofstream 对象与文件关联起来,可以使用 ostream 方法来写文件;通过将 fstream 对象与文件关联起来,可以将输入和输出方法用于文件。

要将文件与流关联起来,可以在初始化文件流对象时提供文件名,也可以先创建一个文件流对象,然后用 open() 方法将这个流与文件关联起来。close() 方法终止流与文件之间的连接。类构造函数和open()方法接受可选的第二个参数,该参数提供文件模式。文件模式决定文件是否被读和/或写、打开文件以便写入时是否截短文件、试图打开不存在的文件时是否会导致错误、是使用二进制模式还是文本模式等。

文本文件以字符格式存储所有的信息,例如,数字值将被转换为字符表示。常规的插入和抽取运算符以及 get() 和 getline() 都支持这种模式。二进制文件使用计算机内部使用的二进制表示来存储信息。与文本文件相比,二进制文件存储数据(尤其是浮点值)更为精确、简洁,但可移植性较差。read() 和 write() 方法都支持二进制输入和输出。

seekg() 和 seekp() 函数提供了对文件的随机存取。这些类方法使得能够将文件指针放置到相对于文件开头、文件尾和当前位置的某个位置。tellg() 和 tellp() 方法报告当前的文件位置。

sstream 头文件定义了 istringstream 和 ostringstream 类,这些类使得能够使用 istream 和 ostream 方法来抽取字符串中的信息,并对要放入到字符串中的信息进行格式化。

复习题

  1. istream 文件在 C++ I/O 中扮演何种角色?
    答:iostream 文件定义了用于管理输入和输出的类、常量和操纵符,这些对象管理用于处理 I/O 的流和缓冲区。该文件还创建了一些标准对象(cin、cout、cerr 和 clog 以及对应的宽字符对象),用于处理与每个程序相连的标准输入和输出流。

  2. 为什么键入数字(如121)作为输入要求程序进行转换?
    答:键盘输入生成一系列字符。输入121将生成3个字符,每个字符都由一个1字节的二进制码表示。要将这个值存储为 int 类型,则必须将这 3 个字符转换为 121 值的二进制表示。

  3. 标准输出与标准错误之间有什么区别?
    答:在默认情况下,标准输出和标准错误都将输出发送给标准输出设备(通常为显示器)。然而,如果要求操作系统将输出重定向到文件,则标准输出将与文件(而不是显示器)相连,但标准错误仍与显示器相连。

  4. 为什么在不为每个类型提供明确指示的情况下,cout 仍能够显示不同的 C++ 类型?
    ostream 类为每种 C++ 基本类型定义了一个 operator<<() 重载。

  5. 输出方法的定义哪一特征让您能够拼接输出?
    答:返回 ostream & 类型使得能够拼接输出。

  6. 编写一个程序,要求用户输入一个整数,然后以十进制、八进制和十六进制显示该整数。在宽度为 15 个字符的字段中显示每种形式,并将它们显示在同一行上,同时使用 C++ 基数前缀。

    #include<iostream>
    #include<iomanip>
    
    int main() {
        int num;
        std::cout << "Input an integer: ";
        std::cin >> num;
        std::cout.setf(std::ios_base::showbase);
        std::cout << std::hex << std::setw(15) << num
                  << std::dec << std::setw(15) << num
                  << std::oct << std::setw(15) << num << std::endl;
    
        return 0;
    }
    
  7. 编写一个程序,请求用户输入下面的信息,并按下面的格式显示它们:

    Enter your name: Billy Gruff
    Enter your hourly wages: 12
    Enter number of hours worked: 7.5
    Fisrt format:
             Billy Gruff: $     12.00:  7.5
    Second format:
    Billy Gruff         : $12.00     :7.5 
    

    答:

    #include<iostream>
    #include<iomanip>
    
    const int LIM = 20;
    
    int main() {
        using namespace std;
        char name[20];
        float hourly;
        float hours;
    
        cout << "Enter your name: ";
        cin.get(name, LIM).get();
        cout << "Enter your hourly wages: ";
        cin >> hourly;
        cout << "Enter number of hours worked: ";
        cin >> hours;
    
        cout.setf(ios::showpoint);
        cout.setf(ios::fixed, ios_base::floatfield);
    
        cout << "Fisrt format:\n";
        cout.setf(ios_base::right, ios_base::adjustfield);
        cout << setw(20) << name << ": $" << setprecision(2)
             << setw(10) << hourly << ":" << setprecision(1)
             << setw(5) << hours << "\n";
        cout << "Second format:\n";
        cout.setf(ios_base::left, ios_base::adjustfield);
        cout << setw(20) << name << ": $" << setprecision(2)
             << setw(10) << hourly << ":" << setprecision(1)
             << setw(5) << hours << "\n";
        
        return 0;
        
    }
    
  8. 对于下面的程序:

    rq17-8.cpp
    #include <iostream>
    #include <iomanip>
    
    int main() {
    	using namespace std;
    	char ch;
    	int ct1 = 0;
    	
    	cin >> ch;
    	while ( ch != 'q' ) {
    		ct1++;
    		cin >> ch;
    	}
    	
    	int ct2 = 0;
    	cin.get(ch);
    	while ( ch != 'q' ) {
    		ct2++;
    		cin.get(ch);
    	}
    	cout << "ct1 = " << ct1 << "; ct2 = " << ct2 << "\n";
    
    	return 0;
    }
    

    如果输入如下,该程序将打印什么内容?

    I see a q<Enter>
    I see a q<Enter>
    

    答:
    ct1 = 5; ct2 = 9;
    该程序的前半部分忽略空格和换行符,而后半部分没有。注意,程序的后半部分从第一个 q 后面的换行符开始读取,将换行符计算在内。

  9. 下面的两条语句都读取并丢弃行尾之前的所有字符(包括行尾)。这两条语句的行为在哪方面不同?

    while (cin.get() != '\n') {
    	continue;
    }
    cin.ignore(80, '\n');
    

    答:第一条语句可以除去包括换行符在内的该行的所有字符,而第二条语句虽然也能这样做,但最多只能去除80个字符,如果在清除了80个字符时仍然没有遇到换行符,就将剩下的字符留在缓冲区。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值