编程练习
-
编写一个程序计算输入流中第一个$之前的字符数目,并将$留在输入流中。
#include<iostream> int main() { int ct = 0; while(std::cin.peek()!='$'){ ct++; std::cin.get(); } std::cout << "num: " << ct << std::endl; return 0; }
答:
#include<iostream> int main() { int ct = 0; while(std::cin.peek()!='$'){ ct++; std::cin.get(); } std::cout << "num: " << ct << std::endl; return 0; }
-
编写一个程序,将键盘输入(直到模拟的文件尾)复制到通过命令行指定的文件中。
#include <cstdlib> #include <iostream> #include <fstream> #include <string> int main(int argc, char *argv[]){ if(argc<2){ std::cout << "Usage: " << argv[0] << " <filename>" << std::endl; exit(EXIT_FAILURE); } std::fstream fs; for(int file = 1; file < argc; file++){ fs.open(argv[file], std::ios_base::out); if(!fs.is_open()){ std::cerr << "error happens when open " << argv[file] << ".\n"; exit(EXIT_FAILURE); } std::cout << "Please enter your input: \n"; std::string input; getline(std::cin, input); while(input.size()>0){ fs << input << std::endl; getline(std::cin, input); } fs.clear(); fs.close(); fs.open(argv[file], std::ios_base::in); if(!fs.is_open()){ std::cerr << "error happens when open " << argv[file] << ".\n"; exit(EXIT_FAILURE); } std::cout << "The content of the " << argv[file] << ":\n"; char ch; while(fs.get(ch)){ std::cout << ch; } if(!fs.eof()){ std::cerr << "error happens when read " << argv[file] << ".\n"; exit(EXIT_FAILURE); } return 0; } }
答:
#include <cstdlib> #include <iostream> #include <fstream> #include <string> int main(int argc, char *argv[]){ if(argc<2){ std::cout << "Usage: " << argv[0] << " <filename>" << std::endl; exit(EXIT_FAILURE); } std::fstream fs; for(int file = 1; file < argc; file++){ fs.open(argv[file], std::ios_base::out); if(!fs.is_open()){ std::cerr << "error happens when open " << argv[file] << ".\n"; exit(EXIT_FAILURE); } std::cout << "Please enter your input: \n"; std::string input; getline(std::cin, input); while(input.size()>0){ fs << input << std::endl; getline(std::cin, input); } fs.clear(); fs.close(); fs.open(argv[file], std::ios_base::in); if(!fs.is_open()){ std::cerr << "error happens when open " << argv[file] << ".\n"; exit(EXIT_FAILURE); } std::cout << "The content of the " << argv[file] << ":\n"; char ch; while(fs.get(ch)){ std::cout << ch; } if(!fs.eof()){ std::cerr << "error happens when read " << argv[file] << ".\n"; exit(EXIT_FAILURE); } return 0; } }
-
编写一个程序,将一个文件复制到另一个文件中。让程序通过命令行获取文件名。如果文件无法打开,程序将指出这一点。
//#include <cstdlib> #include<fstream> #include<iostream> #include<string> int main(int argc, char* argv[]){ if(argc!=3){ std::cout << "Usage: " << argv[0] << " <target filename> <sourse filename>.\n"; exit(EXIT_FAILURE); } std::ofstream ofs; ofs.open(argv[1], std::ios_base::out); if(!ofs.is_open()){ std::cerr << "Error happen when open " << argv[1] << ".\n"; exit(EXIT_FAILURE); } std::ifstream ifs; ifs.open(argv[2], std::ios_base::in); if(!ifs.is_open()){ std::cerr << "Error happen when open " << argv[2] << ".\n"; exit(EXIT_FAILURE); } std::string line; getline(ifs,line); while(line.size()>0){ ofs << line << std::endl; getline(ifs,line); } if(!ifs.eof()){ std::cerr << "Error happens when read " << argv[1] << ".\n"; } return 0; }
答:
//#include <cstdlib> #include<fstream> #include<iostream> #include<string> int main(int argc, char* argv[]){ if(argc!=3){ std::cout << "Usage: " << argv[0] << " <target filename> <sourse filename>.\n"; exit(EXIT_FAILURE); } std::ofstream ofs; ofs.open(argv[1], std::ios_base::out); if(!ofs.is_open()){ std::cerr << "Error happen when open " << argv[1] << ".\n"; exit(EXIT_FAILURE); } std::ifstream ifs; ifs.open(argv[2], std::ios_base::in); if(!ifs.is_open()){ std::cerr << "Error happen when open " << argv[2] << ".\n"; exit(EXIT_FAILURE); } std::string line; getline(ifs,line); while(line.size()>0){ ofs << line << std::endl; getline(ifs,line); } if(!ifs.eof()){ std::cerr << "Error happens when read " << argv[1] << ".\n"; } return 0; }
-
编写一个程序,它打开两个文本文件进行输入,打开一个文本文件进行输出。该程序将两个输入文件中对应的行并接起来,并用空格分隔,然后将结果写入到输出文件中。如果一个文件比另一个短,则将较长文件中余下的几行值复制到输出文件中。例如,假设第一个输入文件的内容如下:
eggs kites donuts balloons hammers stones
而第二个输入文件的内容如下:
zero lassitude finance drama
则得到的文件的内容将如下:
eggs kites donuts zero lassitude balloons hammers finance drama stones
答:
#include <cstdlib> #include<iostream> #include<fstream> #include<string> using namespace std; int main(int argc, char* argv[]) { if(argc!=4){ cerr << "Usage: " << argv[0] << " <source file1> <source file2> <target file>.\n"; exit(EXIT_FAILURE); } ifstream ifs1(argv[1], ios_base::in); ifstream ifs2(argv[2], ios_base::in); ofstream ofs(argv[3], ios_base::out); if(!ifs1.is_open()) { cerr << "Error when open " << argv[1] << ".\n"; } if(!ifs2.is_open()) { cerr << "Error when open " << argv[2] << ".\n"; } string line1, line2; getline(ifs1, line1); getline(ifs2,line2); while(line1.size() >0 && line2.size() >0 ){ ofs << line1 << ' ' << line2 << endl; getline(ifs1, line1); getline(ifs2,line2); } if(!ifs1.eof()){ while(line1.size()>0){ ofs << line1 << endl; getline(ifs1, line1); } } if(!ifs2.eof()){ while(line2.size()>0){ ofs << line2 << endl; getline(ifs2, line2); } } return 0; }
-
Mat 和 Pat 想邀请他们的朋友来参加派对,就像第16章中的编程练习8那样,但现在他们希望程序使用文件。他们请您编写一个完成下述任务的程序。
- 从文本文件 mat.dat 中读取 Mat 朋友的清单,其中每行为一个朋友。姓名将被存储在容器,然后按顺序显示出来。
- 从文本文件 pat.dat 中读取 Pat 朋友的姓名清单,其中每行为一个朋友。姓名将被存储在容器,然后按顺序显示出来。
- 合并两个清单,删除重复的条目,并将结果保存在文件 matnpat.dat 中,其中每行为一个朋友。
答:
#include <cstdlib> #include<iostream> #include<fstream> #include<string> #include<vector> #include<set> int main() { using namespace std; ifstream matin("mat.dat", ios_base::in); ifstream patin("pat.dat", ios_base::in); if(!(matin && patin)){ cerr << "Failed to open input files.\n"; exit(EXIT_FAILURE); } ofstream matnpatout("matnpat.dat", ios_base::out); if(!matnpatout.is_open()){ cerr << "Failed to open output files.\n"; exit(EXIT_FAILURE); } vector<string> mat; vector<string> pat; string name; while(!matin.eof()) { getline(matin, name); mat.push_back(name); } cout << "Success" << endl; while(!patin.eof()) { getline(patin, name); pat.push_back(name); } cout << "Mat's friends:\n"; for(auto& name : mat){ cout << name << endl; } cout << "Pat's friends:\n"; for(auto& name : pat) { cout << name << endl; } set<string> matnpat; matnpat.insert(mat.begin(), mat.end()); matnpat.insert(pat.begin(), pat.end()); for(auto& name : matnpat) { matnpatout << name << endl; } return 0; }
-
编写一个程序,它使用标准 C++ I/O、文件 I/O 以及 14 章的编程练习5中定义的 employee、manager、fink 和 highfink 类型的数据。该程序应包含程序17.7中的代码行,即允许用户将新数据添加到文件中。该程序首次被运行时,将要求用户输入数据,然后显示所有数据,并将这些信息保存到一个文件中。当该程序再次被运行时,将首先读取并显示文件中的数据,然后让用户添加数据,并显示所有的数据。差别之一是,应通过一个指向 employee 类型的指针来处理数据。这样,指针可以指向 employee 对象,也可以指向从 employee 派生出来的其他三种对象中的任何一种。使数组较小有助于检查程序,例如,您可能将数组限定为最多包含 10 个元素:
const int MAX = 10; // no more than 10 objects ... employee * pc [MAX];
为通过键盘输入,程序应使用一个菜单,让用户选择要创建的对象类型。菜单将使用一个 switch,以便使用 new 来创建指定类型的对象,并将它的地址赋给 pc 数组中的一个指针。然后该对象可以使用虚函数 setall() 来提示用户输入相应的数据:
pc[i] -> setall(); // invokes function corresponding to type of object
为将数据保存到文件中,应设计一个虚函数 writeall():
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 语句创建一个适当的对象来接收数据:
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() 来读取信息:
pc[i++] -> getall();
答:
emp.h#ifndef EMP_H_ #define EMP_H_ #include<iostream> #include<fstream> #include<string> enum classkind {Employee, Manager, Fink, Highfink}; // in class header class ab_emp {; private: std::string fname; std::string lname; std::string job; public: ab_emp(); ab_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 ab_emp & e); virtual ~ab_emp() = 0; }; class employee : virtual public ab_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 & of) const; }; class manager : virtual public ab_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 ab_emp & e, int ico); manager(const manager & m); virtual void ShowAll() const; virtual void SetAll(); std::ofstream & WriteAll(std::ofstream & of) const; }; class fink : virtual public ab_emp { private: std::string reportsto; protected: 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 repo); fink(const ab_emp & e, const std::string repo); fink(const fink & f); virtual void ShowAll() const; virtual void SetAll(); std::ofstream & WriteAll(std::ofstream & of) 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 ab_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"17-6_emp.h" #include <fstream> #include <ostream> #include <string> // ab_emp methods ab_emp::ab_emp() { fname = "none"; lname = "none"; job = "none"; } ab_emp::ab_emp(const std::string & fn, const std::string & ln, const std::string & j) : fname(fn), lname(ln), job(j) { } ab_emp::~ab_emp() {} void ab_emp::ShowAll() const { std::cout << "firstname: " << fname << std::endl; std::cout << "lastname: " << lname << std::endl; std::cout << "job: " << job << std::endl; } void ab_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 & ab_emp::WriteAll (std::ofstream &of) const{ of << fname << " " << lname << " " << job; return of; } std::ostream & operator<<(std::ostream & os, const ab_emp & e){ os << e.fname << " " << e.lname << " " << e.job; return os; } // employee methods employee::employee(){} employee::employee(const std::string & fn, const std::string & ln, const std::string & j): ab_emp(fn, ln, j) { } void employee::ShowAll() const { ab_emp::ShowAll(); } void employee::SetAll() { ab_emp::SetAll(); } std::ofstream & employee::WriteAll(std::ofstream &of) const { of << Employee << " "; ab_emp::WriteAll(of); return of; } // manager methods manager::manager() { inchargeof = 0; } manager::manager(const std::string & fn, const std::string & ln, const std::string & job, int ico) : ab_emp(fn, ln, job), inchargeof(ico) { } manager::manager(const ab_emp & e, int ico) : ab_emp(e), inchargeof(ico) { } manager::manager(const manager & m) : ab_emp(m), inchargeof(m.inchargeof){ } void manager::ShowAll() const { ab_emp::ShowAll(); std::cout << "InchargeOf: " << inchargeof << std::endl; } void manager::SetAll() { ab_emp::SetAll(); std::cout << "Enter inchargeof: "; std::cin >> inchargeof; std::cin.get(); } std::ofstream & manager::WriteAll(std::ofstream &of) const { of << Manager << " "; ab_emp::WriteAll(of) << " " << inchargeof; return of; } // fink methods fink::fink() { reportsto = "none"; } fink::fink(const std::string & fn, const std::string ln, const std::string & job, const std::string repo) : ab_emp(fn,ln,job), reportsto(repo) { } fink::fink(const ab_emp & e, const std::string repo) : ab_emp(e), reportsto(repo) { } fink::fink(const fink & f) : ab_emp(f) ,reportsto(f.reportsto) { } void fink::ShowAll() const { ab_emp::ShowAll(); std::cout << "Reportsto: " << reportsto << std::endl; } void fink::SetAll() { ab_emp::SetAll(); std::cout << "Enter reportsto: "; std::getline(std::cin, reportsto); } std::ofstream & fink::WriteAll(std::ofstream & fout) const { fout << Fink << " "; ab_emp::WriteAll(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 & repo, int ico) : ab_emp(fn,ln,j), manager(fn,ln,j,ico), fink(fn,ln,j, repo) { } highfink::highfink(const ab_emp & e, const std::string & repo, int ico) : ab_emp(e), manager(e,ico), fink(e,repo) { } highfink::highfink(const fink & f, int ico) : ab_emp(f), fink(f), manager((const ab_emp &)f, ico) { } highfink::highfink(const manager & m, const std::string & repo) : ab_emp(m), manager(m), fink((const ab_emp &)m, repo) { } highfink::highfink(const highfink & h) : ab_emp(h), manager(h), fink(h) { } void highfink::ShowAll() const { ab_emp::ShowAll(); std::cout << "ReportsTo: " << fink::ReportsTo() << std::endl; std::cout << "Inchargeof: "<< manager::InChargeOf() << std::endl; } void highfink::SetAll() { ab_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 << " "; ab_emp::WriteAll(fout) << " " << fink::ReportsTo() << " " << manager::InChargeOf(); return fout; }
main.cpp
#include"17-6_emp.h" #include <fstream> using namespace std; inline void showline(int n); void show_menu(); inline void eatline(); const int MAX = 10; int main() { ab_emp* pc[MAX]; int ct; // number counter string fname, lname, job, reportsto; int inchargeof; // read from file ifstream fin("out.txt", ios_base::in); if(fin.is_open()){ 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); break; } ct++; } cout << "content in out.txt: " << endl; for(int i=0; i<ct; i++){ pc[i]->ShowAll(); } fin.close(); } // add elements char choice; show_menu(); while(cin>>choice && choice!='q' && ct<MAX){ eatline(); switch (choice) { case 'e': pc[ct] = new employee; pc[ct]->SetAll(); break; case 'm': pc[ct] = new manager; pc[ct]->SetAll(); break; case 'f': pc[ct] = new fink; pc[ct]->SetAll(); break; case 'h': pc[ct] = new highfink; pc[ct]->SetAll(); break; } ct++; show_menu(); } for(int i=0 ; i<ct; i++){ pc[i]->ShowAll(); } // write to file ofstream fout("out.txt", ios_base::out); for(int i=0; i<ct; i++){ pc[i]->WriteAll(fout); fout << endl; } fout.close(); cout << "all contents written to out.txt\n"; 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); showline(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; showline(35); cout << "Select a type: " << endl; cout.setf(old_fmt); } inline void showline(int n){ cout.fill('-'); cout.width(n); cout << "-" << endl; cout.fill(' '); } inline void eatline() { while(cin.get() != '\n') continue; }
-
下面是某个程序的部分代码。该程序将键盘输入读取到一个由 string 对象组成的 vector 中,将字符串内容(而不是 string 对象)存储到一个文件中,然后该文件的内容复制到另一个由 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 intput.\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 存储了字符串的长度,可以这样做:
成员函数 data() 返回一个指针,该指针指向一个其中存储了字符串中字符的数组。它类似于成员函数 c_str(),只是后者在数组末尾加上了一个空字符。os.write((char *) &len, sizeof(std::size_t)); // store length os.write(s.data(), len);
- 编写函数 GetStrs(),它根据文件恢复信息。该函数可以使用 read() 来获得字符串的长度,然后使用一个循环从文件中读取相应数量的字符,并将它们附加到一个原来为空的临时 string 末尾。由于 string 的数据是私有的,因此必须使用 string 类的方法来将数据存储到 string 对象中,而不能直接存储。
答:
#include <cstddef> #include <cstdlib> #include <ios> #include<iostream> #include<fstream> #include <ostream> #include<vector> #include<string> #include<algorithm> using namespace std; class Store { private: ostream &os; public: Store(ostream &o):os(o){} void operator()(const string & s){ size_t len = s.length(); os.write((const char *)&len, sizeof(std::size_t)); 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.size()>0){ vostr.push_back(temp); } for_each(vostr.begin(), vostr.end(), ShowStr); // store in a file ofstream fout("string.dat", ios_base::out|ios_base::binary); for_each(vostr.begin(), vostr.end(), Store(fout)); fout.close(); cin.get(); // recover file contents vector<string> vistr; ifstream fin("string.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(size_t) ) ){ string str; char ch; for(int i=0; i< len; i++){ fin.read(&ch,sizeof(char)); str.push_back(ch); } vistr.push_back(str); } }