題目
文本壓縮有很多種方法,這里我們只考慮最簡單的一種:把由相同字符組成的一個連續(xù)的片段用這個字符和片段中含有這個字符的個數(shù)來表示。例如
ccccc
就用5c
來表示劫谅。如果字符沒有重復(fù)绰咽,就原樣輸出。例如aba
壓縮后仍然是aba
拂玻。
解壓方法就是反過來酸些,把形如
5c
這樣的表示恢復(fù)為ccccc
。
本題需要你根據(jù)壓縮或解壓的要求檐蚜,對給定字符串進(jìn)行處理魄懂。這里我們簡單地假設(shè)原始字符串是完全由英文字母和空格組成的非空字符串。
輸入格式:
輸入第一行給出一個字符闯第,如果是
C
就表示下面的字符串需要被壓縮市栗;如果是D
就表示下面的字符串需要被解壓。第二行給出需要被壓縮或解壓的不超過 1000 個字符的字符串,以回車結(jié)尾填帽。題目保證字符重復(fù)個數(shù)在整型范圍內(nèi)蛛淋,且輸出文件不超過 1MB。
輸出格式:
根據(jù)要求壓縮或解壓字符串篡腌,并在一行中輸出結(jié)果褐荷。
輸入樣例 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
通過代碼(極致壓行版)
#include <iostream>
#include <ctype.h>
using namespace std;
void Cprint(int& count, char a) {//注意count是引用變量
if (count != 1) cout << count;
cout << a;
count = 0;
}
int main () {
string str, c;
int i = 0, count = 1;//i是解碼的循環(huán)變量,控制下標(biāo)嘹悼。count是壓縮過程中記錄重復(fù)字符出現(xiàn)次數(shù)的
getline(cin, c); getline(cin, str);//輸入
if (c == "C") {
for (int j = 1; j < str.length(); j++, count++)//每次循環(huán)count++
if (str[j - 1] != str[j]) Cprint(count, str[j - 1]);//如果遇到一個字符和前一個不一樣叛甫,輸出,讓count歸零
Cprint(count, str[str.length() - 1]);//輸出最末尾的一個或一串
} else if (c == "D") {
if (!isdigit(str[i])) cout << str[i++];//第一個不是數(shù)字杨伙,直接輸出其监,i++訪問下一個字符
for (int n = 0; i < str.length(); n = 0, i++) {//n為每個字符前的數(shù)字
for (; i < str.length() && isdigit(str[i]); n *= 10, n += (str[i++] - '0'));//如果是數(shù)字,就把數(shù)字字符轉(zhuǎn)換成數(shù)缀台,這里不是雙層for循環(huán)嵌套棠赛,這個for循環(huán)后有一個分號
for (int j = 0; j < (n == 0 ? 1 : n); j++) cout << str[i];//循環(huán)輸出字符,如果沒有遇到數(shù)字膛腐,n為0睛约,就輸出一次
}
}
return 0;
}
通過代碼
#include <iostream>
#include <algorithm>
#include <ctype.h>
using namespace std;
struct out { char c; int n; };
void C () {
string str;
getline(cin, str);
int n = str.length();
out data[n] = {0};
char last = -1;
int count = -1;
for (int i = 0; i < n; i++) {
if (str[i] != last)
data[++count].c = str[i];
data[count].n++;
last = str[i];
}
for (int i = 0; i < count + 1; i++) {
if (data[i].n != 1)
cout << data[i].n;
cout << data[i].c;
}
}
void D () {
string str;
getline(cin, str);
int i = 0;
if (!isdigit(str[i]))
cout << str[i++];
while (i < str.length()) {
int n = 0;
while (i < str.length() && isdigit(str[i])) {
n *= 10;
n += str[i++] - '0';
}
for (int j = 0; j < n; j++)
cout << str[i];
i++;
while ( i < str.length() && !isdigit(str[i]))
cout << str[i++];
}
}
int main () {
char c;
scanf("%c%*c", &c);
if (c == 'C') C();
else D();
return 0;
}
思路與注意
coding(壓縮)一個函數(shù),decoding(解壓)一個函數(shù)分別處理
兩個函數(shù)統(tǒng)一使用getline哲身,main函數(shù)里面要吃掉第一行的換行符
-
對于coding過程
定義一個結(jié)構(gòu)體數(shù)組辩涝,儲存字符與個數(shù)。數(shù)組長度為輸入string的長度(如果輸入的string不能壓縮勘天,正好夠用)
遍歷一遍string怔揩,如果字符和前一個字符一樣,那么當(dāng)前結(jié)構(gòu)體(變量)的字符個數(shù)++脯丝,一旦改變商膊,存到下一個結(jié)構(gòu)體中。
輸出結(jié)構(gòu)體宠进,先輸出個數(shù)(大于1才輸出)晕拆,再輸出這個字符
-
對于decoding過程
先判斷第一個字符,如果是字母直接輸出這個字母材蹬,然后字符串的“指針”向后移实幕。
進(jìn)入循環(huán),循環(huán)的操作為堤器,得到數(shù)字昆庇,輸出數(shù)字后的字母,然后輸出后面的單個字母闸溃,直到遇到下一個數(shù)字整吆,進(jìn)入下一次循環(huán)拱撵,或者遇到字符串結(jié)束,那就結(jié)束掂为。
注意不要用isalpha()函數(shù)(考慮空格的存在)
反思與評價
- 嗯