题目:16.1
回文指的是顺读和逆读都一样的字符串。例如,“tot”和“otto”都 是简短的回文。编写一个程序,让用户输入字符串,并将字符串引用传 递给一个bool函数。如果字符串是回文,该函数将返回true,否则返回 false。此时,不要担心诸如大小写、空格和标点符号这些复杂的问题。 即这个简单的版本将拒绝“Otto”和“Madam,I'm Adam”。请查看附录F中 的字符串方法列表,以简化这项任务。
bool Func(string ch)
{
int size = ch.size();
string::iterator first = ch.begin();
string::iterator second = ch.end();//这是在最末尾后面了
second--;
for (int i = 0; i < size / 2; i++)
{
cout << "first=" << *first << endl;
cout << "second=" << *second << endl;
if (*first != *second)
{
return false;
}
first++;
second--;
}
return true;
}
问题1:string是类模板吗?
string是C++标准库中的一个类模板。在C++中,string类模板用于表示字符串,提供了一系列操作字符串的方法。通过使用string类模板,可以方便地操作字符串,而不需要手动管理内存或处理字符串的长度等问题。因此,string类模板是C++中非常常用的类之一。
题目:16.2
题: 与编程练习1中给出的问题相同,但要考虑诸如大小写、空格和 标点符号这样的复杂问题。即“Madam,I'm Adam”将作为回文来测试。 例如,测试函数可能会将字符串缩略为“madamimadam”,然后测试倒过 来是否一样。不要忘了有用的cctype库,您可能从中找到几个有用的 STL函数,尽管不一定非要使用它们。
bool Func1(string ch)
{
int size = ch.size();
string::iterator first = ch.begin();
string::iterator second = ch.end();//这是在最末尾后面了
second--;
for (int i = 0; i < size / 2; i++)
{
cout << "first=" << *first << endl;
cout << "second=" << *second << endl;
if (*first != *second)
{
return false;
}
first++;
second--;
}
return true;
}
bool Func2(string ch)
{
//需求:判断有符号的一串数字是否是回文数,且要将其全部转为小写字母
string::iterator it = ch.begin();
for (; it != ch.end(); )
{
if (!isalpha(*it))
{
//如果不是字母则将其擦除
it=ch.erase(it);//这种擦除,ch中所分配的内存是会减少的
continue;
}
else
{
//是字母,则转化为小写字母
*it = tolower(*it);
it++;
}
}
//判断是否是回文数
return Func1(ch);
}
问题二:getline()的详细用法
getline(cin, input)
是一个 C++ 的标准库函数,用于从标准输入流cin
中读取一行输入,并将其存储到字符串变量input
中。具体方法如下:
getline()
函数接受两个参数,第一个参数是输入流对象,通常是cin
,第二个参数是一个字符串变量,用于存储读取的输入。当程序执行到
getline(cin, input)
时,程序会等待用户输入一行字符并按下回车键。一旦用户按下回车键,
getline()
函数会将用户输入的整行文本读取并存储到input
字符串变量中。如果用户输入的文本长度超过了
input
字符串变量的最大长度,getline()
函数会截断文本并存储到input
中。
getline()
函数会自动忽略换行符,并将换行符从输入流中移除,因此input
中不会包含换行符。
getline()
函数会返回一个istream
对象,可以用来检查输入流的状态。如果输入流正常操作,返回值为cin
,如果发生错误,返回值为NULL
。总之,
getline(cin, input)
方法是一个方便的方式来从标准输入流中读取一行输入,并存储到字符串变量中。
问题三:tolower()用法
c++ tolower()
函数用于将字符转换为小写字母。它接受一个字符作为参数,并返回相应的小写字母字符。
示例代码:
#include <iostream>
#include <cctype>
int main() {
char ch = 'A';
char lowerCh = tolower(ch);
std::cout << "原始字符: " << ch << std::endl;
std::cout << "转换为小写字母: " << lowerCh << std::endl;
return 0;
}
题目:16.4
题: 编写一个具有老式风格接口的函数,其原型如下:
int reduce(long arr[], int n); 实参应是数组名和数组中的元素个数。该函数对数组进行排序,删 除重复的值,返回缩减后数组中的元素数目。请使用STL函数编写该函 数(如果决定使用通用的unique( )函数,请注意它将返回结果区间的结 尾)。使用一个小程序测试该函数。
//方法1:
int reduce1(long arr[], int n)
{
//决定使用使用set容器,原因:它不存放重复的元素
set<long> ans;
for (int i = 0; i < n; i++)
{
ans.insert(arr[i]);
}
cout << "ans.size()=" << ans.size() << endl;
set<long>::iterator it = ans.begin();
for (; it!=ans.end(); it++)
{
cout << *it;
}
return ans.size();
}
//方法2:
int reduce2(long arr[], int n)
{
//unique():功能是去除相邻的重复元素(注意一定是相邻元素,且只保留一个)
//所以使用前需要对数组进行排序
//对arr进行排序
//arr+n 表示最后一个元素后面一个位置
sort(arr, arr + n);
vector<long>ans;
for (int i = 0; i < n; i++)
{
ans.push_back(arr[i]);
}
//auto自动识别数据类型
auto it=unique(ans.begin(), ans.end());
//取出末尾重复的数
ans.erase(it, ans.end());
vector<long>::iterator ret = ans.begin();
for (ret; ret != ans.end(); ret++)
{
cout << *ret << " ";
}
cout << endl;
return 0;
}
题目:16.5
题: 问题与编程练习4相同,但要编写一个模板函数:
template <class T>
int reduce(T arr[], int n)
在一个使用long实例和string实例的小程序中测试该函数。
template <class T>
int reduce(T arr[], int n)
{
//使用unique()方法
//先排序
sort(arr, arr + n);
//unique函数返回一个指向数组中去除重复元素后的末尾位置的迭代器
vector<T>ans;
for (int i = 0; i < n; i++)
{
ans.push_back(arr[i]);
}
typename vector<T>::iterator it = unique(ans.begin(), ans.end());
//去除相同的末尾元素
typename vector<T>::iterator ret = ans.begin();
ans.erase(it, ans.end());
for (ret; ret != ans.end(); ret++)
{
cout << *ret << " ";
}
cout << endl;
return 0;
}
问题一:为什么在使用类模板时,无法直接使用vector<T>::iterator it 创建一个迭代器
在C++中,
vector<T>::iterator
是std::vector
模板类的一个嵌套类型,表示std::vector
中的迭代器类型。当使用类模板时,例如std::vector<int>
,迭代器类型std::vector<int>::iterator
是由编译器根据std::vector<int>
的具体类型推导出来的。因此,在使用类模板时,无法直接使用
vector<T>::iterator
来创建迭代器,因为T
是一个模板参数,需要具体化为一个实际的类型后才能确定vector<T>::iterator
的具体类型。您需要使用typename std::vector<T>::iterator
来指定迭代器类型,其中typename
表示std::vector<T>::iterator
是一个类型,而不是一个静态成员。
题目:16.7
题: 彩票卡是一个常见的游戏。卡片上是带编号的圆点,其中一些 圆点被随机选中。编写一个lotto( )函数,它接受两个参数。第一个参数 是彩票卡上圆点的个数,第二个参数是随机选择的圆点个数。该函数返 回一个vector对象,其中包含(按排列后的顺序)随机选择的号 码。例如,可以这样使用该函数:
vector<int> winners; winners = Lotto(51, 6);这样将把一个矢量赋给winner,该矢量包含1~51中随机选定的6个 数字。注意,仅仅使用rand( )无法完成这项任务,因它会生成重复的 值。提示:让函数创建一个包含所有可能值的矢量,使用 random_shuffle( ),然后通过打乱后的矢量的第一个值来获取值。编写 一个小程序来测试这个函数。
vector<int> lotto(int size,int size_rand)
{
//设置随机数种子
//srand(time(0));与rand()搭配使用的
vector<int>ans;
for (int i = 1; i < size+1; i++)
{
ans.push_back(i);
}
vector<int>ret;
//每次随机打乱,抽取第一个
for (int i = 0; i < size_rand; i++)
{
random_shuffle(ans.begin(), ans.end());
ret.push_back(ans[0]);
}
for (int i = 0; i < size_rand; i++)
{
cout << ret[i] << " ";
}
cout << endl;
return ret;
}
问题1:randdom_shuffle()用法
在C++中,random_shuffle()函数用于随机打乱指定范围内的元素顺序。该函数需要包含<algorithm>头文件,并且其用法如下:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 随机打乱vector中的元素顺序
std::random_shuffle(vec.begin(), vec.end());
// 输出打乱后的元素
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
题目:16.8
题: Mat和Pat希望邀请他们的朋友来参加派对。他们要编写一个程 序完成下面的任务。
- 让Mat输入他朋友的姓名列表。姓名存储在一个容器中,然后按排 列后的顺序显示出来。
- 让Pat输入她朋友的姓名列表。姓名存储在另一个容器中,然后按 排列后的顺序显示出来。
- 创建第三个容器,将两个列表合并,删除重复的部分,并显示这个 容器的内容。
//输出容器内的数据,使用类模板
template <typename T>
class Container {
private:
T container;
public:
Container(T c) : container(c) {}
void print() {
for (auto it = container.begin(); it != container.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
};
//第三个容器显然使用set,set可以去除重复的数
//前两个使用vector
void Show_Name()
{
vector<string>Mat;
int count = 1;
while (count)
{
string name;
cout << "Mat请输入朋友姓名:";
cin >> name;
cout << endl;
Mat.push_back(name);
cout << "是否继续:1继续,0结束:";
cin >> count;
}
//输出容器内容,用类模板,我另一篇博客有有专门总结过
Container<vector<string>> con(Mat);
con.print();
//
vector<string>Pat;
count=1;
while (count)
{
string name;
cout << "Pat请输入朋友姓名:";
cin >> name;
cout << endl;
Pat.push_back(name);
cout << "是否继续:1继续,0结束:";
cin >> count;
}
//输出容器内容,用类模板
Container<vector<string>> con2(Pat);
con2.print();
//合并两个人的内容
set<string>ans;
//传入Mat的数据
vector<string>::iterator it = Mat.begin();
for (it; it != Mat.end(); it++)
{
ans.insert(*it);
}
//传入Pat的数据
vector<string>::iterator itp = Pat.begin();
for (itp; itp != Pat.end(); itp++)
{
ans.insert(*itp);
}
Container<set<string>> con3(ans);
con3.print();
}