习题选自: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。打印内容如下:
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] != '