字符串的处理
字符串的处理
字符数组与相关函数;string 类与相关函数。
概念
字符串可存为以 '\0' 结尾的字符数组,或用 std::string 动态管理长度。字符数组常用 strlen、strcpy、strcmp(<cstring>)或手动下标遍历;string 支持 +、size()、substr、find 等。与 cspj.cpp.array 的区别:字符串强调文本语义与结束符/长度。与 cspj.math.ascii 的区别:ASCII 是字符编码表,这里是 C++ 里怎么存和处理字符序列。初赛阅读程序常考 char s[] 与 string 混用、下标与 '0'/0 区别;复赛常考按规则解析地址串、定长 01 串逐字符统计等。
CSP-J 常考
cspj-r2-2021编程第 3 题(网络连接):校验a.b.c.d:e地址串格式(段数、范围、前导零),再按规范串查表判断 Server/Client 连接结果。cspj-r1-2025第 9、33、36 题:单选与完善程序,考查string操作或字符数组处理。cspj-r1-2019第 16、19 题:阅读程序判断字符数组遍历、字符比较结果。cspj-r1-2021第 22–23 题:阅读程序,跟踪string或字符数组在函数中的变化。cspj-r2-2019编程第 1 题:读入固定长度字符串,逐字符统计'1'的个数。
#include <string>
using namespace std;
string s = "hello";
s += '!';
for (char c : s)
cout << c;
cout << endl << s.size() << endl;
易错点
- 字符
'0'的 ASCII 是 48,与整数 0 不同;s[i] - '0'才把数字字符转成数值。 - 字符数组若未手动加
'\0',用strlen或cout << char*可能越界读。 - 阅读程序里
string与 C 字符串函数混用时,问能否编译或行为是否定义,要看有没有.c_str()或类型是否匹配。
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
原卷作答说明:判断题正确填 √,错误填 ×
#include <cstdio>2#include <cstring>3using namespace std;4char st[100];5int main() {6 scanf("%s", st);7 int n = strlen(st);8 for (int i = 1; i <= n; ++i) {9 if (n % i == 0) {10 char c = st[i - 1];11 if (c >= 'a')12 st[i - 1] = c - 'a' + 'A';13 }14 }15 printf("%s", st);16 return 0;17}- 16判断1.5 分
输入的字符串只能由小写字母或大写字母组成。()
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
原卷作答说明:判断题正确填 √,错误填 ×
#include <cstdio>2#include <cstring>3using namespace std;4char st[100];5int main() {6 scanf("%s", st);7 int n = strlen(st);8 for (int i = 1; i <= n; ++i) {9 if (n % i == 0) {10 char c = st[i - 1];11 if (c >= 'a')12 st[i - 1] = c - 'a' + 'A';13 }14 }15 printf("%s", st);16 return 0;17}- 19判断1.5 分
若输入的字符串全部由大写字母组成,那么输出的字符串就跟输入的字符串一样。()
数字游戏
C++时间 1 s内存 256 MB 文件 IO:number.in → number.out
小 K 同学向小 P 同学发送了一个长度为 8 的 01 字符串来玩数字游戏,小 P 同学想要知道字符串中究竟有多少个 1。
注意:01 字符串为每一个字符是 0 或者 1 的字符串,如 101 为一个长度为 3 的 01 字符串。
输入格式
输入文件只有一行,一个长度为 8 的 01 字符串 s。
输出格式
输出文件只有一行,包含一个整数,即 01 字符串中字符 1 的个数。
样例
00010100
2
该 01 字符串中有 2 个字符 1。
11111111
8
该 01 字符串中有 8 个字符 1。
数据范围
对于 20% 的数据,保证输入的字符全部为 0。
对于 100% 的数据,输入只可能包含字符 0 和字符 1,字符串长度固定为 8。
部分分
- 100 分
全部 20 个测试点等分;20% 数据保证输入字符全为 0;100% 数据仅含字符 0 与 1,长度固定为 8。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
原卷作答说明:判断题正确填 √,错误填 ×
#include <cstdlib>2#include <iostream>3using namespace std;45char encoder[26] = {'C', 'S', 'P', 0};6char decoder[26];78string st;910int main() {11 int k = 0;12 for (int i = 0; i < 26; ++i)13 if (encoder[i] != 0) ++k;14 for (char x = 'A'; x <= 'Z'; ++x) {15 bool flag = true;16 for (int i = 0; i < 26; ++i)17 if (encoder[i] == x) {18 flag = false;19 break;20 }21 if (flag) {22 encoder[k] = x;23 ++k;24 }25 }26 for (int i = 0; i < 26; ++i)27 decoder[encoder[i] - 'A'] = i + 'A';28 cin >> st;29 for (int i = 0; i < st.length(); ++i)30 st[i] = decoder[st[i] - 'A'];31 cout << st;32 return 0;33}- 17判断1.5 分
若输入的字符串不是空串,则输入的字符串与输出的字符串一定不一样。()
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
原卷作答说明:判断题正确填 √,错误填 ×
#include <iostream>2#include <string>3using namespace std;45char base[64];6char table[256];78void init()9{10 for (int i = 0; i < 26; i++) base[i] = 'A' + i;11 for (int i = 0; i < 26; i++) base[26 + i] = 'a' + i;12 for (int i = 0; i < 10; i++) base[52 + i] = '0' + i;13 base[62] = '+', base[63] = '/';1415 for (int i = 0; i < 256; i++) table[i] = 0xff;16 for (int i = 0; i < 64; i++) table[base[i]] = i;17 table['='] = 0;18}1920string decode(string str)21{22 string ret;23 int i;24 for (i = 0; i < str.size(); i += 4) {25 ret += table[str[i]] << 2 | table[str[i + 1]] >> 4;26 if (str[i + 2] != '=')27 ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2;28 if (str[i + 3] != '=')29 ret += table[str[i + 2]] << 6 | table[str[i + 3]];30 }31 return ret;32}3334int main()35{36 init();37 cout << int(table[0]) << endl;3839 string str;40 cin >> str;41 cout << decode(str) << endl;42 return 0;43}- 22判断1.5 分
输出的第二行一定是由小写字母、大写字母、数字和 +、 /、= 构成的字符串。( )
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
原卷作答说明:判断题正确填 √,错误填 ×
#include <iostream>2#include <string>3using namespace std;45char base[64];6char table[256];78void init()9{10 for (int i = 0; i < 26; i++) base[i] = 'A' + i;11 for (int i = 0; i < 26; i++) base[26 + i] = 'a' + i;12 for (int i = 0; i < 10; i++) base[52 + i] = '0' + i;13 base[62] = '+', base[63] = '/';1415 for (int i = 0; i < 256; i++) table[i] = 0xff;16 for (int i = 0; i < 64; i++) table[base[i]] = i;17 table['='] = 0;18}1920string decode(string str)21{22 string ret;23 int i;24 for (i = 0; i < str.size(); i += 4) {25 ret += table[str[i]] << 2 | table[str[i + 1]] >> 4;26 if (str[i + 2] != '=')27 ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2;28 if (str[i + 3] != '=')29 ret += table[str[i + 2]] << 6 | table[str[i + 3]];30 }31 return ret;32}3334int main()35{36 init();37 cout << int(table[0]) << endl;3839 string str;40 cin >> str;41 cout << decode(str) << endl;42 return 0;43}- 23判断1.5 分
可能存在输入不同,但输出的第二行相同的情形。( )
网络连接
C++时间 1 s内存 512 MB 文件 IO:network.in → network.out
TCP/IP 协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。
在本问题中,计算机分为两大类:服务机(Server)和客户机(Client)。服务机负责建立连接,客户机负责加入连接。
需要进行网络连接的计算机共有 n 台,编号为 1∼n,这些机器将按编号递增的顺序,依次发起一条建立连接或加入连接的操作。
每台机器在尝试建立或加入连接时需要提供一个地址串。服务机提供的地址串表示它尝试建立连接的地址,客户机提供的地址串表示它尝试加入连接的地址。
一个符合规范的地址串应当具有以下特征:
- 必须形如
a.b.c.d:e的格式,其中 a,b,c,d,e 均为非负整数; - 0≤a,b,c,d≤255,0≤e≤65535;
- a,b,c,d,e 均不能含有多余的前导 0。
相应地,不符合规范的地址串可能具有以下特征:
- 不是形如
a.b.c.d:e格式的字符串,例如含有多于 3 个字符.或多于 1 个字符:等情况; - 整数 a,b,c,d,e 中某一个或多个超出上述范围;
- 整数 a,b,c,d,e 中某一个或多个含有多余的前导 0。
例如,地址串 192.168.0.255:80 是符合规范的,但 192.168.0.999:80、192.168.00.1:10、192.168.0.1:088、192:168:0:1.233 均是不符合规范的。
如果服务机或客户机在发起操作时提供的地址串不符合规范,这条操作将被直接忽略。
在本问题中,我们假定凡是符合上述规范的地址串均可参与正常的连接,你无需考虑每个地址串的实际意义。
由于网络阻塞等原因,不允许两台服务机使用相同的地址串,如果此类现象发生,后一台尝试建立连接的服务机将会无法成功建立连接;除此之外,凡是提供符合规范的地址串的服务机均可成功建立连接。
如果某台提供符合规范的地址的客户机在尝试加入连接时,与先前某台已经成功建立连接的服务机提供的地址串相同,这台客户机就可以成功加入连接,并称其连接到这台服务机;如果找不到这样的服务机,则认为这台客户机无法成功加入连接。
请注意,尽管不允许两台不同的服务机使用相同的地址串,但多台客户机使用同样的地址串,以及同一台服务机同时被多台客户机连接的情况是被允许的。
你的任务很简单:在给出每台计算机的类型以及地址串之后,判断这台计算机的连接情况。
输入格式
从文件 network.in 中读入数据。
第一行,一个正整数 n。
接下来 n 行,每行两个字符串 op,ad,分别表示计算机的类型和地址串,按照编号从小到大的顺序给出。
其中,op 保证为字符串 Server 或 Client 之一,ad 保证为长度不超过 25、仅由数字、字符 . 与字符 : 组成的非空字符串。
每行的两个字符串之间恰好用一个空格分隔,行末没有多余空格。
输出格式
输出到文件 network.out 中。
共 n 行,对于第 i 行的计算机,输出一行一个正整数或一个字符串,表示第 i 台计算机的连接情况。具体地:
若第 i 台计算机是服务机,则:
- 若其提供符合规范的地址串,并成功建立连接,则输出字符串
OK; - 若其提供符合规范的地址串,但由于已有相同地址的服务机存在而无法建立连接,则输出字符串
FAIL; - 若其提供的地址串不符合规范,则输出字符串
ERR。
若第 i 台计算机是客户机,则:
- 若其提供符合规范的地址串,并成功加入连接,则输出一个正整数,表示其连接到的服务机编号;
- 若其提供符合规范的地址串,但无法成功加入连接,则输出字符串
FAIL; - 若其提供的地址串不符合规范,则输出字符串
ERR。
样例
5 Server 192.168.1.1:8080 Server 192.168.1.1:8080 Client 192.168.1.1:8080 Client 192.168.1.1:80 Client 192.168.1.1:99999
OK FAIL 1 FAIL ERR
计算机 1 为服务机,提供符合规范的地址串 192.168.1.1:8080,成功建立连接;
计算机 2 为服务机,提供与计算机 1 相同的地址串,未能成功建立连接;
计算机 3 为客户机,提供符合规范的地址串 192.168.1.1:8080,成功加入连接,并连接到服务机 1;
计算机 4 为客户机,提供符合规范的地址串 192.168.1.1:80,找不到服务机与其连接;
计算机 5 为客户机,提供的地址串 192.168.1.1:99999 不符合规范。
10 Server 192.168.1.1:80 Client 192.168.1.1:80 Client 192.168.1.1:8080 Server 192.168.1.1:80 Server 192.168.1.1:8080 Server 192.168.1.999:0 Client 192.168.1.1:8080 Client 192.168.1.1:8080 Client 192.168.1.1:80 Client 192.168.1.999:0
OK 1 FAIL FAIL OK ERR ERR 5 1 ERR
数据范围
对于 100% 的数据,保证 1≤n≤1000。
| 测试点编号 | n≤ | 特殊性质 |
|---|---|---|
| 1 | 10 | 性质 1 2 3 |
| 2∼3 | 100 | 性质 1 2 3 |
| 4∼5 | 1000 | 性质 1 2 3 |
| 6∼8 | 1000 | 性质 1 2 |
| 9∼11 | 1000 | 性质 1 |
| 12∼13 | 1000 | 性质 2 |
| 14∼15 | 1000 | 性质 4 |
| 16∼17 | 1000 | 性质 5 |
| 18∼20 | 1000 | 无特殊性质 |
特殊性质 1:保证所有的地址串均符合规范;
特殊性质 2:保证对于任意两台不同的计算机,如果它们同为服务机或者同为客户机,则它们提供的地址串一定不同;
特殊性质 3:保证任意一台服务机的编号都小于所有的客户机;
特殊性质 4:保证所有的地址串均形如 a.b.c.d:e 的格式,其中 a,b,c,d,e 均为不超过 109 且不含有多余前导 0 的非负整数;
特殊性质 5:保证所有的地址串均形如 a.b.c.d:e 的格式,其中 a,b,c,d,e 均为只含有数字的非空字符串。
部分分
- 5 分
测试点 1:n≤10,特殊性质 1、2、3。
- 10 分
测试点 2∼3:n≤100,特殊性质 1、2、3。
- 10 分
测试点 4∼5:n≤1000,特殊性质 1、2、3。
- 15 分
测试点 6∼8:n≤1000,特殊性质 1、2。
- 15 分
测试点 9∼11:n≤1000,特殊性质 1。
- 10 分
测试点 12∼13:n≤1000,特殊性质 2。
- 10 分
测试点 14∼15:n≤1000,特殊性质 4。
- 10 分
测试点 16∼17:n≤1000,特殊性质 5。
- 15 分
测试点 18∼20:n≤1000,无特殊性质。
原文保真说明:来源改写 1 处(照原卷保留,未作修改)
来源题面被改写其它samples[1].input
原卷作
Client 192.168.1.1:8080,常规写法应为Client 192.168.1.1.8080洛谷 P7911 样例 2 第 7–8 行地址串误用 `.` 作分隔;扫描件 pg-11 为 `192.168.1.1:8080`,已按图像恢复。
已按官方原件恢复:现为原卷原文
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
#include<iostream>2#include<vector>3#include<algorithm>4using namespace std;56int f(string x,string y){7 int m=x.size();8 int n=y.size();9 vector<vector<int>>v(m+1,vector<int>(n+1,0));10 for(int i=1;i<=m;i++){11 for(int j=1;j<=n;j++){12 if(x[i-1]==y[j-1]){13 v[i][j]=v[i-1][j-1]+1;14 }else{15 v[i][j]=max(v[i-1][j],v[i][j-1]);16 }17 }18 }19 return v[m][n];20}21bool g(string x,string y){22 if(x.size() != y.size()){23 return false;24 }25 return f(x+x,y)==y.size();26}27int main(){28 string x,y;29 cin>>x>>y;30 cout<<g(x,y)<<endl;31 return 0;32}- 23判断1.5 分
当输入两个完全相同的字符串时,
g函数的返回值总是true。()
下列关于 C++ string 类的说法,正确的是?
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
(1)(字符串解码)“行程长度编码”(Run-Length Encoding)是一种无损压缩算法,常用于压缩重复字符较多的数据,以减少存储空间。假设原始字符串不包含数字字符。压缩规则如下:i) 如果原始字符串中一个字符连续出现 N 次(N≥2),在压缩字符串中它被表示为“字符 + 数字 N”。例如,编码 A12 代表 12 个连续的字符 A。ii) 如果原始字符串中一个字符只出现 1 次,在压缩字符串中它就表示为该字符本身。例如,编码 B 代表 1 个字符 B。
以下程序实现读取压缩字符串并输出其原始的、解压后的形式。试补全程序。
#include <cctype>2#include <iostream>3#include <string>4using namespace std;56int main() {7 string z;8 cin >> z;9 string s = "";1011 for (int i = 0; i < z.length(); ) {12 char ch = z[i];1314 if (__①__ && isdigit(z[i + 1])) {15 i++;16 int count = 0;17 while (i < z.length() && isdigit(z[i])) {18 count = __②__;19 i++;20 }21 for (int j = 0; j < __③__; ++j) {22 s += ch;23 }24 } else {25 s += __④__;26 __⑤__;27 }28 }2930 cout << s << endl;31 return 0;32}- 33(①)单选空位 ①3 分
①处应填( )
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
(1)(字符串解码)“行程长度编码”(Run-Length Encoding)是一种无损压缩算法,常用于压缩重复字符较多的数据,以减少存储空间。假设原始字符串不包含数字字符。压缩规则如下:i) 如果原始字符串中一个字符连续出现 N 次(N≥2),在压缩字符串中它被表示为“字符 + 数字 N”。例如,编码 A12 代表 12 个连续的字符 A。ii) 如果原始字符串中一个字符只出现 1 次,在压缩字符串中它就表示为该字符本身。例如,编码 B 代表 1 个字符 B。
以下程序实现读取压缩字符串并输出其原始的、解压后的形式。试补全程序。
#include <cctype>2#include <iostream>3#include <string>4using namespace std;56int main() {7 string z;8 cin >> z;9 string s = "";1011 for (int i = 0; i < z.length(); ) {12 char ch = z[i];1314 if (__①__ && isdigit(z[i + 1])) {15 i++;16 int count = 0;17 while (i < z.length() && isdigit(z[i])) {18 count = __②__;19 i++;20 }21 for (int j = 0; j < __③__; ++j) {22 s += ch;23 }24 } else {25 s += __④__;26 __⑤__;27 }28 }2930 cout << s << endl;31 return 0;32}- 36(④)单选空位 ④3 分
④处应填( )