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

习题选自:C++ Primer Plus(第六版)
内容仅供参考,如有错误,欢迎指正 !

1.简单文件输入/输出(写入到文本文件中)
对于文件输入,C++使用类似于cout的东西。对于cout,需要包含iostream头文件,该头文件定义了一个用于输出的ostream类,并且在该头文件中声明了一个cout的ostream变量(对象)。而在使用到文本写入文件时,需要包含头文件fstream,该头文件定义了一个ofstream类,使用的时候需要声明一个ofstream类,声明完成后需要通过open()方法将声明的对象与文件关联起来,例如:
ofstream outFile;
outFile.open("filename.txt");
然后就可以像使用cout一样使用该ofstream对象。将在屏幕上打印的数据信息,存储到文件中去。最后使用close()方法将其关闭。

  • cout<<fixed outFile<<fixed用一般的方式输出浮点型,例如C++程序在控制台显示大一点的数,显示的时候使用了科学计数法,使用该命令即可像一般的方式显示。
  • cout.precision(2)outFile.precision(2)设置精确度为2,并返回上一次的设置。
  • cout.setf(iOS_base::showpoint)outFile.setf(iOS_base::showpoint) 显示浮点数小数点后面的零。

2.简单文件输入/输出(读取文本文件)
对于文件读取,同样的,C++使用类似cin的东西。对于cin,需要包含iostream头文件,该文件定义了一个用于输入的istream类,并在该头文件中已经声明好了一个cin的istream变量(对象)。而在使用读取文件时,需要包含fstream头文件,该头文件定义了ifostream类,在使用的时候需要声明一个ifstream类,通过open()方法与文件关联起来,然后就可以像使用cin一样使用该ifstream,读取目标文件的内容。最后,使用close()方法将文件关闭。

  • 可以结合ifstream对象和运算符>>来读取各种类型的数据。
  • 可以使用ifstream对象与get()方法读取一个字符,使用getline()来读取一行字符。
  • 可以结合使用ifstream与eof()、fail()等方法判断输入是否成功。

复习题

1 .请看下面两个计算空格和换行符数目的代码片段:
//version 1
while(cin.get(ch))   //quit on eof
{  
    if(ch==' ')
         spaces++;
    if(ch=='\n')
         newlines++;
}

//version 2
while(cin.get(ch))   //quit eof
{
    if(ch==' ')
         spacees++;
    else if(ch=='\n')    
         newlines++;
}
第二个格式比第一个格式好在哪里?

第二个版本比第一个版本效率更高,因为在第一个中对于每个字符都需要判断两次,而在第二个版本中,如果字符为空格,在经过if判断确定为空格后,该字符肯定不是换行符,第二个else if的判断直接跳过,节省判断时间。

2.在程序清单6.2中,用ch+1替换++ch将发生什么情况?

程序清单6.2 ifelse.cpp

// ifelse.cpp -- using the if else statement
#include <iostream>
int main()
{
   char ch;
   std::cout << "Type, and I shall repeat.\n";
   std::cin.get(ch);
   while (ch != '.')
   {
       if (ch == '\n')
            std::cout << ch; // done if newline
       else
            std::cout << ++ch; // done otherwise
       std::cin.get(ch);
}
   // try ch + 1 instead of ++ch for interesting effect
   std::cout << "\nPlease excuse the slight confusion.\n";
   // std::cin.get();
   // std::cin.get();
   return 0;
}

++ch的数据类型依旧是char型,但对于char+1最终类型为int型,因此当++ch换成ch+1后,输出的是数字。

3.请认真考虑下面的程序:
#include<iostream>
using namespace std;
int main()
{
    char ch;
    int ct1,ct2;
    ct1=ct2=0;
    while((ch=cin.get())!='$')
    {
        cout<<ch;
        ct1++;
        if(ch='$')
              ct2++;
         cout<<ch;
    }
    cout<<"ct1="<<ct1<<",ct2="<<ct2<<"\n";
    return 0;
}
假设输入如下(请在每行末尾按回车键):

Hi!
Send $10 or $20 now!

则输出将是什么(还记得吗,输入被缓冲)?

输入输出结果为

Hi!
H$i$!$
$Send $10 or $20 now!
S$e$n$d$ $ct1=9,ct2=9

由于程序中使用的是ch='$',所以每次循环该if条件内代码都执行一次,因此ct1与ct2相等。同时在输入Hi!之后键入回车,因此在读取回车之后,打印出来,光标换行,紧接着打印$。

4.创建表示下述条件的逻辑表达式:

a.weight大于或等于115,但小于125。
b.ch为q或Q。
c.x为偶数,但不是26.
d.x为偶数,但不是26。
e.donation为1000-2000或guest为1。
f.ch是小写字母或大写字母(假设小写字母是依次编码的,大写字母也是依次编码的,但在大小写字母间编码是不连续的)。

//a
weight>=115 && weight<125   

//b
ch=='q' || ch=='Q'

//c
x%2==0 && x!=26

//d
x%2==0 && x%26!=0

//e
donation>=1000 && donation<=20000 || guest==1

//f
(ch>='a' && ch<='z') || (ch<='Z' && ch>='A')
5.在英语中,"I will not not speak(我不会不说) "的意思与"I will speak(我要说)"相同。在c++中,!!x是否与x相同呢?

对于bool变量而言,!!x与x是相同的,但对于其他类型变量不一定相同,例如!!5=1,!!5≠5。

6.创建一个条件表达式,其值为变量的绝对值。也就是说,如果变量x为正,则表达式的值为x;但如果x为负,则表达式的值为-x–这是一个正值。
x>=0 ? x : -x;
7.用switch改写下面的代码片段:
if(ch=='A')
    a_grade++;
else if(ch=='B')
    b_grade++;
else if(ch=='C')
    c_grade++;
else if(ch=='D')
    d_grade++;
else
    f_grade++;

改写后代码:

switch(ch)
{
    case 'A' : a_grade++;
                    break;
    case 'B' : b_grade++;
                    break;
    case 'C' : c_grade++;
                    break;
    case 'D' : d_grade++;
                    break;
    default :   f_grade++;
                    break;
}
8.对于程序清单6.10,与使用字符(如a和c)表示菜单选项和case标签有何优点呢?(提示:想一想用户输入q和输入5的情况。)

程序清单6.10 switch.cpp

// switch.cpp -- using the switch statement
#include <iostream>
using namespace std;
void showmenu(); // function prototypes
void report();
void comfort();
int main()
{
	showmenu();
	int choice;
	cin >> choice;
	while (choice != 5)
	{
		switch (choice)
		{
		case 1: cout << "\a\n";
			break;
		case 2: report();
			break;
		case 3: cout << "The boss was in all day.\n";
			break;
		case 4: comfort();
			break;
		default: cout << "That's not a choice.\n";
		}
		showmenu();
		cin >> choice;
	}
	cout << "Bye!\n";
	return 0;
}
void showmenu()
{
	cout << "Please enter 1, 2, 3, 4, or 5:\n"
		"1) alarm 2) report\n"
		"3) alibi 4) comfort\n"
		"5) quit\n";
}
void report()
{
	cout << "It's been an excellent week for business.\n"
		"Sales are up 120%. Expenses are down 35%.\n";
}
void comfort()
{
	cout << "Your employees think you are the finest CEO\n"
		"in the industry. The board of directors think\n"
		"you are the finest CEO in the industry.\n";
}

使用数字作为菜单选项和case标签,限定了用户只有输入数字的时候才能有效,若用户错误的输入非整数类型,导致程序被挂起。而使用字符作为菜单选项和case标签,当用户输入错误类型,程序能正确通过default部分提示用户输入错误,用户体验更加友好,提高了程序的容错性和健壮性。

9.请看下面的代码片段
int line = 0;
char ch;
while(cin.get(ch))
{
    if(ch=='Q')
        break;
    if(ch!='\n')
        continue;
    line++;
}

重写后代码:

int line = 0;
char ch;
while(cin.get(ch) && ch!='Q')
{
    if(ch=='\n')
        line++;
}

编程练习

1.编写一个程序,读取键盘输入,直到遇到@符号为止,并回显输入(数字除外),同时将大写字符转换为小写字符,将小写字符转换为大写(别忘了cctype函数系列)
#include<iostream>
#include<cctype>
using namespace std;

int main()
{
	cout << "Please enter characters (type @ to stop):";
	char ch;
	cin.get(ch);
	while (ch != '@')
	{
		if (islower(ch))
			ch = toupper(ch);
		else if (isupper(ch))
			ch = tolower(ch);
		if (!isdigit(ch))
			cout << ch;
		cin.get(ch);
	}
	system("pause");
	return 0;
}
2.编写一个程序,最多将10个donation值读入一个double数组中(如果你愿意,也可以使用模板类array)。程序遇到非数字输入时将结束输入,并报告这些数字的平均值以及数组中有多少个数字大于平均值。
#include<iostream>
#include<array>
using namespace std;
int main()
{
    array<double,10>donations;
    double sum=0;
    cout<<"Please enter donation(non-number to stop):";
    int i;
    double donation;
    for(i=0;(i<10)&&(cin>>donation);++i)
    {
        donations[i]=donation;
        sum=+donations[i];
    }    
         
    double avg=sum/(i+1);
    cout<<"Average:"<<avg<<endl;
    cout<<"Number larger than average:";
    for(int j=0;j<i;j++)
     {
        if(donations[j]>avg)
            cout<<donations[j]<<" ";
     }   
    cout<<endl;
    return 0;
}
3.编写一个菜单驱动程序的雏形。该程序显示一个提供四个选项的菜单–每个选项用一个字母表标记。如果用户使用有效选项之外的字母进行响应,程序将提示用户输入有效的字母,直到用户这样选择为止。然后,该程序使用一条switch语句,根据用户的选择执行一个简单操作。该程序的运行情况如下:
Please enter one of the following choices:
c) carnivore         p) pianist
t) tree                  g)game
f
Please enter a c,p,t or g:q
Please enter a c,p,t or g:t
A maple is a tree.

代码实现:

#include <iostream>
using namespace std;
int main()
{
    cout<<"Please enter one of the following choices:"<<endl;
    cout<<"c) carnivore         p) pianist"<<endl;
    cout<<"t) tree              g) game"<<endl;
    char ch;
    cin>>ch;
    while(ch!='c' && ch!='p' && ch!='t' && ch!='g')
    { 
        cout<<"Please enter a c,p,t or g:";
        cin>>ch;
    }   
    switch (ch)
    {
        case 'c':
            cout<<"A maple is a carnivore."<<endl;
            break;
        case 'p':
            cout<<"A maple is a pianist."<<endl;
            break;
        case 't':
            cout<<"A maple is a tree."<<endl;
            break;
        case 'g':
            cout<<"A maple is a game."<<endl;
            break;
        default:
            break;
    }
    return 0;
}
4.加入Benevolent Order of Programmer后,在BOP大会上,人们便可以通过加入者的真实姓名、头衔或秘密BOP姓名来了解他(她)。请编写一个程序,可以使用真实姓名、头衔、秘密姓名或成员偏好来列出成员。编写该程序时,请使用下面的结构:
//Benevolent Order of Programmers name structure
struct bop{
    char fullname[strsize];     //real name
    char title[strzie];              //job title
    char bopname[strsize];   //secret BOP name
    int preference;                //0=fullname,1=title,2=bopname
};
该程序创建一个由上述结构组成的小型数组,并将其初始化为适当的值。另外,该程序使用一个循环,让用户在下面的选项中进行选择:
a.display by name        b.diaplay by title
c.display by bopname     d.display by preference
q.quit
注意,“display by preference”并不意味显示成员的偏好,而是意味着根据成员的偏好来列出成员。例如,如果偏好号为1,则选择d将显示程序员的头衔。该程序的运行情况如下:
Benevolent Order of Programmers Report
a. display by name         b. display by title
c. display by bopname      d. display by preference
q. quit
Enter your choice: a
Wimp Macho
Raki Rhodes
Celia Laiter
Hoppy Hipman
Pat Hand
Next choice: d
Wimp Macho
Junior Programmer
MIPS
Analyst Trainee
LOOPY
Next choice: q
Bye!

代码实现 :

#include <iostream>

using namespace std;

const int strsize = 20;
struct bop
{
    char fullname[strsize];
    char title[strsize];
    char bopname[strsize];
    int preference;         //0 = fullname, 1 = title, 2 = bopname
};

int main()
{ 
    int programmerNum = 5;
    bop programmers[programmerNum]={{"Wimp Macho", "Junior Programmer", "WM",0},
    {"Raki Rhodes", "Junior Programmer", "RR", 1},
    {"Celia Laiter", "Junior Programmer", "MIPS", 2},
    {"Hoppy Hipman", "Analyst Trainee", "HH", 1},
    {"Pat Hand", "Junior Programmer", "LOOPY", 2}};
    cout << "Benevolent Order of Programmers Report" << endl;
    cout << "a. display by name          b. display by title" << endl;
    cout << "c. display by bopname       d. display by preference" << endl;
    cout << "q. quit" << endl;
    cout << "Enter your choice: ";
    char choice;
    while(cin.get(choice))
    {
        if(choice == 'a')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                cout << programmers[i].fullname << endl;
            }
        }
        else if(choice == 'b')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                cout << programmers[i].title << endl;
            }
        }
        else if(choice == 'c')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                cout << programmers[i].bopname << endl;
            }
        }
        else if(choice == 'd')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                if(programmers[i].preference == 0)
                {
                    cout << programmers[i].fullname << endl;
                }
                else if(programmers[i].preference == 1)
                {
                    cout << programmers[i].title << endl;
                }
                else
                {
                    cout << programmers[i].bopname << endl;
                }
            }
        }
        else if(choice == 'q')
        {
            cout << "Bye!" << endl;
            break;
        }
        else
        {
            if(choice == '\n')
            {
                continue;
            }
            cout << "input error, please re-enter!" << endl;
        }
        cout << "Next choice: ";
    }
    
    return 0;
}

5.在Neutronia王国,货币单位是tvarp,收入所得税的计算方式如下:

5000 tvarps: 不收税
5001~15000 tvarps: 10%
15001~35000 tvarps: 15%
35000 tvarps以上: 20%

例如,收入为38000 tvarps时,所得税为5000×0.00+10000×0.10+2000×0.15+3000×0.20,即 4600tvarps。请编写一个程序,使用循环来要求用户输入收入,并报告所得税,当用户输入负数或非数字时,循环将结束。

代码实现:

#include<iostream>

using namespace std;

int main()
{
    cout << "Please enter your income(if you enter negative number or non-numberic, it will exit.) : ";
    double income, tax;
    while(cin >> income)
    {
        cout<< income <<endl;
        if(income > 35000)
        {
            tax = 10000 * 0.10 + 20000 * 0.15 + (income - 35000) * 0.20;
        }
        else if(income >= 15001)
        {
            tax = (income - 3500) * 0.15 +10000 * 0.10;
        }
        else if(income >= 5001)
        {
            tax = (income - 5000) * 0.10;
        }
        else if(income >= 0)
        {
            tax = 0;
        }
        else
        {
            cout << "Enter negative number, exiting soon..." << endl;
            break;
        }
        cout << "your should pay tax : " << tax << " tvarps." << endl;
        cout << "Please enter another income(if you enter negative number or non-numberic, it will exit.) : ";
    }
    cout << "Exited, Bye !" << endl;
    return 0;
}

6.编写一个程序,记录捐助给"维护合法权利团体"的资金。该程序要求用户输入捐赠者数目,然后要求用户输入每一个捐献者的姓名和款项。这些信息被存储在一个动态分配的结构数组中.每个数据结构有两个成员:用来存储姓名的字符串数组(或string对象)和用来存储款项的double成员。读取所有的数据后,程序将显示所有捐款超过10000的捐款着姓名及其捐款数额。该列表前应包含一个标题,指出下面的捐款者是重要捐款人(Grand Patrons)。然后,程序将列出其他的捐款者,该列表要以Partons开头。如果某种类别没有捐款者,则程序将打印单词"none"。该程序只显示这两种类别,而不进行排序。

代码实现:

#include<iostream>
#include<string>

using namespace std;

struct DonationInfo{
    string name;
    double amount;
};

void donationInfoDisplay(DonationInfo donationInfo[], int num, bool isGrandPatrons)
{
    int countNum = 0;
    for(int i = 0 ; i < num ; i++)
    {
        if(isGrandPatrons)
        {
            if(donationInfo[i].amount > 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
        else
        {
            if(donationInfo[i].amount <= 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
    }
    if(countNum == 0)
        cout << "none" << endl;
}

int main()
{
    cout << "Please enter the number of donors :";
    int num;
    while(!(cin >> num))
    {
        cin.clear();
        cin.sync();
        cin.ignore();
        cout << "***[WARNING]:Please enter positive integer.***" << endl;
        cout << "Please enter the number of donors :";
    }
    DonationInfo* donationInfo = new DonationInfo[num];
    for(int i = 0; i < num; i++)
    {
        cout << "enter the donor name :";
        cin >> donationInfo[i].name;
        cout << "enter the donation amount :";
        cin >> donationInfo[i].amount;
    }
    cout << "******Grand Partons******" << endl;
    donationInfoDisplay(donationInfo, num, true);
    cout << "******Partons******" << endl;
    donationInfoDisplay(donationInfo, num, false);

    delete[] donationInfo;
    return 0;
}

7.编写一个程序,它每次读取一个单词,直到用户只输入q。然后,该程序指出有多少个单词以元音打头,有多少个单词以辅音打头,还有多少个单词不属于这两类。为此,方法之一是,使用isalpha()来区分以字母和其他字母打头的单词,然后对于通过isalpha()测试的单词,使用if或switch语句来确定哪些以元音打头。该程序的运行情况如下:

Enter words (q to quit):
The 12 awesome oxem ambled
quiety across 15 meters of lawn. q
5 words beginning with vowels
4 words beginning with consonants
2 others

代码实现:

#include<iostream>
#include<string>
using namespace std;

int main()
{
    cout << "Enter words (q to quit) :" << endl;
    string word;
    int vowelNum = 0;
    int consonantNum = 0;
    int othersNum = 0;
    while(cin >> word)
    {
        if(word == "q")
        {
            break;
        }
        else
        {
            if(isalpha(word[0]))
            {
                switch(word[0])
                {
                    case 'a':
                    case 'e':
                    case 'i':
                    case 'o':
                    case 'u':
                    case 'A':
                    case 'E':
                    case 'I':
                    case 'O':
                    case 'U':
                        vowelNum++;
                        break;
                    default:
                        consonantNum++;
                }
            }
            else
            {
                othersNum++;
            }
        }
    }
    cout << vowelNum << " words beginning with vowels" << endl;
    cout << consonantNum << " words beginning with consonants" << endl;
    cout << othersNum << " others" <<endl;
    return 0;
}

8.编写一个程序,他打开一个文件,逐个字地读取该文件,直到到达文件末尾,然后指出该文件中包含多少个字符。

代码实现:

#include<iostream>
#include<fstream>

using namespace std;

int main()
{
    ifstream txtSource;
    txtSource.open("test.txt", ios::in);
    if(!txtSource.is_open())
    {
        cout << "File failed to open !" << endl;
        exit(EXIT_FAILURE);
    }
    char ch;
    int characterNum = 0;
    while(txtSource >> ch)
    {
        characterNum++;
    }
    if (txtSource.eof())
    	cout << "End of file reached.\n";
    else if (txtSource.fail())
    	cout << "Input terminated by data mismatch." << endl;
    else
    	cout << "Input terminated for unknown reason." << endl;
    if(characterNum == 0)
    	cout << "No data processed." << endl;
    else
        cout << "The file contains " << characterNum << " characters" << endl;

    txtSource.close();
    return 0;
}
9.完成编程练习6,但从文件中读取所需的信息。该文件的第一项应为捐款人数,余下的内容应为对的行。在每一对中,第一行为捐款人姓名,第二行为捐款数额。即该文件类似于下面:

代码实现:

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

using namespace std;

struct DonationInfo{
    string name;
    double amount;
};

void donationInfoDisplay(DonationInfo donationInfo[], int num, bool isGrandPatrons)
{
    int countNum = 0;
    for(int i = 0 ; i < num ; i++)
    {
        if(isGrandPatrons)
        {
            if(donationInfo[i].amount > 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
        else
        {
            if(donationInfo[i].amount <= 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
    }
    if(countNum == 0)
        cout << "none" << endl;
}

int main()
{
    cout << "Read file content..." << endl;
    ifstream txtDonationInfo;
    txtDonationInfo.open("test.txt", ios::in);
    if(!txtDonationInfo.is_open())
    {
        cout << "File failed to open !" << endl;
        exit(EXIT_FAILURE);
    }
    int num = 0;
    (txtDonationInfo >> num).get();
    DonationInfo* donationInfo = new DonationInfo[num];
    for(int i = 0; i < num; i++)
    {
        txtDonationInfo >> donationInfo[i].name;
        txtDonationInfo >> donationInfo[i].amount;
    }
    cout << "******Grand Partons******" << endl;
    donationInfoDisplay(donationInfo, num, true);
    cout << "******Partons******" << endl;
    donationInfoDisplay(donationInfo, num, false);

    delete[] donationInfo;
    txtDonationInfo.close();
    return 0;
}

微信公众号,关注一下

微信公众号,关注一下
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《C Primer Plus第六版》是一本面向初学者的C语言教材,由Stephen Prata撰写。这本书深入浅出地介绍了C语言的基本概念、语法和应用,给读者提供了扎实的编程基础。 该书共分为27章,每章都有清晰的目标、易于理解的示例和练习题。从第一章的入门介绍开始,到最后一章的高级主题讨论,书中的内容依次递进,系统完整地覆盖了C语言的方方面面。本书有助于读者逐步掌握C语言的基础知识,从简单的输出语句到复杂的函数调用和指针使用。 《C Primer Plus第六版》的特点是其清晰的讲解风格和丰富的实例。作者通过通俗易懂的语言和生动形象的例子,帮助读者理解和掌握C语言的各种概念和语法。此外,书中还提供了许多练习题和编程项目,供读者巩固所学知识和提高编程能力。 作为一本经典的C语言教材,《C Primer Plus第六版》被广泛用于学校和个人学习。它不仅适用于初学者,也对有一定编程基础的读者有所帮助。读者通过学习本书,可以建立起对C语言编程的扎实基础,为深入学习其他编程语言打下坚实的基础。 综上所述,《C Primer Plus第六版》是一本权威、经典的C语言教材,通过清晰的讲解和丰富多样的示例帮助读者深入理解C语言的基本概念和应用。无论是初学者还是有一定编程基础的读者,都可以从中获益,打下良好的编程基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艰默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值