文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示。例如 ccccc
就用 5c
来表示。如果字符没有重复,就原样输出。例如 aba
压缩后仍然是 aba
。
解压方法就是反过来,把形如 5c
这样的表示恢复为 ccccc
。
本题需要你根据压缩或解压的要求,对给定字符串进行处理。这里我们简单地假设原始字符串是完全由英文字母和空格组成的非空字符串。
输入格式:
输入第一行给出一个字符,如果是 C
就表示下面的字符串需要被压缩;如果是 D
就表示下面的字符串需要被解压。第二行给出需要被压缩或解压的不超过 1000 个字符的字符串,以回车结尾。题目保证字符重复个数在整型范围内,且输出文件不超过 1MB。
输出格式:
根据要求压缩或解压字符串,并在一行中输出结果。
输入样例 1:
C
TTTTThhiiiis isssss a tesssst CAaaa as
输出样例 1:
5T2h4is i5s a3 te4st CA3a as
输入样例 2:
D
5T2h4is i5s a3 te4st CA3a as10Z
输出样例 2:
TTTTThhiiiis isssss a tesssst CAaaa asZZZZZZZZZZ
解题思路:
c
o
m
p
r
e
s
s
(
)
compress()
compress() 函数 :
遍历字符串
s
s
s,使用
w
h
i
l
e
while
while 循环统计连续出现的字符,更新字符计数器
c
n
t
cnt
cnt 及 右移
i
i
i,当出现连续字符(
c
n
t
>
1
cnt > 1
cnt>1)时输出
c
n
t
cnt
cnt,否则仅输出当前字符
s
[
i
]
s[i]
s[i]。
d
e
c
o
m
p
r
e
s
s
(
)
decompress()
decompress() 函数:
遍历字符串
s
s
s,判断当前字符是否为数字,若是数字使用
w
h
i
l
e
while
while 循环计算完整的数字,同时更新计数器
c
n
t
cnt
cnt 并右移
i
i
i,输出
c
n
t
cnt
cnt 个字母
s
[
i
+
1
]
s[i+1]
s[i+1],输出完毕右移
i
i
i 一位;若当前字符不是数字,输出当前字符即可。
N o t e Note Note: 使用 g e t c h a r ( ) getchar() getchar()、 c i n cin cin 这类读入了一个字母,敲回车产生的换行符仍然滞留在输入流了,接着就被 g e t l i n e ( c i n , s ) getline(cin,s) getline(cin,s) 给读进去了,此时的 s=“\n”,所以实际上 s s s 只是读入了一个换行符 \n。使用 g e t c h a r ( ) getchar() getchar() 读入结束的回车后,结束符不放入缓存区,会将读入的\n直接去除,此时缓冲区为空,再用 g e t l i n e ( ) getline() getline() 进行读入,此时不会发生问题。
答案代码:
#include <iostream>
#include <string>
using namespace std;
void compress(string s) {
for (int i = 0; i < s.size(); i++) { // 遍历字符串
int cnt = 1;
while (s[i] == s[i+1]) { // 相邻字符相等
cnt++; i++;
}
if (cnt > 1) cout << cnt;
cout << s[i];
}
cout << endl;
}
void decompress(string s) {
int i;
for (i = 0; i < s.size(); i++) { // 遍历字符串
int cnt = 1;
if (isdigit(s[i])) {
cnt = s[i] - '0';
while (isdigit(s[i+1])) { // 解压字符的个数
cnt = cnt*10 + s[i+1] - '0';
i++;
}
for (int j = 0; j < cnt; j++)
cout << s[i+1];
i++;
}
else cout << s[i];
}
cout << endl;
}
int main() {
char c = ' ';
cin >> c;
getchar();
string s;
getline(cin,s);
if (c == 'C') compress(s);
else if (c == 'D') decompress(s);
return 0;
}