1078 字符串压缩与解压 (20 分)

文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示。例如 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

这道题应该不算难题,但自己出了很多问题

选择大于努力,可以直接拉到最后面看柳神代码

问题代码

#include<iostream>
using namespace std;
int main(){
	string s;
	cin>>s;
	if(s[0]=='C'){
		getchar();
		string s;
		getline(cin,s); 
		int count=1;
		for(int i=0;i<s.length();i++){
			if(s[i]==s[i+1]){
				count++;
			}else{
				if(count>1){
					cout<<count<<s[i];
				}else{
					cout<<s[i];
				}
				count=1;
			} 
		}
	} 
	else {
		getchar();
		char c;
		while(1){
			int i;
			if(scanf("%d",&i)){
				c=getchar();
                if(c==EOF){
					return 0;
				} 
				for(int a=0;a<i;a++){
					cout<<c;
				}
                
			}
			else{
				c=getchar();
				if(c==EOF){
					return 0;
				}
				cout<<c;
                
			}
		}
	}
	return 0;
}

1. 先是超时问题,因为while(getchar())是读不完的,会卡在这里,所以需要判断读进来的char是不是 回车"\n",oj上是文件输入,可能没回车 需要判断文件结尾EOF 

if(c==EOF){return 0;}

2.解压的时候我想的是先读数字,读到就读到,读不到再读字母,先scanf一个?%d,就冲掉了输入流里面的回车,所以不能这样读,我的想法是先读一下,读到空格输出?不是 空格再还回去?(太麻烦了)

3.后面还是过了,用了奇葩函数ungetc()

还是最好别这么用

函数扩展ungetc()

函数原型

int ungetc( int character, FILE * stream );

函数功能

将一个字符返回到流中。与getchar()作用相反。

头文件

#include <stdio.h>

参数

character
要返回到流中的字符。

stream
字符返回的目标流。

返回值

成功则返回返回到流中的字符;

否则返回 EOF。

程序实例

参加上面代码,对getchar()取出数字情况的处理。

修补后通过的代码

#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
	string s;
	cin>>s;
	if(s[0]=='C'){
		getchar();
		string s;
		getline(cin,s); 
		int count=1;
		for(int i=0;i<s.length();i++){
			if(s[i]==s[i+1]){
				count++;
			}else{
				if(count>1){
					cout<<count<<s[i];
				}else{
					cout<<s[i];
				}
				count=1;
			} 
		}
	} 
	else {
		getchar();
		char c;
		while(1){
			int i;
			c=getchar();
			
			if(c!=' '){
				ungetc(c, stdin);
			}else{
				cout<<c;
			}
			if(scanf("%d",&i)){
				c=getchar();
                if(c==EOF){
					return 0;
				} 
				for(int a=0;a<i;a++){
					cout<<c;
				}
                
			}
			else{
				c=getchar();
				if(c==EOF){
					return 0;
				}
				cout<<c;
                
			}
		}
	}
	return 0;
}

 还是看柳婼大神的代码

学习她的比较好

1.先把所有信息读进字符串 getline ,再在字符串里面操作,这样不会出现向我这样又超时,又吞掉空格等等坑爹的BUG。

2.说明选择大于努力。选对了这个方法,很多坑 是可以直接跳过去的。

#include <iostream>
using namespace std;
int main() {
    char t;
    cin >> t;
    getchar();
    string s, num;
    getline(cin, s);
    int cnt = 1;
    if (t == 'D') {
        for (int i = 0; i < s.length(); i++) {
            if (s[i] >= '0' && s[i] <= '9') {
                num += s[i];
            } else {
                if (num.length() > 0) cnt = stoi(num);
                while(cnt--) cout << s[i];
                cnt = 1;
                num = "";
            }
        }
    } else if (s.length() != 0) {
        char pre = s[0];
        for (int i = 1; i < s.length(); i++) {
            if (s[i] == pre) {
                cnt++;
            } else {
                if (cnt >= 2) cout << cnt;
                cout << pre;
                cnt = 1;
                pre = s[i];
            }
        }
        if (cnt >= 2) cout << cnt;
        cout << pre;
    }
    return 0;
}