C++ Primer Plus習(xí)題及答案-第十七章

習(xí)題選自:C++ Primer Plus(第六版)
內(nèi)容僅供參考件甥,如有錯(cuò)誤漠嵌,歡迎指正 !

cout格式化輸出

使用cin進(jìn)行輸入

文件的輸入和輸出

復(fù)習(xí)題

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

iostream文件定義了用于管理輸入和輸出的類概行、常量和操作符蠢挡,這些對象用于I/O的流和緩沖區(qū)。該文件還創(chuàng)建了一些用于處理標(biāo)準(zhǔn)輸入輸出流的標(biāo)準(zhǔn)對象(如cin凳忙、cout业踏、cerr和clog以及對應(yīng)的寬字符對象)。

2. 為什么鍵入數(shù)字(如121)作為輸入要求程序進(jìn)行轉(zhuǎn)換涧卵?

鍵盤輸入會生成一系列字符勤家,輸入121將會生成3個(gè)字符,每個(gè)字符都由一個(gè)字節(jié)的二進(jìn)制碼表示柳恐。要將這個(gè)值存儲為int類型伐脖,則必須將這3個(gè)字符轉(zhuǎn)換為121值的二進(jìn)制表示。

3. 標(biāo)準(zhǔn)輸出與標(biāo)準(zhǔn)錯(cuò)誤之間有什么區(qū)別乐设?

默認(rèn)情況下兩者都將輸出發(fā)給標(biāo)準(zhǔn)輸出設(shè)備(通常為顯示器)讼庇。然而,如果要求操作系統(tǒng)操作系統(tǒng)將輸出重定向到文件近尚,則標(biāo)準(zhǔn)輸出將與文件相連蠕啄,但標(biāo)準(zhǔn)錯(cuò)誤仍與顯示器相連。

4. 為什么在不為每個(gè)類型提供明確指示的情況下,cout仍能夠顯示不同的C++類型歼跟?

ostream類為每種C++基本類型定義了一個(gè)operator <<()函數(shù)的版本和媳。編譯器將類似cout << spot的表達(dá)式解釋為cout.operator<<(spot),這樣哈街,它便能夠?qū)⒃摲椒ㄕ{(diào)用與具有相同參數(shù)類型的函數(shù)原型匹配留瞳。

5. 輸出方法的定義的哪一特征讓您能夠拼接輸出?

返回ostream &類型的輸出方法能夠拼接輸出叹卷。通過一個(gè)對象調(diào)用方法時(shí)撼港,將返回該對象。然后骤竹,返回對象將可以調(diào)用序列中的下一個(gè)方法

6. 編寫一個(gè)程序帝牡,要求用戶輸入一個(gè)整數(shù),然后以十進(jìn)制蒙揣、八進(jìn)制和十六進(jìn)制顯示該整數(shù)靶溜。在寬度為15個(gè)字符的字段中顯示每種形式,并將它們顯示在同一行上懒震,同時(shí)使用C++數(shù)基前綴罩息。

#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. 編寫一個(gè)程序,請求用戶輸入下面的信息个扰,并按下面的格式顯示它們:

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:

#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. 對于下面的程序:

//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;
}

如果輸入如下瓷炮,該程序?qū)⒋蛴∈裁磧?nèi)容?

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

其中递宅,<Enter>表示按回車鍵娘香。

使用cin >> ch;會自動忽略空格和換行符,因此ct1的值應(yīng)為5办龄。而cin.get(ch);不忽略空格和換行符烘绽,且第一次輸入的回車鍵,也會被cin.get(ch);捕捉到俐填,因此ct2的值應(yīng)為9安接。打印內(nèi)容如下:

ct1 = 5; ct2 = 9

9. 下面的兩條語句都讀取并丟棄行尾之前的所有字符(包括行尾)。這兩條語句的行為在哪方面不同英融?

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

如果輸入超過80個(gè)字符盏檐,且這80個(gè)字符中沒有出現(xiàn)'\n',則ignore()會將前80個(gè)字符都會拋棄掉驶悟,然后再開始執(zhí)行后面的語句胡野。也就是說當(dāng)輸入超過80個(gè)字符,且這80個(gè)字符中沒有出現(xiàn)'\n'撩银,cin.ignore(80, '\n');讀取并丟棄行尾之前的所有字符(包括行尾)的作用可能會不符合預(yù)期给涕。而第一條語句沒有該限制豺憔《罨瘢【注:可以將第二個(gè)語句中80改為numeric_limits<streamsize>::max()來解除該限制】

編程練習(xí)

1. 編寫一個(gè)程序計(jì)算輸入流中第一個(gè)$之前的字符數(shù)目够庙,并將$留在輸入流中。

main.cpp:

#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. 編寫一個(gè)程序抄邀,將鍵盤輸入(直到模擬的文件尾)復(fù)制到通過命令行指定的文件中耘眨。

main.cpp:

#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下鍵盤模擬輸入文件結(jié)束符為Ctrl+D

3. 編寫一個(gè)程序,將一個(gè)文件復(fù)制到另一個(gè)文件中境肾。讓程序通過命令行獲取文件名剔难。如果文件無法打開,程序?qū)⒅赋鲞@一點(diǎn)奥喻。

main.cpp:

#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. 編寫一個(gè)程序偶宫,它打開兩個(gè)文本文件進(jìn)行輸入,打開一個(gè)文本文件進(jìn)行輸出环鲤。該程序?qū)蓚€(gè)輸入文件中對應(yīng)的行拼接起來纯趋,并用空格分隔,然后將結(jié)果寫入到輸出文件中冷离。如果一個(gè)文件比另一個(gè)短吵冒,則將較長文件中余下的幾行直接復(fù)制到輸出文件中。例如西剥,假設(shè)第一個(gè)輸入文件的內(nèi)容如下:

eggs kites donuts
balloons hammers
stones

而第二個(gè)輸入文件的內(nèi)容如下:

zero lassitude
finance drama

則得到的文件的內(nèi)容將如下:

eggs kites donuts zero lassitude
balloons hammers finance drama
stones

main.cpp:

#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章中的編程練習(xí)8那樣,但現(xiàn)在他們希望程序使用文件瞭空。他們請您編寫一個(gè)完成下述任務(wù)的程序揪阿。

  • 從文本文件mat.dat中讀取Mat朋友的姓名清單,其中每行為一個(gè)朋友匙铡。姓名將被存儲在容器图甜,然后按順序顯示出來。
  • 從文本文件pat.dat中讀取Pat朋友的姓名清單鳖眼,其中每行為一個(gè)朋友黑毅。姓名將被存儲在容器中,然后按順序顯示出來钦讳。
  • 合并兩個(gè)清單矿瘦,刪除重復(fù)的條目,并將結(jié)果保存在文件matnpat.dat中愿卒,其中每行為一個(gè)朋友缚去。

main.cpp:

#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章的編程練習(xí)5中的類定義。如果還沒有完成這個(gè)練習(xí)琼开,請現(xiàn)在就做易结,然后完成下面的任務(wù)。

編寫一個(gè)程序,它使用標(biāo)準(zhǔn)C++ I/O搞动、文件I/O以及14章的編程練習(xí)5中定義的employee躏精、manager、fink和highfink類型的數(shù)據(jù)鹦肿。該程序應(yīng)包含程序清單17.17中的代碼行矗烛,即允許用戶將新數(shù)據(jù)添加到文件中。該程序首次被運(yùn)行時(shí)箩溃,將要求用戶輸入數(shù)據(jù)瞭吃,然后顯示所有的數(shù)據(jù),并將這些信息保存到一個(gè)文件中涣旨。當(dāng)該程序再次被運(yùn)行時(shí)歪架,將首先讀取并顯示文件中的數(shù)據(jù),然后讓用戶添加數(shù)據(jù)霹陡,并顯示所有的數(shù)據(jù)牡拇。差別之一是,應(yīng)通過一個(gè)指向employee類型的指針數(shù)組來處理數(shù)據(jù)穆律。這樣吵瞻,指針可以指向employee對象丈氓,也可以指向從employee派生出來的其他三種對象中的任何一種。使數(shù)組較小有助于檢查程序,例如癌压,您可能將數(shù)組限定為最多包含10個(gè)元素:

const int MAX = 10; // no more than 10 objects
...
employee * pc[MAX];

為通過鍵盤輸入募强,程序應(yīng)使用一個(gè)菜單浪感,讓用戶選擇要?jiǎng)?chuàng)建的對象類型更卒。菜單將使用一個(gè)switch,以便使用new來創(chuàng)建指定類型的對象洛口,并將它的地址賦給pc數(shù)組中的一個(gè)指針矫付。然后該對象可以使用虛函數(shù)setall( )來提示用戶輸入相應(yīng)的數(shù)據(jù):

pc[i]->setall(); // invokes function corresponding to type of object

為將數(shù)據(jù)保存到文件中,應(yīng)設(shè)計(jì)一個(gè)虛函數(shù)writeall( ):

for (i = 0; i < index; i++)
pc[i]->writeall(fout);// fout ofstream connected to output file

注意】:

對于這個(gè)練習(xí)第焰,應(yīng)使用文本I/O买优,而不是二進(jìn)制I/O(遺憾的是,虛對象包含指向虛函數(shù)指針表的指針挺举,而write( )將把這種信息復(fù)制到文件中杀赢。使用read( )讀取文件的內(nèi)容,以填充對象時(shí)湘纵,函數(shù)指針值將為亂碼脂崔,這將擾亂虛函數(shù)的行為)∥嗯纾可使用換行符將字段分隔開砌左,這樣在輸入時(shí)將很容易識別各個(gè)字段脖咐。也可以使用二進(jìn)制I/O,但不能將對象作為一個(gè)整體寫入汇歹,而應(yīng)該提供分別對每個(gè)類成員應(yīng)用write( )和read( )的類方法文搂。這樣,程序?qū)⒅话阉璧臄?shù)據(jù)保存到文件中秤朗。

比較難處理的部分是使用文件恢復(fù)數(shù)據(jù)。問題在于:程序如何才能知道接下來要恢復(fù)的項(xiàng)目是employee對象笔喉、manager對象取视、fink對象還是highfink對象?一種方法是常挚,在對象的數(shù)據(jù)寫入文件時(shí)作谭,在數(shù)據(jù)前面加上一個(gè)指示對象類型的整數(shù)。這樣奄毡,在文件輸入時(shí)折欠,程序便可以讀取該整數(shù),并使用switch語句創(chuàng)建一個(gè)適當(dāng)?shù)膶ο髞斫邮諗?shù)據(jù):

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;

然后便可以使用指針調(diào)用虛函數(shù)getall( )來讀取信息:

pc[i++]->getall();

emp.h:

#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:

#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:

#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. 下面是某個(gè)程序的部分代碼吼过。該程序?qū)㈡I盤輸入讀取到一個(gè)由string對象組成的vector中锐秦,將字符串內(nèi)容(而不是string對象)存儲到一個(gè)文件中,然后該文件的內(nèi)容復(fù)制到另一個(gè)由string對象組成的vector中盗忱。

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;
}

該程序以二進(jìn)制格式打開文件酱床,并想使用read( )和write( )來完成I/O。余下的工作如下所述趟佃。

  • 編寫函數(shù)void ShowStr(const string &)扇谣,它顯示一個(gè)string對象,并在顯示完后換行闲昭。

  • 編寫函數(shù)符Store罐寨,它將字符串信息寫入到文件中。Store的構(gòu)造函數(shù)應(yīng)接受一個(gè)指定ifstream對象的參數(shù)序矩,而重載的operator( )(const string &)應(yīng)指出要寫入到文件中的字符串鸯绿。一種可行的計(jì)劃是,首先將字符串的長度寫入到文件中簸淀,然后將字符串的內(nèi)容寫入到文件中楞慈。例如,如果len存儲了字符串的長度啃擦,可以這樣做:

    os.write((char *)&len, sizeof(std::size_t)); // store length
    os.write(s.data(), len); // store characters
    

    成員函數(shù)data( )返回一個(gè)指針囊蓝,該指針指向一個(gè)其中存儲了字符串中字符的數(shù)組。它類似于成員函數(shù)c_str( )令蛉,只是后者在數(shù)組末尾加上了一個(gè)空字符聚霜。

  • 編寫函數(shù)GetStrs( )狡恬,它根據(jù)文件恢復(fù)信息。該函數(shù)可以使用read( )來獲得字符串的長度蝎宇,然后使用一個(gè)循環(huán)從文件中讀取相應(yīng)數(shù)量的字符弟劲,并將它們附加到一個(gè)原來為空的臨時(shí)string末尾。由于string的數(shù)據(jù)是私有的姥芥,因此必須使用string類的方法來將數(shù)據(jù)存儲到string對象中兔乞,而不能直接存儲。

main.cpp:

#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);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凉唐,一起剝皮案震驚了整個(gè)濱河市庸追,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌台囱,老刑警劉巖淡溯,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異簿训,居然都是意外死亡咱娶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門强品,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膘侮,“玉大人,你說我怎么就攤上這事的榛∮髟” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵困曙,是天一觀的道長表伦。 經(jīng)常有香客問我,道長慷丽,這世上最難降的妖魔是什么蹦哼? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮要糊,結(jié)果婚禮上纲熏,老公的妹妹穿的比我還像新娘。我一直安慰自己锄俄,他們只是感情好局劲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奶赠,像睡著了一般鱼填。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上毅戈,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天苹丸,我揣著相機(jī)與錄音愤惰,去河邊找鬼。 笑死赘理,一個(gè)胖子當(dāng)著我的面吹牛宦言,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播商模,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼奠旺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了施流?” 一聲冷哼從身側(cè)響起响疚,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嫂沉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扮碧,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡趟章,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了慎王。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚓土。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赖淤,靈堂內(nèi)的尸體忽然破棺而出蜀漆,到底是詐尸還是另有隱情,我是刑警寧澤咱旱,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布确丢,位于F島的核電站,受9級特大地震影響吐限,放射性物質(zhì)發(fā)生泄漏鲜侥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一诸典、第九天 我趴在偏房一處隱蔽的房頂上張望描函。 院中可真熱鬧,春花似錦狐粱、人聲如沸舀寓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽互墓。三九已至,卻和暖如春蒋搜,著一層夾襖步出監(jiān)牢的瞬間轰豆,已是汗流浹背胰伍。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酸休,地道東北人骂租。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像斑司,于是被迫代替她去往敵國和親渗饮。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容