我必须在c中用转义字符(Q)做一个rle算法。
例如,如果我有一个输入,如:AAAAAAABBBCCCDDDDDDEFG
输出必须是:QA7BBBCCCQD6FFG
这就是我做的代码:
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *source = fopen("Test.txt", "r");
FILE *destination = fopen("Dest.txt", "w");
char carCorrente; //in english: currentChar
char carSucc; // in english: nextChar
int count = 1;
while(fread(&carCorrente, sizeof(char),1, source) != 0) {
if (fread(&carCorrente, sizeof(char),1, source) == 0){
if(count<=3){
for(int i=0;i<count;i++){
fprintf(destination,"%c",carCorrente);
}
}
else {
fwrite("Q",sizeof(char),1,destination);
fprintf(destination,"%c",carCorrente);
fprintf(destination,"%d",count);
}
break;
}
else fseek(source,-1*sizeof(char), SEEK_CUR);
while (fread(&carSucc, sizeof(char), 1, source) != 0) {
if (carCorrente == carSucc) {
count++;
}
else {
if(count<=3){
for(int i=0;i<count;i++){
fprintf(destination,"%c",carCorrente);
}
}
else {
fwrite("Q",sizeof(char),1,destination);
fprintf(destination,"%c",carCorrente);
fprintf(destination,"%d",count);
}
count = 1;
goto OUT;
}
}
OUT:fseek(source,-1*sizeof(char), SEEK_CUR); //exit 2° while
}
}问题是当我有这样的输入时:ABBBCCCDDDDDEFGD
在本例中,输出是:QB4CCCQD5FFDD
我不知道为什么:
发布于 2013-11-24 16:32:14
没有必要像您所做的那样使用rewind来倒带,这里有一个代码,它是通过使用简单的逆流序列字符而编写的,而不是使用它。
C实现:
#include<stdio.h>
#include<stdlib.h>
void main()
{
FILE *source = fopen("Test.txt", "r");
FILE *destination = fopen("Dest.txt", "w");
char currentChar;
char seqChar;
int count = 0;
while(1) {
int flag = (fread(¤tChar, sizeof(char),1, source) == 0);
if(flag||seqChar!=currentChar) {
if(count>3) {
char ch = 'Q';
int k = count;
char str[100];
int digits = sprintf(str,"%d",count);
fwrite(&ch,sizeof(ch),1,destination);
fwrite(&seqChar,sizeof(ch),1,destination);
fwrite(&str,sizeof(char)*digits,1,destination);
}
else {
for(int i=0;i<count;i++)
fwrite(&seqChar,sizeof(char),1,destination);
}
seqChar = currentChar;
count =1;
}
else count++;
if(flag)
break;
}
fclose(source);
fclose(destination);
}发布于 2013-11-24 16:30:51
您的代码有各种问题。首先,我不确定你是否应该从文件中直接阅读。在您的示例中,最好先使用fgets将源字符串读入文本缓冲区,然后进行编码。(我认为在你的作业中,你只应该对字母进行编码。如果source是一个常规文本文件,它将至少有一个换行符。)
但是,让我们假设您需要直接从磁盘读取:您不需要倒退。您已经有了当前和下一个字符的两个变量。从磁盘读取下一个字符一次。在进一步阅读“下一个字符”之前,分配:
int carSucc, carCorr; // should be ints for getc
carSucc = getc(source); // read next character once before loop
while (carSucc != EOF) { // test for end of input stream
int carCorr = next; // this turn's char is last turn's "next"
carSucc = getc(source);
// ... encode ...
}前进和后退使循环变得复杂。此外,如果第二次读取的字符为零,即已到达文件的末尾,会发生什么情况?然后回溯一次,然后进入第二个循环。这看起来好像不是故意的。
试着往前走,并使用上面的循环作为编码的基础。
发布于 2013-11-24 18:16:57
我认为您的方法的主要问题是,在多个不同的地方,您读取输入并在输入中查找,这太复杂了。RLE可以一次完成,不应该有必要去寻找以前的字符。解决这一问题的一种方法是将逻辑转换为查看前面的字符以及它们被重复了多少次,而不是试图展望未来的字符。例如:
int repeatCount = 0;
int previousChar = EOF;
int currentChar; // type changed to 'int' for fgetc input
while ((currentChar = fgetc(source)) != EOF) {
if (currentChar != previousChar) {
// print out the previous run of repeated characters
outputRLE(previousChar, repeatCount, destination);
// start a new run with the current character
previousChar = currentChar;
repeatCount = 1;
} else {
// same character repeated
++repeatCount;
}
}
// output the final run of characters at end of input
outputRLE(previousChar, repeatCount, destination);然后,您可以实现outputRLE来完成输出,以打印出字符c重复的count次数的运行(注意,count可以是0);下面是函数声明:
void outputRLE(const int c, const int count, FILE * const destination)虽然通过将fwrite和两个fprintf组合成一个fprintf,您可以使用与当前代码相同的方式进行简化。另外,如果转义字符'Q'出现在输入中,或者运行10个或更多的重复字符,您可能想一想会发生什么。在outputRLE中处理这些案件。
代码中一个不相关的问题是,返回类型的main应该是int,而不是void。
https://stackoverflow.com/questions/20176338
复制相似问题