C++蓝桥杯基础篇(八)
片头
嗨~小伙伴们,大家好!今天我们一起来学习C++蓝桥杯基础篇(八),练习相关字符串的习题,准备好了吗?Are you ready? Let's go!
第1题 字符串中的数字个数
这道题,我们用字符数组或者string类型来存储数据都可以。
因为其中可能包含空格,因此scanf和cin是不能使用的。如果是字符数组,采用fgets函数从键盘中读取;如果是string类型,使用getline函数从键盘中读取。
代码如下:
方法一:使用string类型从键盘中读取数据
//字符串中的数字个数
//输入一行字符,长度不超过10
//统计其中的数字字符的个数
//输入一行字符,注意其中包含空格
//输出一个整数,表示数字字符的个数
//string类型来读取数据
int main() {
string str;
getline(cin, str);
int num = 0;
for (int i = 0; str[i]; i++) {
if (str[i] >= '0' && str[i] <= '9') {
num++;
}
}
cout << num << endl;
return 0;
}
方法二:用字符数组从键盘中读取数据
int main() {
char a[10]; //定义一个字符数组,长度为10
fgets(a, 10, stdin); //从键盘中最多输入9个有效数据,最后1个值为'\0'
int num = 0;
for (int i = 0; a[i] != '\0' && a[i] != '\n'; i++) {
if (a[i] >= '0' && a[i] <= '9') {
num++;
}
}
cout << num << endl;
return 0;
}
第2题 循环相克令
这道题,类似于我们小时候玩的剪刀石头布,2个玩家,石头赢剪刀,布赢石头,剪刀赢布。如果双方出的相同,则平局。
这道题也一样。狗熊赢猎人,枪赢狗熊,猎人赢枪。
好啦,本道题的代码如下:
//循环相克令
//循环相克令是一个两人玩的小游戏。
//令词为“猎人、狗熊、枪”,两人同时说出令词,同时做出一个动作--
//猎人的动作是双手叉腰; 狗熊的动作是双手搭在胸前 : 枪的动作是双手举起呈手枪状。
//双方以此动作判定输赢,猎人赢枪、枪狗熊、狗熊赢猎人,动作相同则视为平局。
//现在给定你一系列的动作组合,请你判断游戏结果。
//第一行包含整数T,表示共有T组测试数据。
//接下来T行,每行包含两个字符串,表示一局游戏中两人做出的动作,
//字符串为“Hunter"“Bear", “Gun”中的一个
//这三个单词分别代表猎人,狗熊和枪。
//如果第一个玩家赢了,则输出“Player1”。
//如果第二个玩家赢了,则输出“Player2”。
//如果平局,则输出“Tie”。
// 猎人 0 1赢0
// 狗熊 1 2赢1
// 枪 2 0赢2
// x == (y + 1) % 3
int main() {
int t;
cin >> t; //表示共有t组测试数据
int x, y;
while (t--) {
string a, b;
cin >> a >> b;
if (a == "Hunter") x = 0;
else if (a == "Bear") x = 1;
else x = 2;
if (b == "Hunter") y = 0;
else if (b == "Bear") y = 1;
else y = 2;
if (x == y) cout << "Tie" << endl;
else if (x == (y + 1) % 3) cout << "Player1" << endl;
else cout << "Player2" << endl;
}
return 0;
}
第3题 字符串加空格
这道题,要求在字符串的每个字符之间加一个空格。代码如下:
//字符串加空格
//给定一个字符串,在字符串的每个字符之间都加一个空格。
//输出修改后的新字符串。
//输入共一行,包含一个字符串。注意字符串中可能包含空格。
//输出增加空格后的字符串。
//1 < 字符串长度 < 100
int main() {
string s;
getline(cin, s);
int len = s.size();
string b = "";
for (int i = 0; i < len; i++) {
b = b + s[i] + ' ';
}
cout << b << endl;
return 0;
}
或者采用范围for也可以
int main() {
string s;
getline(cin, s);
string b = "";
for (auto e : s) {
b = b + e + ' ';
}
cout << b << endl;
return 0;
}
注意:必须写成 b = b + s[i] + ' '; 如果写成 b += s[i] + ' '; 那么 s[i] 会先和空格相加,得到一个ASCII码值,再用这个ASCII码值和字符串b相加。很显然,违背了题意,因此,我们必须分开写。
第4题 字符串插入
首先,我们先来介绍substr函数。
string substr(size_t pos = 0,size_t len = npos);
参数:
pos: 要复制的第一个字符的位置
len: 子字符串的长度
size_t: 这是一个无符号整数类型
返回值: 返回一个字符串对象功能:在str中从pos位置开始,截取len个字符,然后将其返回
例如:
void test() {
string s1("hello world!");
//从下标为0的元素开始,截取5个字符
string s2 = s1.substr(0, 5);
cout << s2 << endl;
}
欧克欧克,我们回到这道题上面。
题目要求我们把sub插入到str中ASCII码值最大的那个字符后面。我们可以采用擂台法。用一个变量p来保存下标为0的元素,依次和后面的元素进行比较。如果后面的元素比当前元素值大,那么就把p更新。
再用substr函数,插入到ASCII码最大值的字符后面。分成3段,第1部分是下标为0的元素~下标为p的元素,总共p+1个元素;第2部分就是我们要插入的sub;第3部分是下标为p+1的元素一直到字符串的结束位置'\0'
代码如下:
//s.substr(i,len)
//从字符串s中的索引i开始打印,长度为len的子字符串
//len默认为npos
int main() {
string str;
string sub;
while (cin >> str >> sub) {
int p = 0; //设最大值的下标为0
for (int i = 1; str[i]; i++) {
if (str[i] > str[p]) {
p = i;
}
}
//因为是从下标为p的位置开始插入,因此前面的字符个数为p+1
//从字符串str中的下标为0的位置开始,截取p+1个字符
//将得到的结果和sub字符串进行拼接
//最后将从下标p+1的位置,截取npos个字符,也就是剩余的字符串长度
//和之前的结果拼接到一起
cout << str.substr(0, p + 1) + sub + str.substr(p + 1) << endl;
}
return 0;
}
第5题 字符串匹配
这道题,其实就是依次比较2个字符串中的字符是否相同
代码如下:
//字符串匹配
//给定两个长度相同的字符串a和字符串 b。
//如果在某个位置i上,满足字符串a上的字符a[i]和字符串b上的字符b[i]相同,那么这个位置上的字符就是匹配的。
//如果两个字符串的匹配位置的数量与字符串总长度的比值大于或等于k,则称两个字符串是匹配的。
//现在请你判断给定的两个字符串是否匹配。
//第一行包含一个浮点数k,第二行包含字符串a,第三行包含字符串b。
//输入的字符串中不包含空格。
//如果两个字符串匹配,则输出“yes”;否则,输出“no”。
//0 < k < 1,
//字符串的长度不超过100。
int main() {
double k;
cin >> k;
string a, b;
cin >> a >> b;
int count = 0;
int len = a.size();
for (int i = 0; a[i]; i++) {
if (a[i] == b[i]) {
count++;
}
}
if ((double)count / len >= k) {
cout << "yes" << endl;
}
else {
cout << "no" << endl;
}
return 0;
}
第6题 忽略大小写比较字符串大小
这道题,其实是比较2个字符串,将大写字母转变成小写字母,进行比较。'a'为97,'A'为65,差值为32。如果将大写字母转为小写字母,那么只需要将数值加上32即可。最后将2个字符串用strcmp函数进行比较。如果相等,输出"=";如果结果为1,输出">";否则输出"<"。
需要注意的是,字符串中可能包含空格,因此我们需要用fgets函数或者getline函数。
代码如下:
//忽略大小写比较字符串大小
//一般我们用strcmp可比较两个字符串的大小,比较方法为对两个字符串从前往后逐个字符相比较(按ASCII码值大小比较),直到出现不同的字符或遇到'\0’为止。
//如果全部字符都相同,则认为相同; 如果出现不相同的字符,则以第一个不相同的字符的比较结果为准
//但在有些时候,我们比较字符串的大小时,希望忽略字母的大小,例如”Hello”和”hello”在忽略字母大小写时是相等的。
//请写一个程序,实现对两个字符串进行忽略字母大小写的大小比较
//输入为两行,每行一个字符串,共两个字符串。注意字符串中可能包含空格。
//数据保证每个字符串的长度都不超过80。
//如果第一个字符串比第二个字符串小,输出一个字符”<”。
//如果第一个字符串比第二个字符串大,输出一个字符” > ”
//如果两个字符串相等,输出一个字符” = ”。
int main() {
char a[80];
char b[80];
fgets(a, 80, stdin);
fgets(b, 80, stdin);
if (a[strlen(a) - 1] == '\n') a[strlen(a) - 1] = 0; //去掉末尾回车
if (b[strlen(b) - 1] == '\n') b[strlen(b) - 1] = 0; //去掉末尾回车
for (int i = 0; a[i]; i++) {
if (a[i] >= 'A' && a[i] <= 'Z') { //将大写字母转换为小写字母
a[i] += 32;
}
}
for (int j = 0; b[j]; j++) {
if (b[j] >= 'A' && b[j] <= 'Z') { //将大写字母转换为小写字母
b[j] += 32;
}
}
int t = strcmp(a, b);
if (t == 0) cout << "=" << endl;
else if (t > 0) cout << ">" << endl;
else cout << "<" << endl;
return 0;
}
第7题 去掉多余的空格
这道题,咱们有2种方法~
方法一:直接用cin读取一整行字符串,注意这里使用while循环。cin遇到空格或换行会停止读取
代码如下:
//去掉多余的空格
//输入一个字符串,字符串中可能包含多个连续的空格,请将多余的空格去掉,只留下一个空格。
//输入共一行,包含一个字符串。
//输出去掉多余空格后的字符串,占一行。
//输入字符串的长度不超过200
//在控制台上输入,是遇到\n结束
//而cin读取的话,直到遇到空白字符(如空格、制表、换行符等)就会结束
//cin其实是遇到空格或\n就停止,执行循环内部,再去读取下一个值
int main() {
string s;
while (cin >> s) cout << s << " ";
return 0;
}
方法二:采用双指针法,下标 i 在起始位置,定义下标 j ,初始位置为下标 i 的位置,如果下标 j 没有走到 '\0' ,并且下标 j 对应的值为空格,那么 j++,直到下标 j 对应的值不是空格。此时下标 i 位置更新,更新到下标 j 的位置。
int main() {
string a;
getline(cin, a); //使用getline函数读取一整行字符串(包含空格)
string b = ""; //定义字符串b为最终输出的结果
int len = a.size();
for (int i = 0; i < len; i++) {
if (a[i] != ' ') b += a[i]; //如果a[i]不是空格,直接拼接到字符串b
else {
b = b + ' '; //如果a[i]是空格,字符串b只需要加1次空格
int j = i;
while (j < a.size() && a[j] == ' ') j++;
//for (; j < a.size() && a[j] == ' '; j++);
i = j - 1; //因为else语句的外面还有i++,i又会自增1次
//如果 i == j,那么i++,i就会跳到j位置的右边(下一个位置)
//所以 i = j - 1; 执行完else语句,i++,i刚好等于j
}
}
cout << b << endl;
return 0;
}
第8题 输出字符串
这道题,要求我们输出字符串b,那么对字符串b的要求是什么呢?咱们画个图~
本题的代码如下:
//输出字符串
//给定一个字符串a,请你按照下面的要求输出字符串b。
//给定字符串a的第一个字符的ASCII值加第二个字符的ASCII值,得到b的第一个字符;
//给定字符串a的第二个字符的ASCII值加第三个字符的ASCII值,得到b的第二个字符
//给定字符串a的倒数第二个字符的ASCII值加最后一个字符的ASCII值,得到b的倒数第二个字符,
//给定字符串a的最后一个字符的ASCII值加第一个字符的ASCII值,得到b的最后一个字符。
//输入共一行,包含字符串a。注意字符串中可能包含空格。
//数据保证字符串内的字符的ASCII值均不超过63。
//输入: 1 2 3
//输出: QRRSd
int main() {
string a;
string b;
getline(cin, a); //因为要包含空格,所以使用getline函数
int len = a.size();
for (int i = 0; i < len; i++) {
b += (char)(a[i] + a[(i + 1) % a.size()]); //不强转成char类型也可以
}
cout << b << endl;
return 0;
}
第9题 单词替换
这道题,本意是让我们输入一整行字符串s,输入待替换的单词a,接着再输入将被替换的单词b,输出将字符串s中所有单词a替换成b之后的字符串。
这个就需要stringstream类来解决此类问题了, stringstream 是 C++ 提供的专门用于处理字符串的 输入输出 流类。 stringstream 定义于头文件 <sstream>。
stringstream的用途:利用 stringstream 去除字符串空格,因为 stringstream 默认是以空格来分割字符串的。
示例代码:
int main() {
string a;
getline(cin, a); // I am a student!
stringstream ssin(a); //将字符串a传入stringstream对象ssin中
//注意:stringstream的对象ssin,是一个单词一个单词"流入"e的
string e;
while (ssin >> e) cout << e << endl;
//打印结果为:
// I
// am
// a
// student!
return 0;
}
因此,我们先定义字符串s,s包含多个单词。接着定义待替换的单词a,定义将被替换的单词b。定义stringstream类的一个对象ssin,将字符串s传递过去。此时ssin会把一整行字符串s,以空格为分隔符,拆分成一个一个单词。再逐一判断每个单词是否要被替换。
代码如下:
//单词替换
//stringstream 的用法:
//默认以空格来分割字符串
int main() {
string s,a,b;
getline(cin, s); //多个单词的字符串s
cin >> a; //待替换的单词a
cin >> b; //a将被替换的单词b
stringstream ssin(s); //stringstream 读取s字符串的时候,自动把s字符串里面的内容按照空格分隔提取出来
string part; //将s字符串中,按照空格分隔符,将每个单词都存放到part变量中
//注意: stringstream的对象ssin,是一个单词一个单词"流入"part的
while (ssin >> part) {
if (part == a) cout << b << " ";
else cout << part << " ";
}
return 0;
}
第10题 字符串中最长的连续出现的字符
题目要求字符串中最长的连续出现的字符,还是运用我们双指针法。
OK啦,本道题的代码如下:
//字符串中最长的连续出现的字符
//求一个字符串中最长的连续出现的字符,输出该字符及其出现次数,字符串中无空白字符(空格、回车和tab)
//如果这样的字符不止一个,则输出第一个。
//第一行输入整数N,表示测试数据的组数。
//每组数据占一行,包含一个不含空白字符的字符串,字符串长度不超过200。
//输出共一行,输出最长的连续出现的字符及其出现次数,中间用空格隔开。
int main() {
int n; //测试的组数
cin >> n;
while (n--) {
string str;
cin >> str;
int len = str.size();
int count = 0;//字符出现的次数
char c; //字符
for (int i = 0; i < len; i++) {
int j = i;
while (j < len && str[j] == str[i]) j++;
if (count < j - i) count = j - i, c = str[i];
i = j - 1;
}
cout << c << " " << count << endl;
}
return 0;
}
第11题 最长单词
对于这道题,咱们先来一个简单方法:
//最长单词
//一个以'.'结尾的简单英文句子,单词之间用空格分隔,没有缩写形式和其它特殊形式,求句子中的最长单词。
//输入这个简单英文句子,长度不超过500。
//输出该句子中最长的单词。如果多于一个,则输出第一个。
//输入样例:
//I am a student of Peking University.
//输出样例:
//University
//方法一
int main() {
string s;
string res = "";
while (cin >> s) {
if (s.back() == '.') s.pop_back(); //如果当前字符串的最后一个字符为'.'
//那么就调用pop_back()函数
//把最后这个字符删除
if (s.size() > res.size()) res = s; //如果字符串s的长度大于之前res的长度
//将新的字符串赋给res
}
cout << res << endl;
return 0;
}
另外,s.back() == '.' 也可以写成 s[s.size()-1] == '.'
第12题 倒排单词
对于这道题,咱们先来试一试~
//倒排单词
//编写程序,读入一行英文(只包含字母和空格,单词间以单个空格分隔),
//将所有单词的顺序倒排并输出,依然以单个空格分隔。
//输入为一个字符串(字符串长度至多为100)。
//输出为按要求排序后的字符串。
//输入样例 :
//I am a student
//输出样例 :
//student a am I
int main() {
string a[100]; //定义一个字符串数组,可以存放100个字符串
int i = 0;
while (cin >> a[i]) i++; //往字符串a数组里面存入元素时,下标i自增
for (int j = i - 1; j >= 0; j--) //下标j从最后一个元素的下标开始,从后往前遍历整个字符串数组
{
cout << a[j] << " ";
}
return 0;
}
片尾
今天我们学习了字符串相关的习题,希望这篇文章对友友们有所帮助!!!
求点赞收藏加关注!!!
谢谢大家!!!