習(xí)題選自:C++ Primer Plus(第六版)
內(nèi)容僅供參考件甥,如有錯(cuò)誤漠嵌,歡迎指正 !
復(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);
}
}