本篇将介绍一种新的变量类型:字符串。
字符串与字符数组不同的地方就在于:字符数组的大小在声明时就已经定了下来;而字符串的大小是可以改变的,当你往字符串里面添加元素时,字符串的大小也会相应地改变。下面介绍对于字符串的操作(转载自YCOJ):
s.size(); // 得到字符串长度
s.find(); // 查找字符或子串所在位置,若存在子串则返回子串开头字符下标,否则返回-1
s.find('a');
s.find("hello");
s.find("hello", 2);//从字符串s下标2往后面查找
s.replace(); // 字符串s某个部分替换成另一个字符串
s.replace(0, 5, "hello");//字符串s从下标0开始,长度为5的部分替换成"hello"
s.substr(); // 取字符串某个部分(子串)
s.substr(2); //取字符串s从下标2开始到结束的部分
s.substr(2,5); //取字符串s从下标2开始长度为5的部分
△ 字符串拼接
s = s + 'a';
s = s + "hello";
s += "hello";
s = "hello" + "world";//注意,这种写法是错的(想一想为什么?)
getline(); // 读入一行,用法:
getline(cin, s);
△ 字典序 联系英语词典单词的排序方式,如果你能够轻松的对这几个字符串按字典序排序,那么可以断定你已经理解了:
abs
ab
abc
abcde
△ 字典序比较:string类型的字符串也可用下面比较符
>
<
==
>=
<=
!=
下面是一些字符串的习题:
字符串中A的数量
Description
输入一个字符串,统计其中字符 A 的数量并且输出。
Input
输入共有一行,为一个不带空格的字符串(其中字符数不超过 100)。
Output
输出一行,包含一个整数, 为输入字符串中的 A 的数量。
这题只需要用size()函数得到字符串的长度,然后用for循环一个字符一个字符地访问看是不是'A’就可以了:
#include<iostream>
#include<cstring>//有关字符串的操作都需要加上cstring的头文件
using namespace std;
int main(){
string s;
cin >> s;
int cnt = 0;//记录'A'出现的次数
for(int i = 0; i < s.size(); i++){
if(s[i] == 'A'){
cnt++;
}
}
cout << cnt;
return 0;
}
*这里需要注意的是,字符串的下标是从0开始,到字符串长度减一结束的。
当然了,使用find()函数也是可以做的,但是对下标的控制需要熟练:
#include<iostream>
#include<cstring>
using namespace std;
int main(){
string s;
cin >> s;
int cnt = 0;
int d = -1;//存储下标的值
do{
d = s.find('A', d + 1);
if(d != -1) cnt++;
}while(d != -1);
cout << cnt;
return 0;
}
下一个字母
Description
从键盘输入一个长度大于 10 的字符串,现要求:将字符串中的所有大小写字母都改写成该字母的下一个字母;特殊的,小写字母 z 改写成字母 a;大写字母 Z 改写成 A,其他字符依照原有顺序不变。
Input
输入只有一行,包含 1 个任意的不带有空格的字符串(其长度在 10 到 1000 之间)。
Output
输出只有一行,即为满足条件的字符串。
对于字符,是可以当做整数来进行运算的(具体参照ASCII码)。这题需要对'Z'和‘z’进行特殊判断一下。代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int main(){
string str;
cin >> str;
int len = str.size();
for(int i = 0; i < len; i++){
if((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z') ){
str[i]++;
if(str[i] > 'Z' && str[i] < 'a') str[i] = 'A';
else if(str[i] > 'z') str[i] = 'a';
}
}
cout << str << endl;
return 0;
}
选小寿星
Description
五年级一班有一个传统,全班一起庆祝当月过生日的同学。有 m 名学生都是 1 月份过生日,班主任决定挑一名学生作为寿星代表切蛋糕。班主任将过生日的 m 名学生随机围成一个圈,从 1 到 m 进行编号。随机挑一个数字 n(1≤n≤9),从第一个同学开始连续报数,报数到 n 的同学就出局,然后从下一位 同学重新开始报数,一直到剩下最后一名同学。由于女生少,班主任决定每个女生有 2 次机会,也就是说,每名女生第 2 次数到 n 时才出局。
例如,m=3,其中有 1 名女生,编号顺序为 1,2,3,分别是男,女,男,n=2。第一轮报数,报到的是 2 号女生,暂不出局(注:女生有 2 次机会)。第二轮报数,3 号男生报 1,1 号男生报 2 出局。第三轮报数,2 号女生报 1,3 号男生报 2 出局,最后留下 2 号女生。
Input
输入第一行输入数字为 m,表示有 m 个人,m<20。
第二行是 m 个整数,1 代表男生,0 代表女生。
第三行是 n,表示 n 是出局数字。(注意:女生有 2 次机会)
Output
输出留下学生的序号,中间用空格隔开。
这题就比较经典了。这题需要将出局的学生进行标记,直到只有一个人未被标记时,游戏结束。
#include<iostream>
using namespace std;
const int maxn = 10000 + 5;
bool sex[maxn];//记录学生的性别,0为女生、1为男生
int main(){
int m; cin >> m;
for (int i = 1 ; i <= m ; i++) cin >> sex[i];
int n; cin >> n;
int stu[maxn];
for (int i = 1 ; i <= m ; i++) {
if (sex[i] == 0) stu[i] = 2 ;//女生两次机会
else stu[i] = 1;//男生一次机会
}
int t = 0 ;
int chance = 0 ;//记录总共的机会数
for(int i = 1 ; i <= m ; i++) chance += stu[i] ;
for (int i = 1 ; ; i++) {
if(chance == 1) break ;//当总机会数只剩下1时,不论剩下男生还是女生,游戏都将结束
if(i == m+1) i = 1 ;//将队伍的首位连接起来
if(stu[i] == 0) continue ;//如果轮到的人已经出局,不进行下面的操作,进行下一次循环
t++ ;//报数
if(t == n){
t = 0 ;
stu[i]-- ;
chance-- ;
}//报到n的人减少一次机会,总机会数也减一,报出的数归零。
}
int temp = 0 ;
for(int i = 1 ; i <= m ; i++){
if(stu[i] != 0) cout << i ;//寻找未出局的人
}
return 0 ;
}
这里是考察对数据的操控。
规范化名字
Description
一个 名单里面有大型机械的很多零部件名,但是由于制作这个名单的人习惯不太好,零部件的名称的大小写很混乱。有的是大写字母开头,有些是小写字母开头,零部件名称中间的字符也是大小写混乱。
请你设计程序,将名单上零部件的名称都变为开头字母大写,后面字母全小写的形式。
Input
输入第一行只有一个正整数 N,表示名单上的零部件(1≤N≤100)。
之后的 N 行: 为 N 个零部件的名称。
Output
输出为 N 行,为所有 N 个零部件的名称, 首字母为大写,后面 的字母为小写。
这里要用到c++中的两个函数:toupper(),tolower(),它们的作用分别是将字母转大写、转小写。代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int main(){
int n; cin >> n;
string name[n + 1];
for(int i = 1; i <= n; i++) cin >> name[i];
int len[n + 1];
for(int i = 1; i <= n; i++){
len[i] = name[i].size();
}
for(int i = 1; i <= n; i++){
for(int j = 0; j < len[i]; j++){
if(j == 0) name[i][j] = toupper(name[i][j]);
else name[i][j] = tolower(name[i][j]);
}
}
for(int i = 1; i <= n; i++){
cout << name[i] << endl;
}
return 0;
}
禁止吸烟
Description
小信的学校设计了很多的标语,但是中间很多地方都把 No_smoking 写成了 Ban_smoking。请你找到这些错误并将他们替换成正确的结果。
Input
输入第一行为 N 表示总共的标语数量。
之后的 N 行每行是一个待处理的标语。每个标语中不带有任何的空格。
Output
输出为 N 行, 为经过处理后的所有的标语。输出顺序与输入时保持 一致。
这题只要灵活使用find()、replace()就可以了。代码如下:
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 10000+5;
const string wstr = "Ban_smoking", re = "No_smoking";
const int lenws = 11;//"Ban_smoking"的长度
int main(){
int n;
cin >> n;
string sign[maxn];
for(int i = 1; i <= n; i++) cin >> sign[i];
for(int i = 1; i <= n; i++){
int beg;
beg = sign[i].find(wstr);
while(beg != -1){
sign[i].replace(beg, lenws, re);
beg = sign[i].find(wstr);
}
cout << sign[i] << endl;
}
return 0;
}