CSP-J 2025 入门级 第一轮(初赛) 完善程序(1)
【题目】
(字符串解码)"行程长度编码"(Run-Length Encoding)是一种无损压缩算法,常用于压缩重复字符较多的数据,以减少存储空间。假设原始字符串不包含数字字符。压缩规则如下:i)如果原始字符串中一个字符连续出现 NNN 次(N≥2N \ge 2N≥2),在压缩字符串中它被表示为 "字符+数字 NNN"。例如,编码 "A12A12A12" 代表 121212 个连续的字符 AAA。ii)如果原始字符串中一个字符只出现 111 次,在压缩字符串中它就表示为该字符本身。例如,编码 "BBB" 代表 111 个字符 BBB。
以下程序实现读取压缩字符串并输出其原始的、解压后的形式。试补全程序。
cpp
01 #include <cctype>
02 #include <iostream>
03 #include <string>
04 using namespace std;
05
06 int main() {
07 string z;
08 cin >> z;
09 string s = "";
10
11 for (int i = 0; i < z.length(); ) {
12 char ch = z[i];
13
14 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 } else {
24 s += ____④____;
25 ____⑤____;
26 }
27 }
28
29 cout << s << endl;
30 return 0;
31 }
-
① 处应填( )。
A. i<z.length()i < z.length()i<z.length()
B. i−1≥0i - 1 \ge 0i−1≥0
C. i+1<z.length()i + 1 < z.length()i+1<z.length()
D. isdigit(z[i])isdigit(z[i])isdigit(z[i])
-
② 处应填( )。
A. count+(z[i]−′0′)count + (z[i] - '0')count+(z[i]−′0′)
B. count×10+(z[i]−′0′)count \times 10 + (z[i] - '0')count×10+(z[i]−′0′)
C. z[i]−′0′z[i] - '0'z[i]−′0′
D. count+1count + 1count+1
-
③ 处应填( )。
A. count−1count - 1count−1
B. countcountcount
C. 101010
D. z[i]−′0′z[i] - '0'z[i]−′0′
-
④ 处应填( )。
A. z[i+1]z[i+1]z[i+1]
B. chchch
C. z.back()z.back()z.back()
D. (char)z[i]+1(char)z[i] + 1(char)z[i]+1
-
⑤ 处应填( )。
A. i−−i--i−−
B. i=i+2i = i + 2i=i+2
C. i++i++i++
D. // 不执行任何操作
【题目难度】:D
【题目考点】
1. 字符串
- string类操作
【题目解析】
完善程序题,首先根据题面自行想应该使用什么算法解决。本题给定的是压缩后的字符串,需要还原出原字符串。
解题思路为:遍历压缩后的字符串,当访问到一个字母字符ccc时,将ccc后面的几个数字字符构造成一个整数nnn,nnn为ccc在原字符串中ccc出现的次数,而后在原字符串中末尾添加nnn个ccc。如果ccc后没有数字字符,则在原字符中末尾添加1个ccc。
cpp
06 int main() {
07 string z;
08 cin >> z;
09 string s = "";
10
11 for (int i = 0; i < z.length(); ) {
12 char ch = z[i];
首先声明并输入了字符串zzz,zzz是原字符串,根据接下来的代码可知字符串sss是结果字符串,初值为空字符串(其实不写="",sss的初值也是空字符串)。
而后遍历zzz字符串,chchch是当前访问到的字符。
cpp
14 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; }
当前访问的字符串的下标为iii,由于原字符串中是没有数字字符的,此时默认访问到的z[i]z[i]z[i]也就是chchch是字母字符,要看下一个字符z[i+1]z[i+1]z[i+1]是不是数字字符(isdigit(c)可以判断一个字符是否是数字字符)。既然要访问i+1i+1i+1位置,那么i+1i+1i+1位置必须在字符串zzz的下标范围之内,zzz的下标范围为[0,z.length()−1][0,z.length()-1][0,z.length()−1],因此一定有i+1≤z.length()−1i+1\le z.length()-1i+1≤z.length()−1,也就是i+1<z.length()i+1<z.length()i+1<z.length()。第(1)空填i+1<z.length()i+1<z.length()i+1<z.length(),选C 。
而后15行i++,取到下一个位置。此时z[i]z[i]z[i]一定是数字字符。而后向后遍历,只要访问到数字字符,就将数字字符整合为一个整数,直到访问到字符串的末尾,或遇到非数字字符。countcountcount为字符chchch后的数字字符构成的数值,初值为0,每遇到一个字符z[i]z[i]z[i],则先将z[i]z[i]z[i]转为数值z[i]−′0′z[i]-'0'z[i]−′0′,将countcountcount乘以10,再加上z[i]−′0′z[i]-'0'z[i]−′0′,就可以在原数值countcountcount末尾增加一位数。这是从高位到低位的数位组合写法。因此第(2)空填count∗10+z[i]−′0′count*10+z[i]-'0'count∗10+z[i]−′0′,选B
压缩后的字符串中字符chchch后的整数为countcountcount,那么在原字符串中就有countcountcount个字符,循环countcountcount次,21行jjj从0循环到count−1count-1count−1,循环进行的条件为j<countj<countj<count,第(3)空选B ,每次循环在字符串sss末尾添加(连接)一个字符chchch。
cpp
23 } else {
24 s += ____④____;
25 ____⑤____;
26 }
第14行的判断条件为:i+1i+1i+1在字符串下标范围之内而且z[i+1]z[i+1]z[i+1]还是数字字符。如果该条件不满足,那么可能是iii位置已经是zzz字符串的最后一个字符,或者chchch的下一个字符z[i+1]z[i+1]z[i+1]还是字母字符,这说明原字符串中字符chchch只出现了一次,在字符串sss末尾添加一个字符chchch即可。string类的+=操作可以在字符串末尾添加一个字符或字符串,因此第(4)空填chchch ,选B。
由于第11行for循环是没有写增量表达式(for循环这一行中的第三个表达式),在第14行条件为真时的分支中已经包含了让下标iii增加的操作。在第14行条件为假时,每次循环也要让iii增加1,因此第(5)空填i++i++i++,选C。
【题目答案】
- C
- B
- B
- B
- C