前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ Primer Plus习题及答案-第十七章

C++ Primer Plus习题及答案-第十七章

作者头像
艰默
发布2023-02-26 11:02:12
3.1K0
发布2023-02-26 11:02:12
举报
文章被收录于专栏:iDoitnow

习题选自:C++ Primer Plus(第六版) 内容仅供参考,如有错误,欢迎指正 ! cout格式化输出 使用cin进行输入 文件的输入和输出

复习题

1. iostream文件在C++ I/O中扮演何种角色?

iostream文件定义了用于管理输入和输出的类、常量和操作符,这些对象用于I/O的流和缓冲区。该文件还创建了一些用于处理标准输入输出流的标准对象(如cin、cout、cerr和clog以及对应的宽字符对象)。

2. 为什么键入数字(如121)作为输入要求程序进行转换?

键盘输入会生成一系列字符,输入121将会生成3个字符,每个字符都由一个字节的二进制码表示。要将这个值存储为int类型,则必须将这3个字符转换为121值的二进制表示。

3. 标准输出与标准错误之间有什么区别?

默认情况下两者都将输出发给标准输出设备(通常为显示器)。然而,如果要求操作系统操作系统将输出重定向到文件,则标准输出将与文件相连,但标准错误仍与显示器相连。

4. 为什么在不为每个类型提供明确指示的情况下,cout仍能够显示不同的C++类型?

ostream类为每种C++基本类型定义了一个operator <<()函数的版本。编译器将类似cout << spot的表达式解释为cout.operator<<(spot),这样,它便能够将该方法调用与具有相同参数类型的函数原型匹配。

5. 输出方法的定义的哪一特征让您能够拼接输出?

返回ostream &类型的输出方法能够拼接输出。通过一个对象调用方法时,将返回该对象。然后,返回对象将可以调用序列中的下一个方法

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

代码语言:javascript
复制
#include <iomanip>
#include <iostream>

int main() {
  using namespace std;
  cout << "Enter an interger: ";
  int n;
  cin >> n;
  cout << setw(15) << "base ten" << setw(15) << "base sixteen" << setw(15)
       << "base eight"
       << "\n";
  cout.setf(ios::showbase);
  cout << setw(15) << n << hex << setw(15) << n << oct << setw(15) << n << "\n";
  return 0;
}

7. 编写一个程序,请求用户输入下面的信息,并按下面的格式显示它们:

代码语言:javascript
复制
Enter your name: Billy Gruff
Enter your hourly wages: 12
Enter number of hours worked: 7.5
First format:
             Billy Gruff: $ 12.00: 7.5
Second format:
Billy Gruff             : $12.00 :7.5

main.cpp:

代码语言:javascript
复制
#include <iomanip>
#include <iostream>
int main() {
    using namespace std;
    char name[20];
    float hourly;
    float hours;
    cout << "Enter your name: ";
    cin.get(name, 20).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::floatfield);
    cout.setf(ios::right, ios::adjustfield);
    // or cout << showpoint << fixed << right;
    cout << "First format:\n";
    cout << setw(30) << name << ": $" << setprecision(2) << setw(10) << hourly
        << ":" << setprecision(1) << setw(5) << hours << "\n";
    cout << "Second format:\n";
    cout.setf(ios::left, ios::adjustfield);
    cout << setw(30) << name << ": $" << setprecision(2) << setw(10) << hourly
        << ":" << setprecision(1) << setw(5) << hours << "\n";
    return 0;
}

8. 对于下面的程序:

代码语言:javascript
复制
//rq17-8.cpp
#include <iostream>
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;
}

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

代码语言:javascript
复制
I see a q<Enter>
I see a q<Enter>

其中,表示按回车键。

使用cin >> ch;会自动忽略空格和换行符,因此ct1的值应为5。而cin.get(ch);不忽略空格和换行符,且第一次输入的回车键,也会被cin.get(ch);捕捉到,因此ct2的值应为9。打印内容如下:

代码语言:javascript
复制
ct1 = 5; ct2 = 9

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

代码语言:javascript
复制
while (cin.get() != '\n')
    continue;
cin.ignore(80, '\n');

如果输入超过80个字符,且这80个字符中没有出现'\n',则ignore()会将前80个字符都会抛弃掉,然后再开始执行后面的语句。也就是说当输入超过80个字符,且这80个字符中没有出现'\n'cin.ignore(80, '\n');读取并丢弃行尾之前的所有字符(包括行尾)的作用可能会不符合预期。而第一条语句没有该限制。【注:可以将第二个语句中80改为numeric_limits<streamsize>::max()来解除该限制】

编程练习

1. 编写一个程序计算输入流中第一个之前的字符数目,并将留在输入流中。

main.cpp:

代码语言:javascript
复制
#include <iostream>
//#include <ios>  //used to get stream size
//#include <limits>  //used to get numeric limits

int main() {
    using std::cin;
    using std::cout;
    using std::endl;

    cout << "Enter a string with a '$' in it: " << endl;
    int ct = 0;
    char ch;
    while ((ch = cin.get()) != '$') ct++;
    cin.putback(ch);  // put $ back to stream

    while (cin.get() != '\n') continue;
    // or use cin.ignore(std::numeric_limits<std::streamsize>::max(),// '\n');

    cout << "There are " << ct << " characters before $" << endl;

    return 0;
}

2. 编写一个程序,将键盘输入(直到模拟的文件尾)复制到通过命令行指定的文件中。

main.cpp:

代码语言:javascript
复制
#include <cstdlib>
#include <fstream>
#include <iostream>

using namespace std;

int main() {
    cout << "Please enter filename: ";
    char fname[30];
    cin >> fname;
    ofstream fout;
    fout.open(fname, std::ios_base::out);

    cout << "Please enter something: " << endl;
    char ch;
    while (cin.get(ch) && ch != EOF) fout << ch;

    fout.close();

    return 0;
}

:linux下键盘模拟输入文件结束符为Ctrl+D

3. 编写一个程序,将一个文件复制到另一个文件中。让程序通过命令行获取文件名。如果文件无法打开,程序将指出这一点。

main.cpp:

代码语言:javascript
复制
#include <cstdlib>
#include <fstream>
#include <iostream>

int main(int argc, char* argv[]) {
    using namespace std;

    if (argc < 3) {
        cerr << "Usage: " << argv[0] << " source-file target-file" << endl;
        exit(EXIT_FAILURE);
    }

    ifstream fin(argv[1], ios_base::in);
    if (!fin) {
        cerr << "Cant't open" << argv[1] << " for input" << endl;
        exit(EXIT_FAILURE);
    }

    ofstream fout(argv[2], ios_base::out);
    if (!fout) {
        cerr << "Can't open" << argv[2] << " for output" << endl;
        exit(EXIT_FAILURE);
    }

    char ch;
    while (fin.get(ch)) fout.put(ch);

    cout << "Content of " << argv[1] << " copied to " << argv[2] << "success."
        << endl;
    fin.close();
    fout.close();

    return 0;
}

4. 编写一个程序,它打开两个文本文件进行输入,打开一个文本文件进行输出。该程序将两个输入文件中对应的行拼接起来,并用空格分隔,然后将结果写入到输出文件中。如果一个文件比另一个短,则将较长文件中余下的几行直接复制到输出文件中。例如,假设第一个输入文件的内容如下:

代码语言:javascript
复制
eggs kites donuts
balloons hammers
stones

而第二个输入文件的内容如下:

代码语言:javascript
复制
zero lassitude
finance drama

则得到的文件的内容将如下:

代码语言:javascript
复制
eggs kites donuts zero lassitude
balloons hammers finance drama
stones

main.cpp:

代码语言:javascript
复制
#include <fstream>
#include <iostream>

int main() {
    using namespace std;
    char* file1 = "input1.txt";
    char* file2 = "input2.txt";
    char* file3 = "output.txt";
    ifstream fin1(file1, ios_base::in);
    ifstream fin2(file2, ios_base::in);
    ofstream fout1(file3, ios_base::out);
    if (!fin1.is_open() || !fin2.is_open()) {
        cerr << file1 << " or " << file2 << "open fail.";
        exit(EXIT_FAILURE);
    }
    char ch;
    if (!fout1.is_open()) {
        cerr << "Can't open " << file3 << endl;
        exit(EXIT_FAILURE);
    } else {
        while (!fin1.eof() || !fin2.eof()) {
            if (!fin1.eof()) {
                while (fin1.get(ch) && ch != '\n') fout1 << ch;
                fout1 << ' ';
            }
            if (!fin2.eof()) {
                while (fin2.get(ch) && ch != '\n') fout1 << ch;
            }
            fout1 << '\n';
        }
    }
    fin1.close();
    fin2.close();
    fout1.close();

    return 0;
}

5. Mat和Pat想邀请他们的朋友来参加派对,就像第16章中的编程练习8那样,但现在他们希望程序使用文件。他们请您编写一个完成下述任务的程序。

  • 从文本文件mat.dat中读取Mat朋友的姓名清单,其中每行为一个朋友。姓名将被存储在容器,然后按顺序显示出来。
  • 从文本文件pat.dat中读取Pat朋友的姓名清单,其中每行为一个朋友。姓名将被存储在容器中,然后按顺序显示出来。
  • 合并两个清单,删除重复的条目,并将结果保存在文件matnpat.dat中,其中每行为一个朋友。

main.cpp:

代码语言:javascript
复制
#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <set>
#include <string>
#include <vector>

int main() {
    using namespace std;

    vector<string> mat;
    vector<string> pat;
    set<string> matnpat;

    ifstream fmat("mat.dat", ios_base::in), fpat("pat.dat", ios_base::in);
    if (!(fmat && fpat)) {
        cerr << "Failed to open input files" << endl;
        exit(EXIT_FAILURE);
    }

    ofstream fout("matnpat.at", ios_base::out);
    if (!fout) {
        cerr << "Failed to open output files" << endl;
        exit(EXIT_FAILURE);
    }

    string name;

    while (fmat >> name) mat.push_back(name);
    cout << "Mat's friends: ";
    for (auto it = mat.begin(); it != mat.end(); ++it) cout << *it << " ";
    cout << endl;

    while (fpat >> name) pat.push_back(name);
    cout << "Pat's friends: ";
    for (auto it = pat.begin(); it != pat.end(); ++it) cout << *it << " ";
    cout << endl;

    matnpat.insert(mat.begin(), mat.end());
    matnpat.insert(pat.begin(), pat.end());
    cout << "All friends: " << endl;
    for (auto& name : matnpat) cout << name << " ";
    cout << endl;

    return 0;
}

6. 考虑14章的编程练习5中的类定义。如果还没有完成这个练习,请现在就做,然后完成下面的任务。

编写一个程序,它使用标准C++ I/O、文件I/O以及14章的编程练习5中定义的employee、manager、fink和highfink类型的数据。该程序应包含程序清单17.17中的代码行,即允许用户将新数据添加到文件中。该程序首次被运行时,将要求用户输入数据,然后显示所有的数据,并将这些信息保存到一个文件中。当该程序再次被运行时,将首先读取并显示文件中的数据,然后让用户添加数据,并显示所有的数据。差别之一是,应通过一个指向employee类型的指针数组来处理数据。这样,指针可以指向employee对象,也可以指向从employee派生出来的其他三种对象中的任何一种。使数组较小有助于检查程序,例如,您可能将数组限定为最多包含10个元素:

代码语言:javascript
复制
const int MAX = 10; // no more than 10 objects
...
employee * pc[MAX];

为通过键盘输入,程序应使用一个菜单,让用户选择要创建的对象类型。菜单将使用一个switch,以便使用new来创建指定类型的对象,并将它的地址赋给pc数组中的一个指针。然后该对象可以使用虚函数setall( )来提示用户输入相应的数据:

代码语言:javascript
复制
pc[i]->setall(); // invokes function corresponding to type of object

为将数据保存到文件中,应设计一个虚函数writeall( ):

代码语言:javascript
复制
for (i = 0; i < index; i++)
pc[i]->writeall(fout);// fout ofstream connected to output file

注意】:

对于这个练习,应使用文本I/O,而不是二进制I/O(遗憾的是,虚对象包含指向虚函数指针表的指针,而write( )将把这种信息复制到文件中。使用read( )读取文件的内容,以填充对象时,函数指针值将为乱码,这将扰乱虚函数的行为)。可使用换行符将字段分隔开,这样在输入时将很容易识别各个字段。也可以使用二进制I/O,但不能将对象作为一个整体写入,而应该提供分别对每个类成员应用write( )和read( )的类方法。这样,程序将只把所需的数据保存到文件中。

比较难处理的部分是使用文件恢复数据。问题在于:程序如何才能知道接下来要恢复的项目是employee对象、manager对象、fink对象还是highfink对象?一种方法是,在对象的数据写入文件时,在数据前面加上一个指示对象类型的整数。这样,在文件输入时,程序便可以读取该整数,并使用switch语句创建一个适当的对象来接收数据:

代码语言:javascript
复制
enum classkind{Employee, Manager, Fink, Highfink}; // in class header
...
    int classtype;
while((fin >> classtype).get(ch)){ // newline separates int from data
    switch(classtype) {
        case Employee : pc[i] = new employee;
            : break;

然后便可以使用指针调用虚函数getall( )来读取信息:

代码语言:javascript
复制
pc[i++]->getall();

emp.h:

代码语言:javascript
复制
#ifndef EMP_H_
#define EMP_H_

#include <iostream>
#include <string>
#include <fstream>

enum classkind {Employee, Manager, Fink, HighFink};

class abstr_emp
{
private:
    std::string fname;
    std::string lname;
    std::string job;
public:
    abstr_emp();
    abstr_emp(const std::string & fn, const std::string & ln,
              const std::string & j);
    virtual void ShowAll() const;
    virtual void SetAll();
    virtual std::ofstream & WriteAll(std::ofstream & of) const;
    friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e);
    virtual ~abstr_emp() = 0;
};

class employee : public abstr_emp
{
public:
    employee();
    employee(const std::string & fn, const std::string & ln,
             const std::string & j);
    virtual void ShowAll() const;
    virtual void SetAll();
    std::ofstream & WriteAll(std::ofstream & fout) const;
};

class manager : virtual public abstr_emp
{
private:
    int inchargeof;
protected:
    int InChargeOf() const { return inchargeof; }
    int & InChargeOf() { return inchargeof; }
public:
    manager();
    manager(const std::string & fn, const std::string & ln,
            const std::string & j, int ico = 0);
    manager(const abstr_emp & e, int ico);
    manager(const manager & m);
    virtual void ShowAll() const;
    virtual void SetAll();
    std::ofstream & WriteAll(std::ofstream & fout) const;
};

class fink : virtual public abstr_emp
{
private:
    std::string reportsto;
protected:
    const std::string ReportsTo() const { return reportsto; }
    std::string & ReportsTo() { return reportsto; }
public:
    fink();
    fink(const std::string & fn, const std::string ln,
         const std::string & j, const std::string rpo);
    fink(const abstr_emp & e, const std::string & rpo);
    fink(const fink & f);
    virtual void ShowAll() const;
    virtual void SetAll();
    std::ofstream & WriteAll(std::ofstream & fout) const;
};

class highfink : public manager, public fink
{
public:
    highfink();
    highfink(const std::string & fn, const std::string & ln,
             const std::string & j, const std::string & rpo,
             int ico);
    highfink(const abstr_emp & e, const std::string rpo, int ico);
    highfink(const fink & f, int ico);
    highfink(const manager & m, const std::string rpo);
    highfink(const highfink & h);
    virtual void ShowAll() const;
    virtual void SetAll();
    std::ofstream & WriteAll(std::ofstream & fout) const;
};

#endif

emp.cpp:

代码语言:javascript
复制
#include "emp.h"

/*******************
 * abstr_emp methods
 *******************/
abstr_emp::abstr_emp()
{
    fname = "none";
    lname = "none";
    job = "none";
}

abstr_emp::abstr_emp(const std::string & fn, const std::string & ln,
                     const std::string & j) : fname(fn), lname(ln), job(j)
{
}

abstr_emp::~abstr_emp() {}

void abstr_emp::ShowAll() const
{
    std::cout << "firstname: " << fname << std::endl;
    std::cout << "lastname: " << lname << std::endl;
    std::cout << "job: " << job << std::endl;
}

void abstr_emp::SetAll()
{
    std::cout << "Enter firstname: ";
    std::getline(std::cin, fname);
    std::cout << "Enter lastname: ";
    std::getline(std::cin, lname);
    std::cout << "Enter job: ";
    std::getline(std::cin, job);
}

std::ofstream & abstr_emp::WriteAll(std::ofstream & fout) const
{
    fout << fname << " " << lname << " " << job;
    return fout;
}

// friend functions
std::ostream & operator<<(std::ostream & os, const abstr_emp & e)
{
    os << e.lname << " " << e.fname << ", " << e.job;
    return os;
}

/******************
 * employee methods
 ******************/
employee::employee() {}

employee::employee(const std::string & fn, const std::string & ln,
                   const std::string & j)
    : abstr_emp(fn, ln, j)
{
}

void employee::ShowAll() const
{
    abstr_emp::ShowAll();
}

void employee::SetAll()
{
    abstr_emp::SetAll();
}

std::ofstream & employee::WriteAll(std::ofstream & fout) const
{
    fout << Employee << " ";
    abstr_emp::WriteAll(fout);
    return fout;
}


/*****************
 * manager methods
 *****************/
manager::manager()
{
    inchargeof = 0;
}


manager::manager(const std::string & fn, const std::string & ln,
                 const std::string & j, int ico)
    : abstr_emp(fn, ln, j), inchargeof(ico)
{
}

manager::manager(const abstr_emp & e, int ico)
    : abstr_emp(e)
{
    inchargeof = ico;
}

manager::manager(const manager & m)
    : abstr_emp(m)
{
    inchargeof = m.inchargeof;
}

void manager::ShowAll() const
{
    abstr_emp::ShowAll();
    std::cout << "Inchargeof: " << inchargeof << std::endl;
}

void manager::SetAll()
{
    abstr_emp::SetAll();
    std::cout << "Enter inchargeof: ";
    std::cin >> inchargeof;
    std::cin.get();
}

std::ofstream & manager::WriteAll(std::ofstream & fout) const
{
    fout << Manager << " ";
    abstr_emp::WriteAll(fout);
    fout << " " << inchargeof;
    return fout;
}

/**************
 * fink methods
 **************/
fink::fink()
{
    reportsto = "none";
}

fink::fink(const std::string & fn, const std::string ln,
           const std::string & j, const std::string rpo)
    : abstr_emp(fn, ln, j), reportsto(rpo)
{
}

fink::fink(const abstr_emp & e, const std::string & rpo)
    : abstr_emp(e), reportsto(rpo)
{
}

fink::fink(const fink & f)
    : abstr_emp(f)
{
    reportsto = f.reportsto;
}

void fink::ShowAll() const
{
    abstr_emp::ShowAll();
    std::cout << "Reportsto: " << reportsto << std::endl;
}

void fink::SetAll()
{
    abstr_emp::SetAll();
    std::cout << "Enter reportsto: ";
    std::getline(std::cin, reportsto);
}

std::ofstream & fink::WriteAll(std::ofstream & fout) const
{
    fout << Fink << " ";
    abstr_emp::WriteAll(fout);
    fout << " " << reportsto;
    return fout;
}

/******************
 * highfink methods
 ******************/
highfink::highfink() {}

highfink::highfink(const std::string & fn, const std::string & ln,
                   const std::string & j, const std::string & rpo,
                   int ico)
    : abstr_emp(fn, ln, j), manager(fn, ln, j, ico), fink(fn, ln, j, rpo)
{
}

highfink::highfink(const abstr_emp & e, const std::string rpo, int ico)
    : abstr_emp(e), manager(e, ico), fink(e, rpo)
{
}

highfink::highfink(const fink & f, int ico)
    : abstr_emp(f), fink(f), manager((const abstr_emp &)f, ico)  // ????
{
}

highfink::highfink(const manager & m, const std::string rpo)
    : abstr_emp(m), manager(m), fink((const abstr_emp &)m, rpo)
{
}

highfink::highfink(const highfink & h)
    : abstr_emp(h), manager(h), fink(h)
{
}

void highfink::ShowAll() const
{
    abstr_emp::ShowAll();
    std::cout << "Inchargeof: " << manager::InChargeOf() << std::endl;
    std::cout << "Reportsto: " << fink::ReportsTo() << std::endl;
}

void highfink::SetAll()
{
    abstr_emp::SetAll();
    std::cout << "Enter reportsto: ";
    std::getline(std::cin, fink::ReportsTo());
    std::cout << "Enter Inchargeof: ";
    std::cin >> manager::InChargeOf();
    std::cin.get();
}

std::ofstream & highfink::WriteAll(std::ofstream & fout) const
{
    fout << HighFink << " ";
    abstr_emp::WriteAll(fout);
    fout << " " << manager::InChargeOf() << " " << fink::ReportsTo();
    return fout;
}

main.cpp:

代码语言:javascript
复制
#include <fstream>
#include <iostream>

#include "emp.h"

using namespace std;

inline void show_line(int n);
void show_menu();
inline void eatline();

const int MAX = 10;

int main() {
    abstr_emp* pc[MAX];
    int ct = 0;  // number counter

    string fname, lname, job, reportsto;
    int inchargeof;

    ifstream fin("out.txt", ios_base::in);
    if (fin.good()) {  // read from file
        int kind;
        while (fin >> kind) {
            switch (kind) {
                case Employee:
                    fin >> fname;
                    fin >> lname;
                    fin >> job;
                    pc[ct] = new employee(fname, lname, job);
                    break;
                case Manager:
                    fin >> fname;
                    fin >> lname;
                    fin >> job;
                    fin >> inchargeof;
                    pc[ct] = new manager(fname, lname, job, inchargeof);
                    break;
                case Fink:
                    fin >> fname;
                    fin >> lname;
                    fin >> job;
                    fin >> reportsto;
                    pc[ct] = new fink(fname, lname, job, reportsto);
                    break;
                case HighFink:
                    fin >> fname;
                    fin >> lname;
                    fin >> job;
                    fin >> reportsto;
                    fin >> inchargeof;
                    pc[ct] = new highfink(fname, lname, job, reportsto, inchargeof);
            }
            ct++;
        }

        // show content in file
        cout << "content in out.txt" << endl;
        for (int i = 0; i < ct; ++i) pc[i]->ShowAll();
    }

    // fill the array
    show_menu();
    char choice;
    abstr_emp* p;
    while (cin >> choice && choice != 'q' && ct < MAX) {
        eatline();
        switch (choice) {
            case 'e':  // employee
                p = new employee;
                p->SetAll();
                pc[ct] = p;
                break;
            case 'm':  // manager
                p = new manager;
                p->SetAll();
                pc[ct] = p;
                break;
            case 'f':  // fink
                p = new fink;
                p->SetAll();
                pc[ct] = p;
                break;
            case 'h':  // highfink
                p = new highfink;
                p->SetAll();
                pc[ct] = p;
                break;
        }
        ct++;
        show_menu();
    }

    // show all input
    for (int i = 0; i < ct; ++i) pc[i]->ShowAll();

    // write to files
    ofstream fout("out.txt", ios_base::out);
    for (int i = 0; i < ct; ++i) {
        pc[i]->WriteAll(fout);
        fout << endl;
    }
    fout.close();

    cout << "content in array are written to out.txt" << endl;

    // free memories
    for (int i = 0; i < ct; ++i) delete pc[i];

    return 0;
}

void show_menu() {
    ios_base::fmtflags old_fmt = cout.setf(ios_base::left, ios_base::adjustfield);

    show_line(35);
    cout.width(20);
    cout << "e. employee";
    cout << "m. manager" << endl;
    cout.width(20);
    cout << "f. fink";
    cout << "h. highfink" << endl;
    cout << "q. quit" << endl;
    show_line(35);
    cout << "Select a type: " << endl;

    cout.setf(old_fmt);
}

inline void show_line(int n) {
    cout.fill('-');
    cout.width(n);
    cout << "-" << endl;
    cout.fill(' ');
}

inline void eatline() {
    while (cin.get() != '\n') continue;
}

7. 下面是某个程序的部分代码。该程序将键盘输入读取到一个由string对象组成的vector中,将字符串内容(而不是string对象)存储到一个文件中,然后该文件的内容复制到另一个由string对象组成的vector中。

代码语言:javascript
复制
int main()
{
    using namespace std;
    vector<string> vostr;
    string temp;
    // acquire strings
    cout << "Enter strings (empty line to quit):\n";
    while (getline(cin,temp) && temp[0] != '\0')
        vostr.push_back(temp);
    cout << "Here is your input.\n";
    for_each(vostr.begin(), vostr.end(), ShowStr);
    // store in a file
    ofstream fout("strings.dat", ios_base::out | ios_base::binary);
    for_each(vostr.begin(), vostr.end(), Store(fout));
    fout.close();
    // recover file contents
    vector<string> vistr;
    ifstream fin("strings.dat", ios_base::in | ios_base::binary);
    if (!fin.is_open())
    {
        cerr << "Could not open file for input.\n";
        exit(EXIT_FAILURE);
    }
    GetStrs(fin, vistr);
    cout << "\nHere are the strings read from the file:\n";
    for_each(vistr.begin(), vistr.end(), ShowStr);
    return 0;
}

该程序以二进制格式打开文件,并想使用read( )和write( )来完成I/O。余下的工作如下所述。

  • 编写函数void ShowStr(const string &),它显示一个string对象,并在显示完后换行。
  • 编写函数符Store,它将字符串信息写入到文件中。Store的构造函数应接受一个指定ifstream对象的参数,而重载的operator( )(const string &)应指出要写入到文件中的字符串。一种可行的计划是,首先将字符串的长度写入到文件中,然后将字符串的内容写入到文件中。例如,如果len存储了字符串的长度,可以这样做:
代码语言:javascript
复制
os.write((char *)&len, sizeof(std::size_t)); // store length
os.write(s.data(), len); // store characters

成员函数data( )返回一个指针,该指针指向一个其中存储了字符串中字符的数组。它类似于成员函数c_str( ),只是后者在数组末尾加上了一个空字符。

  • 编写函数GetStrs( ),它根据文件恢复信息。该函数可以使用read( )来获得字符串的长度,然后使用一个循环从文件中读取相应数量的字符,并将它们附加到一个原来为空的临时string末尾。由于string的数据是私有的,因此必须使用string类的方法来将数据存储到string对象中,而不能直接存储。

main.cpp:

代码语言:javascript
复制
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Store {
    private:
    ostream& os;

    public:
    Store(ostream& o) : os(o){};
    void operator()(const string& s) {
        size_t len = s.length();

        // store string length
        os.write((char*)&len, sizeof(std::size_t));
        // store string data
        os.write(s.data(), len);
    }
};
inline void ShowStr(const std::string& s) { cout << s << endl; };
void GetStrs(std::ifstream& fin, std::vector<std::string>& vistr);

int main() {
    using namespace std;
    vector<string> vostr;
    string temp;

    // acquire strings
    cout << "Enter strings (empty line to quit):\n";
    while (getline(cin, temp) && temp[0] != '\0') vostr.push_back(temp);
    cout << "Here is your input.\n";
    for_each(vostr.begin(), vostr.end(), ShowStr);

    // store in a file
    ofstream fout("strings.dat", ios_base::out | ios_base::binary);
    for_each(vostr.begin(), vostr.end(), Store(fout));
    fout.close();

    // recover file contents
    vector<string> vistr;
    ifstream fin("strings.dat", ios_base::in | ios_base::binary);
    if (!fin.is_open()) {
        cerr << "Could not open file for input.\n";
        exit(EXIT_FAILURE);
    }
    GetStrs(fin, vistr);
    cout << "\nHere are the strings read from the file:\n";
    for_each(vistr.begin(), vistr.end(), ShowStr);
    return 0;
}

void GetStrs(std::ifstream& fin, std::vector<std::string>& vistr) {
    size_t len;  // string length
    while (fin.read((char*)&len, sizeof(std::size_t))) {
        string str;
        char ch;
        for (int i = 0; i < len; ++i) {
            fin.read(&ch, sizeof(char));
            str.push_back(ch);
        }

        // put string to vector
        vistr.push_back(str);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-02-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iDoitnow 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 复习题
  • 编程练习
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档