1. 回文指的是顺读和逆读都一样的字符串。例如,“tot”和“otto”都是简短的回文。编写一个程序,让用户输入字符串,并将字符串引用传递给一个bool函数。如果字符串时回文,该函数将返回true,否则返回false。此时,不要担心诸如大小写、空格和标点符号这些复杂的问题。即这个简单的版本将拒绝"Otto”和“Madam, I'm Adam”。请查看附录F中的字符串方法列表,以简化这项任务。
本题要求我们编写程序来识别回文,我们需要编写一个bool函数来判断是否是回文,判断回文的方法有很多种,在这里因为不需要考虑标点符号和大小写等问题,所以我们只需要考虑最简单的方法即可,即将原字符串反转,倒序生成一个新字符串,判断新生成的字符串与原字符串是否严格相等。
16.1.cpp代码如下所示:
// 16.1.cpp -- judge if a string is hui-string
#include "stdafx.h"
#include
#include
using namespace std;
bool isHui(const string & str);
int main()
{
cout << "Test begin.\n";
cout << "Please enter your input (empty input to quit): ";
string input;
getline(cin, input);
while (cin && input.size() > 0)
{
if (isHui(input))
cout << "What you input is a Hui string!\n";
else
cout << "What you input is not a Hui string!\n";
cout << "Please enter your input (empty input to quit): ";
getline(cin, input);
}
cout << "Test end. Quit.\n";
system("pause");
return 0;
}
bool isHui(const string & str)
{
string rev(str.rbegin(), str.rend());
return (str == rev);
}
运行结果如下图所示:
从结果图可以看出,该程序可以识别简单的回文,但拒绝大小写或标点符号等形式的回文。
2. 与编程练习1中给出的问题相同,但要考虑诸如大小写、空格和标点符号这样的复杂问题。即“Madam, I'm Adam”将作为回文来测试。例如,测试函数可能会将字符串缩略为“madamimadam”,然后测试倒过来是否一样。不要忘了有用的cctype库,您可能从中找到几个有用的STL函数,尽管不一定非要使用它们。
本题要求在考虑空格、大小写和标点符号的情况下来测试回文,整体程序框架可以与上一题完全一样,只需要修改判断是否是回文的bool函数。
在判断是否是回文之前,我们必须把空格和标点符号去掉,然后把大小写归一化才行。对于去掉空格和标点符号,最简单的方法是调用cctype库中的erase()函数,该函数会删去指定的字符,那么我们可以使用isalpha()函数来判断是否是字母,如果不是字母,即空格或者各式各样的标点符号,则调用erase()函数将其删去。对于大小写的归一化,我们可以统一到一种格式上,比如按照题目中举的例子,就是统一都格式化成小写,那么就是使用tolower()函数。
在这里特别注意两个问题,第一个问题是对于在循环中删去字符的情况,这种情况下我们不需要在删去字符之后加上i++;语句,因为此时本来下标为i的字符已经被删去了,后面的本来下标为i+1的字符会自动顶上来,因此下一次还是去处理下标为i的字符;第二个问题是对于将下标为i的字符格式化为小写,由于此时i是一个迭代器,是一个字符串引用,因此我们需要使用*i来获取它的值。
16.2.cpp代码如下所示:
// 16.2.cpp -- judge if a string is a Hui-string (contains the space and symbols)
#include "stdafx.h"
#include
#include
#include
using namespace std;
bool isHui(const string & str);
int main()
{
cout << "Test begin.\n";
cout << "Please enter your input (empty input to quit): ";
string input;
getline(cin, input);
while (cin && input.size() > 0)
{
if (isHui(input))
cout << "What you input is a Hui string!\n";
else
cout << "What you input is not a Hui string!\n";
cout << "Please enter your input (empty input to quit): ";
getline(cin, input);
}
cout << "Test end. Quit.\n";
system("pause");
return 0;
}
bool isHui(const string & str)
{
string str_test = str;
for (auto i = str_test.begin(); i != str_test.end();)
{
if (!isalpha(*i))
{
i = str_test.erase(i);
continue;
}
else
{
*i = tolower(*i);
i++;
}
}
string rev(str_test.rbegin(), str_test.rend());
return (str_test == rev);
}
运行结果如下图所示:
从上图的第三个输入可以看出,该函数忽略空格,从上图的第四个输入可以看出,该函数忽略大小写,从上图的第五个输入可以看出,该函数忽略标点符号。
3. 修改程序清单16.3,使之从文件中读取单词。一种方案是,使用vector
本题要求在程序清单16.3的基础上进行修改,不是直接获取单词列表,而是改为从文件中去读取单词。题中给出的思路是将string数组修改为vector
首先,我们在程序目录下生成一个wordlist.txt文件,输入程序清单16.3的string数组的单词,用空格分开,如下图所示:
接下来我们得声明一个读取文件的fin,对打不开文件的情况进行处理,这些内容可以阅读《C++ Primer Plus (第六版)》的第17章详细学习。我们声明一个名叫wordlist的evctor
对于后面具体的hangman游戏的处理,我们可以完全使用程序清单16.3一模一样的代码即可。
16.3.cpp代码如下所示:
// 16.3.cpp -- a new hangman
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include
//const string wordlist[NUM] = { "apiary", "beetle", "cereal",
//"danger", "ensign", "florid", "garage", "health", "insult",
//"jackal", "keeper", "loaner", "manage", "nonce", "onset",
//"plaid", "quilt", "remote", "stolid", "train", "useful",
//"valid", "whence", "xenon", "yearn", "zippy" };
int main()
{
using namespace std;