字符

ASCII码

每个常用字符都对应一个-128~127的数字,两者之间可以互相转化。48~57对应阿拉伯数字0~9,ascii码65~90对应大写字母A~Z,小写英文字母a从97开始到122,大小写相差32。

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main()
{
char c = 'a';

cout << (int)c << endl;
cout << (char)97 << endl;

return 0;
}

输出

1
2
97
a

字符与数字可以相互转换,字符参与运算会把他当成整数

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main()
{
printf("%d\n", 'b' - 'a');
printf("%d\n", 'z' - 'a');
printf("%c\n", 'a' + 3);

return 0;
}

输出

1
2
3
1
25
d

练习

输入一行字符,统计出其中数字字符的个数,以及字母字符的个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

int main()
{
char c;
int nums = 0, chars = 0;
while (cin >> c)
{
if (c >= 48 && c <= 57)
nums ++;
else if (c >= 65 && c <= 90 || c >= 97 && c <= 122)
chars ++;
}

printf("numbers: %d\ncharacters: %d", nums, chars);

return 0;
}

输入

1
episode13

输出

1
2
numbers: 2
characters: 7

字符数组、字符串

字符串就是字符数组加上结束符\0。字符串是表面的,字符数组是底层用来存储字符串的。

可以使用字符串来初始化字符数组,但此时要注意,每个字符串结尾会暗含一个’\0’字符,因此字符数组的长度至少要比字符串的长度多1。

字符数组的初始化

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main()
{
char a1[] = {'c', '+', '+'}; //列表初始化,没有空字符,是字符数组但不是字符串
char a2[] = {'c', '+', '+', '\0'}; //列表初始化,含有显示的空字符,是字符串
char a3[] = "c++"; //自动添加表示字符串结尾的空字符,用字符串初始化字符数组
char a4[3] = "c++"; //错误!没有空间存放空字符

return 0;
}

字符数组的输入、输出

输出

使用cout、printf()输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
char a[] = "episodexiii";

cout << a << endl;
printf("%s\n", a);

cout << a + 7 << endl; //从特定位置开始输出
printf("%s\n", a + 10); //从特定位置开始输出

return 0;
}

输出

1
2
3
4
episodexiii
episodexiii
xiii
i

需要输出字符串时,可以使用puts()函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string.h>
using namespace std;

int main()
{
char s[100];

scanf("%s", s);

puts(s);

return 0;
}

输入

1
epxiii

输出

1
epxiii

输入

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
char arr[100];

scanf("%s", arr); //用scanf输入数组时不能加“&”,数组的名字本身就是指针
cout << arr << endl;

return 0;
}

输入

1
ep13

输出

1
ep13

从指定位置开始输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
char arr[100];

cin >> arr + 1; //从指定位置开始输入
cout << arr + 1 << endl;
cout << arr[1] << endl;

return 0;
}

输入

1
ep13

输出

1
2
ep13
e

读入字符串时,遇到空格、回车或结束才会停止。

  • 可以使用fgets()函数读入带有空格的字符数组。fgets(a, b, c)第一个参数是要读入的字符数组名,第二个是要读入的长度,第三个决定从哪个文件读入,一般使用“stdin”。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
    #include <cstdio>
    using namespace std;

    int main()
    {
    char arr[100];

    fgets(arr, 100, stdin);

    cout << arr << endl;

    return 0;
    }
    输入
    1
    ep 13
    输出
    1
    ep 13
  • 也可以使用cin.getline()读入字符数组,两个参数分别为要读入的字符数组名与要读入的长度。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
    #include <cstdio>
    using namespace std;

    int main()
    {
    char arr[100];

    cin.getline(arr, 100);

    printf("%s", arr);

    return 0;
    }
  • 如果读入的是string类型而不是char数组,则可以使用包含在<string.h>头文件中的getline()函数,两个参数第一个固定为“cin”,第二个是要读入的字符串名。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
    #include <string.h>
    using namespace std;

    int main()
    {
    string a;

    getline(cin, a);

    cout << a << endl;

    return 0;
    }

字符数组的常用操作

对字符串进行操作需要引入数头文件<string.h>`。

  • strlen(str),求字符串长度,但不包含最后的\0字符。
  • strcmp(a, b),比较两个字符串大小,若a < b返回-1a == b返回0a > b返回1,比较方式是字典序。
  • strcpy(a, b),将字符串b复制给从a开始的字符数组。

遍历字符数组中的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char s[100];

scanf("%s", s);

for (int i = 0; i < strlen(s); i ++) //此处可以提前用一个变量存放strlin(s)的值,避免每次执行循环都要执行一遍strlen(s)
cout << s[i] << endl;

return 0;
}

输入

1
franxx

输出

1
2
3
4
5
6
f
r
a
n
x
x

练习

  1. 给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//我的方法,会超时
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char s[100001] = {0};
char t[100001] = {0};
cin >> s;
int l = strlen(s);
strcpy(t, s);

for (int i = 0; i < l; i ++)
{
bool k = true;

for (int j = 0; j < l; j ++)
{
if (i == j)
continue;

if (s[i] == t[j])
k = false;
}

if (k == true)
{
cout << s[i] << endl;
return 0;
}

}
cout << "no" << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//正确方法
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char s[100010] = {0};
int cnt[26] = {0}; //初始化一个数组存储每个字符出现的次数
cin >> s;
int l = strlen(s);

for (int i = 0; i < l; i ++)
{
cnt[s[i] - 97] ++;
}

for (int i = 0; i < l; i ++)
{
if (cnt[s[i] - 97] == 1)
{
cout << s[i];
return 0;
}
}

cout << "no" << endl;

return 0;
}
  1. 把一个字符串中特定的字符全部用#替换,得到一个新的字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char s[31];
char c;
cin >> s >> c;
int l = strlen(s);

for (int i = 0; i < l; i ++)
{
if (s[i] == c)
s[i] = '#';
}

for (int i = 0; i < l; i ++)
cout << s[i];

return 0;
}

标准库类型string

可变长的字符序列,需要引入头文件#include <string>,或可以直接包括在<iostream>中。

定义与初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
string s1; //定义一个空的字符串
string s2 = s1; //定义字符串s2等于s1
string s3 = "franxx"; //直接赋值
string s4(10, 'c'); //s4的内容是:cccccccccc

return 0;
}

string的操作

string的读写

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <string>
using namespace std;

int main()
{
string s1, s2;
cin >> s1 >> s2;
cout << s1 << ' ' << s2;

return 0;
}
  • string读入一行可以使用getline(cin, s1),字符串用cin.getline(s2, 1000)
  • 无法用scanf()读入string类型的变量,但是可以用printf("%s\n", s1.c_srt())输出,也可以用puts(s1.c_str())输出。

string的判断

使用empty判断string变量是否为空,返回bool值,若为空则s.empty()的值为1,否则为0。
使用size判断string变量长度,s.size()不需要遍历一遍,所以时间复杂度比类似的strlen()更低。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;

int main()
{
string s1, s2 = "franxx";

cout << s1.empty() << endl;
cout << s2.empty() << endl;

cout << s1.size() << endl;
cout << s2.size() << endl;

return 0;
}

输出

1
2
3
4
1
0
0
6

string的比较

支持 >, <, >=, <=, ==, !=等所有比较操作,按字典序进行比较。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
using namespace std;

int main()
{
string s1 = "abc", s2 = "abd";

if (s1 > s2)
cout << "s1 > s2" << endl;
else
cout << "s1 <= s2" << endl;

return 0;
}

输出

1
s1 <= s2

string加法

两个string相加是直接把两个拼在一起,没有减法、乘法、除法操作。string在与字面值和字符相加时,会把字面值和字符转化成string对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;

int main()
{
string s1 = "dar", s2 = "ling";

string s3 = s1 + s2;
string s4 = s3 + " in the franxx";

cout << s3 << endl;
cout << s4 << endl;

return 0;
}

输出

1
2
darling
darling in the franxx

※在对字符串做加法时,必须保证+左右至少有一个string类型。

1
2
string s = s1 + ", " + "world";  // 正确,每个加法运算都有一个运算符是string
string s = "hello" + ", " + s2; // 错误:不能把字面值直接相加,运算是从左到右进行的

处理string对象中的字符

可以把string对象当成字符数组处理

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;

int main()
{
string s = "franxx";

for (int i = 0; i < s.size(); i ++)
cout << s[i] << endl;

return 0;
}

输出

1
2
3
4
5
6
f
r
a
n
x
x

或者使用基于范围的for语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;

int main()
{
string s = "franxx";

for (char c : s) //C++的范围遍历,前面是字符数组里的类型char,用c遍历s里的每一个char变量,但是不能用于改变s里的值,如果想改变s的值,可以使用&c。
cout << c << endl;

return 0;
}

输出

1
2
3
4
5
6
f
r
a
n
x
x

例题

  1. 字符串长度

    给定一行长度不超过 100 的非空字符串,请你求出它的具体长度。

    输入格式

    输入一行,表示一个字符串。注意字符串中可能包含空格

    输出格式

    输出一个整数,表示它的长度。

    输入样例

    1
    I love Beijing.

    输出样例

    1
    15

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
    #include <string>
    using namespace std;

    int main()
    {
    string s;
    getline(cin, s);

    cout << s.size() << endl;

    return 0;
    }
  2. 字符串中的数字个数

    输入一行字符,长度不超过 100,请你统计一下其中的数字字符的个数。

    输入格式

    输入一行字符。注意其中可能包含空格。

    输出格式

    输出一个整数,表示字数字字符的个数。

    输入样例

    1
    I am 18 years old this year.

    输出样例

    1
    2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <iostream>
    #include <string>
    using namespace std;

    int main()
    {
    string s;
    getline(cin, s);
    int k = 0;

    for (int i = 0; i < s.size(); i ++)
    {
    if (s[i] >= 48 && s[i] <= 57)
    {
    k ++;
    }

    }

    cout << k << endl;

    return 0;
    }
  3. 循环相克令

    循环相克令是一个两人玩的小游戏。

    令词为“猎人、狗熊、枪”,两人同时说出令词,同时做出一个动作——猎人的动作是双手叉腰;狗熊的动作是双手搭在胸前;枪的动作是双手举起呈手枪状。

    双方以此动作判定输赢,猎人赢枪、枪赢狗熊、狗熊赢猎人,动作相同则视为平局。

    现在给定你一系列的动作组合,请你判断游戏结果。

    输入格式

    第一行包含整数 T,表示共有 T 组测试数据。

    接下来 T 行,每行包含两个字符串,表示一局游戏中两人做出的动作,字符串为 Hunter, Bear, Gun 中的一个,这三个单词分别代表猎人,狗熊和枪。

    输出格式

    如果第一个玩家赢了,则输出 Player1。

    如果第二个玩家赢了,则输出 Player2。

    如果平局,则输出 Tie。

    输入样例

    1
    2
    3
    4
    3
    Hunter Gun
    Bear Bear
    Hunter Bear

    输出样例

    1
    2
    3
    Player1
    Tie
    Player2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <iostream>
    #include <string>
    using namespace std;

    int main()
    {
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++)
    {
    string s1, s2;
    cin >> s1 >> s2;
    if (s1 == s2)
    cout << "Tie" << endl;
    else if (s1 == "Hunter")
    {
    if (s2 == "Bear")
    cout << "Player2" << endl;
    else
    cout << "Player1" << endl;
    }
    else if (s1 == "Bear")
    {
    if (s2 == "Gun")
    cout << "Player2" << endl;
    else
    cout << "Player1" << endl;
    }
    else if (s1 == "Gun")
    {
    if (s2 == "Hunter")
    cout << "Player2" << endl;
    else
    cout << "Player1" << endl;
    }
    }

    return 0;
    }
  4. 字符串加空格

    给定一个字符串,在字符串的每个字符之间都加一个空格。

    输出修改后的新字符串。

    输入格式

    共一行,包含一个字符串。注意字符串中可能包含空格。

    输出格式

    输出增加空格后的字符串。

    输入样例

    1
    2
    3
    test case

    输出样例

    1
    t e s t   c a s e

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <iostream>
    using namespace std;

    int main()
    {
    string s;
    getline(cin, s);

    for (char c : s)
    {
    cout << c << ' ';
    }

    return 0;
    }
  5. 替换字符

    给定一个由大小写字母构成的字符串。

    把该字符串中特定的字符全部用字符 # 替换。

    请你输出替换后的字符串。

    输入格式

    输入共两行。

    第一行包含一个长度不超过 30 的字符串。

    第二行包含一个字符,表示要替换掉的特定字符。

    输出格式

    输出共一行,为替换后的字符串。

    输入样例

    1
    2
    hello
    l

    输出样例

    1
    he##o

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
    using namespace std;

    int main()
    {
    string s;
    char c;
    cin >> s >> c;

    for (int i = 0; i < s.size(); i ++)
    {
    if (s[i] == c)
    s[i] = '#';
    }
    cout << s << endl;

    return 0;
    }
  6. 字符串插入

    有两个不包含空白字符的字符串 strsubstrstr 的字符个数不超过 10,substr 的字符个数为 3。(字符个数不包括字符串结尾处的 \0。)

    substr 插入到 str 中 ASCII 码最大的那个字符后面,若有多个最大则只考虑第一个。

    输入格式

    输入包括若干行,每一行为一组测试数据,格式为

    str substr

    输出格式

    对于每一组测试数据,输出插入之后的字符串。

    输入样例

    1
    2
    abcab eee
    12343 555

    输出样例

    1
    2
    abceeeab
    12345553

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include <iostream>
    using namespace std;

    int main()
    {
    string str, substr;
    while (cin >> str >> substr)
    {
    char max = str[0];
    int k = 0;
    for (int i = 1; i < str.size(); i ++)
    {
    if (str[i] > max)
    {
    max = str[i];
    k = i;
    }
    }
    for (int i = 0; i <= k; i ++)
    cout << str[i];

    cout << substr;

    for (int j = k + 1; j <str.size(); j ++)
    cout <<str[j];

    cout << endl;
    }

    return 0;
    }
  7. 只出现一次的字符

    给你一个只包含小写字母的字符串。

    请你判断是否存在只在字符串中出现过一次的字符。

    如果存在,则输出满足条件的字符中位置最靠前的那个。

    如果没有,输出 no。

    输入格式

    共一行,包含一个由小写字母构成的字符串。

    数据保证字符串的长度不超过 100000。

    输出格式

    输出满足条件的第一个字符。

    如果没有,则输出 no

    输入样例

    1
    abceabcd

    输出样例

    1
    e

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include <iostream>
    using namespace std;

    int main()
    {
    string s;
    cin >> s;
    char cnt[26] = {0};

    for (int i = 0; i < s.size(); i ++)
    {
    cnt[s[i] - 97] ++;
    }

    for (int i = 0; i < s.size(); i ++)
    {
    if (cnt[s[i] - 97] == 1)
    {
    cout << s[i] << endl;
    return 0;
    }
    }
    cout << "no" << endl;

    return 0;
    }

习题

  1. 字符串匹配

    给定两个长度相同的字符串 a 和字符串 b。

    如果在某个位置 i 上,满足字符串 a 上的字符 a[i] 和字符串 b 上的字符 b[i] 相同,那么这个位置上的字符就是匹配的。

    如果两个字符串的匹配位置的数量与字符串总长度的比值大于或等于 k,则称两个字符串是匹配的。

    现在请你判断给定的两个字符串是否匹配。

    输入格式

    第一行包含一个浮点数 k,第二行包含字符串 a,第三行包含字符串 b。

    输入的字符串中不包含空格。

    输出格式

    如果两个字符串匹配,则输出 yes。

    否则,输出 no。

    输入样例

    1
    2
    3
    0.4
    abcde
    xbacd

    输出样例

    1
    no

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <iostream>
    using namespace std;
    int main()
    {
    string s1, s2;
    double rate;
    cin >> rate >> s1 >> s2;
    double k = 0;

    for (int i = 0; i < s1.size(); i ++)
    {
    if (s1[i] == s2[i])
    k ++;
    }

    if (k / s1.size() < rate)
    cout << "no" << endl;
    else
    cout << "yes" << endl;

    return 0;
    }
  2. 忽略大小写比较字符串大小

    一般我们用 strcmp 可比较两个字符串的大小,比较方法为对两个字符串从前往后逐个字符相比较(按 ASCII 码值大小比较),直到出现不同的字符或遇到 \0 为止。

    如果全部字符都相同,则认为相同;如果出现不相同的字符,则以第一个不相同的字符的比较结果为准。

    但在有些时候,我们比较字符串的大小时,希望忽略字母的大小,例如 Hellohello 在忽略字母大小写时是相等的。

    请写一个程序,实现对两个字符串进行忽略字母大小写的大小比较。

    输入格式

    输入为两行,每行一个字符串,共两个字符串。注意字符串中可能包含空格。

    数据保证每个字符串的长度都不超过 80。

    输出格式

    如果第一个字符串比第二个字符串小,输出一个字符 <

    如果第一个字符串比第二个字符串大,输出一个字符 >

    如果两个字符串相等,输出一个字符 =

    否则,输出 no

    输入样例

    1
    2
    Hello
    hello

    输出样例

    1
    =

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include <iostream>
    using namespace std;

    int main()
    {
    string s1, s2, subs1, subs2;
    getline(cin, s1);
    getline(cin, s2);

    for (int i = 0; i < s1.size(); i ++)
    if (s1[i] >= 'a' && s1[i] <='z')
    s1[i] = s1[i] - 32;

    for (int i = 0; i < s1.size(); i ++)
    if (s2[i] >= 'a' && s2[i] <='z')
    s2[i] = s2[i] - 32;

    if (s1 < s2)
    cout << '<' << endl;
    else if (s1 > s2)
    cout << '>' << endl;
    else
    cout << '=' << endl;

    return 0;
    }
  3. 去掉多余的空格

    输入一个字符串,字符串中可能包含多个连续的空格,请将多余的空格去掉,只留下一个空格。

    输入格式

    共一行,包含一个字符串。

    输出格式

    输出去掉多余空格后的字符串,占一行。

    输入样例

    1
    Hello      world.This is    c language.

    输出样例

    1
    Hello world.This is c language.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <iostream>
    using namespace std;

    int main()
    {
    string s;
    while (cin >> s)
    cout << s << ' ';

    return 0;
    }
  4. 信息加密

    在传输信息的过程中,为了保证信息的安全,我们需要对原信息进行加密处理,形成加密信息,从而使得信息内容不会被监听者窃取。

    现在给定一个字符串,对其进行加密处理。

    加密的规则如下:

    • 字符串中的小写字母,a 加密为 bb 加密为 c,…,y 加密为 zz 加密为 a。
    • 字符串中的大写字母,A 加密为 BB 加密为 C,…,Y 加密为 ZZ 加密为 A
    • 字符串中的其他字符,不作处理。
      请你输出加密后的字符串。

    输入格式

    共一行,包含一个字符串。注意字符串中可能包含空格。

    输出格式

    输出加密后的字符串。

    输入样例

    1
    Hello! How are you!

    输出样例

    1
    Ifmmp! Ipx bsf zpv!


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <iostream>
    using namespace std;

    int main()
    {
    string s;
    while (getline(cin, s))
    {
    for (int i = 0; i < s.size(); i ++)
    {
    if ((s[i] >= 'a' && s[i] <= 'y') || (s[i] >= 'A' && s[i] <= 'Y'))
    s[i] = s[i] + 1;
    else if (s[i] == 'z')
    s[i] = 'a';
    else if (s[i] == 'Z')
    s[i] = 'A';
    }

    cout << s;
    }

    return 0;
    }

  5. 输出字符串

    给定一个字符串 a,请你按照下面的要求输出字符串 b。

    给定字符串 a 的第一个字符的 ASCII 值加第二个字符的 ASCII 值,得到 b 的第一个字符;

    给定字符串 a 的第二个字符的 ASCII 值加第三个字符的 ASCII 值,得到 b 的第二个字符;

    给定字符串 a 的倒数第二个字符的 ASCII 值加最后一个字符的 ASCII 值,得到 b 的倒数第二个字符;

    给定字符串 a 的最后一个字符的 ASCII 值加第一个字符的 ASCII 值,得到 b 的最后一个字符。

    输入格式

    输入共一行,包含字符串 a。注意字符串中可能包含空格。

    数据保证字符串内的字符的 ASCII 值均不超过 63。

    输出格式

    输出共一行,包含字符串 b。

    输入样例

    1
    1 2 3

    输出样例

    1
    QRRSd

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <iostream>
    using namespace std;

    int main()
    {
    string a, b;
    getline(cin, a);

    for (int i = 0; i < a.size() - 1; i ++)
    {
    b[i] = a[i] + a[i + 1];
    }

    b[a.size() - 1] = a[a.size() - 1] + a[0];

    for (int i = 0; i < a.size(); i ++)
    cout << b[i];

    return 0;
    }
  6. 单词替换

    输入一个字符串,以回车结束(字符串长度不超过 100)。

    该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。

    现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。

    输入格式

    输入共 3 行。

    第 1 行是包含多个单词的字符串 s;

    第 2 行是待替换的单词 a(长度不超过 100);

    第 3 行是 a 将被替换的单词 b(长度不超过 100)。

    输出格式

    共一行,输出将 s 中所有单词 a 替换成 b 之后的字符串。

    输入样例

    1
    2
    3
    You want someone to help you
    You
    I

    输出样例

    1
    I want someone to help you

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
        #include <iostream>
    #include <sstream> //"<sstream>"头文件包含stringstream
    using namespace std;

    int main()
    {
    string s, a, b, word;
    getline(cin, s);
    cin >> a >> b;

    stringstream ssin(s); //使用stringstream将字符串分割成字符串流

    while (ssin >> word) //可以将stringstream处理后的字符串流直接输入到字符串里
    {
    if (word != a)
    cout << word << ' ';
    else if (word == a)
    cout << b << ' ';

    }
    return 0;
    }

    7. **字符串中最长的连续出现的字符**

    求一个字符串中最长的连续出现的字符,输出该字符及其出现次数,字符串中无空白字符(空格、回车和 tab),如果这样的字符不止一个,则输出第一个。

    **输入格式**

    第一行输入整数 N,表示测试数据的组数。

    每组数据占一行,包含一个不含空白字符的字符串,字符串长度不超过 200

    **输出格式**

    共一行,输出最长的连续出现的字符及其出现次数,中间用空格隔开。

    **输入样例**

    2
    aaaaabbbbbcccccccdddddddddd
    abcdefghigk

    1
    2
    3

    **输出样例**

    d 10
    a 1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40

    **解**
    ```C++
    //双指针算法
    #include <iostream>
    using namespace std;

    int main()
    {
    int n;
    cin >> n;
    while (n --)
    {
    string s;
    cin >> s;

    int cnt = 0;
    char c;

    for (int i = 0; i < s.size(); i ++) //从i = 0开始遍历整个字符串
    {
    int j = i; //从i开始向后遍历
    while (j < s.size() && s[i] == s[j])
    j ++;

    if (j - i > cnt)
    {
    cnt = j - i;
    c = s[i];
    }

    i = j - 1;

    }

    cout << c << ' ' << cnt << endl;
    }

    return 0;
    }
  7. 最长单词

    一个以. 结尾的简单英文句子,单词之间用空格分隔,没有缩写形式和其它特殊形式,求句子中的最长单词。

    输入格式

    输入一行字符串,表示这个简单英文句子,长度不超过 500。

    输出格式

    该句子中最长的单词。如果多于一个,则输出第一个。

    输入样例

    1
    I am a student of Peking University.

    输出样例

    1
    University

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <iostream>
    using namespace std;

    int main()
    {
    string s, ans;

    while (cin >> s)
    {
    if (s.back() == '.') //s.back()返回字符串s最后一个字符
    s.pop_back(); //s.pop_back()删除字符串s最后一个字符

    if (s.size() > ans.size())
    ans = s;
    }

    cout << ans << endl;

    return 0;
    }
  8. 倒排单词

    编写程序,读入一行英文(只包含字母和空格,单词间以单个空格分隔),将所有单词的顺序倒排并输出,依然以单个空格分隔。

    输入格式

    输入为一个字符串(字符串长度至多为 100)。

    输出格式

    输出为按要求排序后的字符串。

    输入样例

    1
    I am a student

    输出样例

    1
    student a am I

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <iostream>

    using namespace std;

    int main()
    {
    string s[100];
    int n = 0;

    while (cin >> s[n]) //只要还有输入值就能继续读入并得到一共有多少单词
    n ++;

    for (int i = n - 1; i >= 0 ; i -- )
    cout << s[i] << ' ';

    return 0;
    }
  9. 字符串移位包含问题

    对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾形成新的字符串。

    给定两个字符串 s1 和 s2,要求判定其中一个字符串是否是另一字符串通过若干次循环移位后的新字符串的子串。

    例如 CDAA 是由 AABCD 两次移位后产生的新串 BCDAA 的子串,而 ABCD 与 ACBD 则不能通过多次移位来得到其中一个字符串是新串的子串。

    输入格式

    共一行,包含两个字符串,中间由单个空格隔开。

    字符串只包含字母和数字,长度不超过 30。

    输出格式

    如果一个字符串是另一字符串通过若干次循环移位产生的新串的子串,则输出 true,否则输出 false。

    输入样例

    1
    AABCD CDAA

    输出样例

    1
    true

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #include <iostream>
    #include <algorithm>

    using namespace std;

    int main()
    {
    string s1, s2;
    cin >> s1 >> s2;
    if (s1.size() < s2.size())
    {
    string tmp = s2;
    s2 = s1;
    s1 = tmp;
    }

    string s = s1;

    for (int i = 0; i < s1.size(); i ++)
    {
    s1 = s;
    reverse(s1.begin(), s1.begin() + s1.size());
    reverse(s1.begin(), s1.begin() + i);
    reverse(s1.begin() + i, s1.begin() + s1.size());

    if (s1.find(s2) != -1) //使用s1.find(s2)寻找s2是否是s1的子串,如果不是返回-1,如果找到,返回子串在母串中的位置(下标)
    {
    cout << "true" << endl;
    return 0;
    }
    }

    cout << "false" << endl;

    return 0;
    }
  10. 字符串乘方

    给定两个字符串 ab,我们定义 a×b 为他们的连接。

    例如,如果 a=abcb=def, 则 a×b=abcdef

    如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a0=``(空字符串),a(n+1)=a×(an)

    输入格式

    输入包含多组测试样例,每组测试样例占一行。

    每组样例包含一个由小写字母构成的字符串 ss 的长度不超过 100,且不包含空格。

    最后的测试样例后面将是一个点号作为一行。

    输出格式

    对于每一个 s,你需要输出最大的 n,使得存在一个字符串 a,让 s=an

    输入样例

    1
    2
    3
    4
    abcd
    aaaa
    ababab
    .

    输出样例

    1
    2
    3
    1
    4
    3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #include <iostream>

    using namespace std;

    int main()
    {
    string str;
    while (cin >> str, str != ".")
    {
    int len = str.size();

    for (int n = len; n; n --)
    {
    if (len % n == 0)
    {
    int m = len / n;
    string s = str.substr(0, m); //str.substr(0, m)输出从第一个字符开始到第m个字符结束的字符串

    string r;
    for (int i = 0; i < n; i ++)
    r += s;

    if (r == str)
    {
    cout << n << endl;
    break;
    }
    }
    }
    }

    return 0;
    }
  11. 字符串最大跨距

    有三个字符串 S,S1,S2,其中,S 长度不超过 300,S1 和 S2 的长度不超过 10。

    现在,我们想要检测 S1 和 S2 是否同时在 S 中出现,且 S1 位于 S2 的左边,并在 S 中互不交叉(即,S1 的右边界点在 S2 的左边界点的左侧)。

    计算满足上述条件的最大跨距(即,最大间隔距离:最右边的 S2 的起始点与最左边的 S1 的终止点之间的字符数目)。

    如果没有满足条件的 S1,S2 存在,则输出 −1。

    例如,S= abcd123ab888efghij45ef67kl, S1= ab, S2= ef,其中,S1 在 S 中出现了 2 次,S2 也在 S 中出现了 2 次,最大跨距为:18。

    输入格式

    输入共一行,包含三个字符串 S,S1,S2,字符串之间用逗号隔开。

    数据保证三个字符串中不含空格和逗号。

    输出格式

    输出一个整数,表示最大跨距。

    如果没有满足条件的 S1 和 S2 存在,则输出 −1。

    输入样例

    1
    abcd123ab888efghij45ef67kl,ab,ef

    输出样例

    1
    18

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include <iostream>

    using namespace std;

    int main()
    {
    string s, s1, s2;
    char c;

    while (cin >> c, c != ',') //输入中间用“,”分隔时用这种方法读入
    s += c;
    while (cin >> c, c != ',')
    s1 += c;
    while (cin >> c)
    s2 += c;

    if (s.size() < s1.size() || s.size() < s2.size())
    cout << -1;
    else
    {
    //判断s1在s中所在位置
    int l = 0; //l表示匹配s1时的起点
    while (l + s1.size() < s.size())
    {
    int k = 0; //k表示从起点l处前进了多少位
    while (k < s1.size())
    {
    if (s[l + k] != s1[k]) //从l处前进k位和s1的第k位不相等的话,不匹配跳出循环
    break;

    k ++;
    }

    if (k == s1.size()) //如果s送l处开始前进k位直到等于s1的长度,还和s1相同,则s1所在位置就是k处
    break;

    l ++;
    }

    //判断s2在s中所在位置,从右往左
    int r = s.size() - s2.size(); //r表示匹配s2时的起点
    while (r >= 0)
    {
    int k = 0;
    while (k < s2.size())
    {
    if (s[r + k] != s2[k])
    break;

    k ++;
    }

    if (k == s2.size())
    break;

    r --;
    }

    l += s1.size() -1; //再把l赋值为s1结束的位置

    if (l >= r) //判断s1是否在s2左边
    cout << "-1" << endl;
    else
    cout << r - l - 1 << endl;
    }
    return 0;
    }
  12. 最长公共字符串后缀

    给出若干个字符串,输出这些字符串的最长公共后缀。

    输入格式

    由若干组输入组成。

    每组输入的第一行是一个整数 N。

    N 为 0 时表示输入结束,否则后面会继续有 N 行输入,每行是一个字符串(字符串内不含空白符)。

    每个字符串的长度不超过 200。

    输出格式

    共一行,为 N 个字符串的最长公共后缀(可能为空)。

    输入样例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    3
    baba
    aba
    cba
    2
    aa
    cc
    2
    aa
    a
    0

    输出样例

    1
    2
    3
    ba

    a

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #include<iostream>
    using namespace std;

    const int N =200;
    int n;
    string str[N]; //定义个字符串数组

    int main(){

    while(cin >> n , n)
    {
    int len = 1000 ; //用来记录公共后缀的长度
    for(int i = 0 ; i < n ; i++ )
    {
    cin >> str[i] ; //输入n个字符串
    if(len > str[i].size()) len = str[i].size(); //将公共后缀长度更新为最短的字符串的长度!
    }

    while(len) //当len>0的时候,也就是有公共后缀的时候
    {
    bool is_success = true ; //标记是否匹配成功

    for(int i = 1 ; i < n ; i++ ) //让所有字符串与第一个字符串比较后缀
    {
    bool is_same = true ;//标记后缀是否相等

    for(int j = 1 ; j <= len ; j++) // 后缀长度从1到len,每个字符逐个比较
    {
    if(str[i][str[i].size() - j ] != str[0][str[0].size() - j])
    {
    is_same = false ;
    break ;
    }
    }

    if(!is_same) //后缀不等跳出
    {
    is_success = false ;
    break;
    }

    }
    if(is_success) break ; //匹配成功跳出while循环,输出长度为len的后缀
    len -- ; //匹配失败,长度减1


    }
    cout << str[0].substr(str[0].size() - len ) << endl ;
    }

    return 0;
    }