RLE エンコーディング…何が問題なのでしょうか?
質問
文字専用のRLE(Run-Length Encoder)プログラムを作成しようとしています。ネット上のメモでその仕組みを読みました。そしてコードを修正してみました!コードの手順は正しいと思うのに、コードが機能しません。実行すると、奇妙な「Z」の文字が表示されます。本当に何が間違っているのかわかりません。アドバイスをいただけますか?
#include <stdio.h>
int main()
{
int count;
unsigned char currChar,prevChar=EOF;
while(currChar=getchar() != EOF)
{
if ( ( (currChar='A')&&(currChar='Z') ) || ( (currChar='a')&&(currChar='z') ) )
{
printf("%c",currChar);
if(prevChar==currChar)
{
count=0;
currChar=getchar();
while(currChar!=EOF)
{
if (currChar==prevChar)
count++;
else
{
if(count<=9)
printf("%d%c",count,prevChar);
else
{
printf("%d%c",reverse(count),prevChar);
}
prevChar=currChar;
break;
}
}
}
else
prevChar=currChar;
if(currChar==EOF)
{ printf("%d",count);
break;
}
}
else
{
printf("Error Message:Only characters are accepted! Please try again! False input!");
break;
}
}
return 0;
}
int reverse(int x)
{
int p,y,r=0;
x=(x<0)?-x:x;
while (x>0)
{
y=x%10;
p=x/10;
r=10*r+y;
x=p;
}
printf("%d",r);
return 1;
}
例えば私は入力を行いました:
AAAAAAAAAAAAAAAAAAAAFFFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEEEGGGGGGGGGGGGGGGGVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSRRRRRRRRRRHD RRRRRRRRRRRRRRRRRRRRHHHHHHHHHHHHHHHHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMMMMMMMMMMMMMMMMMMMMMMMMMS TTTTTTTTTTTHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
そして私は出力を得ました:
Z0AZZ0AZZ0FZZ0FZZ0FZZ0FZZ0FZZ0FZZ0FZZ0FZZ0FZZ0EZZ0EZZ0EZZ0EZZ0EZZ0EZZ0EZZ0EZZ0GZZ0GZZ0GZZ0GZZ0GZZ0GZZ0VZZ0VZZ0VZZ0VZZ0VZZ0VZZ0VZZ0VZZ0VZZ0VZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0SZZ0RZZ0RZZ0RZZ0RZZ0 ZZ0RZZ0RZZ0RZZ0RZZ0RZZ0RZZ0HZZ0HZZ0HZZ0HZZ0HZZ0HZZ0AZZ0AZZ0AZZ0AZZ0AZZ0AZZ0AZZ0AZZ0AZZ0AZZ0
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :(
解決
以前のコメントを回答に変換しています...
他の回答で指摘されているように、「if」条件での代入には問題があります。
unsigned char に値を割り当ててから EOF の検出を期待することはできません。名前は忘れてください。getc() と getchar() (および fgetc()) は文字ではなく整数を返すことを思い出してください。可能なすべての有効な文字値と EOF を返す必要があるため、整数を返す必要があります。
あなたのテストは
if(currChar=='EOF')
奇妙だ。複数文字の定数を使用していますが、これはせいぜい実装定義であり、getchar() によって返される EOF (引用符なし) と等しくありません。さらに、currChar の型が間違っています。reverse() は常に 0 を返します。それはあなたが本当に望んでいたものですか?
この線 '
while(currChar=getchar() != EOF)
' 期待どおりに動作するには、追加のかっこが必要です。'while((currChar = getchar()) != EOF)
'。現時点では、currChar には 0 (NUL、'\0') または 1 (Control-A) が割り当てられます。内部の while ループは文字をまったく読み取らないため、プログラムが混乱状態に陥ります。代入する必要があります。
while((currChar = getchar()) != EOF)
』表記も。次に、期待される出力が実際に何であるかを理解する必要があります。なぜなら、それはあまり意味がないと思うからです - 特に野良 'printf("%c",currChar);
' メイン テスト後のメッセージは疑わしいです。おそらく、これは誤って残したデバッグ プリントかもしれません。また、改行などをコードでどのように処理するかを検討する必要があります。それは、出力のあいまいさの問題 (RLE でエンコードされたデータと数値を含むデータの違いをどうやって区別するか) に取り組む前に検討する必要があります。アルゴリズムには心配すべきことがたくさんあります。ほとんどが正しくありません、ごめんなさい。
以下に、半分動作するコードをいくつか示します。数字の処理を明示的に拒否します (ただし、それだけです)。
/* RLE - Run Length Encoding */
/* SO 2485285 */
/*
** Input: stream of data except for digits 0-9
** Output: stream of data with adjacent sets of 3 or more of the same
** character represented by 3Z (for ZZZ), etc.
*/
#include <stdio.h>
#include <ctype.h>
static void print_rle(int count, int repchar)
{
if (count > 2)
printf("%d%c", count, repchar);
else if (count == 2)
printf("%c%c", repchar, repchar);
else if (repchar != EOF)
printf("%c", repchar);
}
int main()
{
int count = 1;
int currChar;
int prevChar = EOF;
while ((currChar = getchar()) != EOF)
{
if (isdigit(currChar))
fprintf(stderr, "Bogus character %c read - ignored\n", currChar);
else if (currChar == prevChar)
count++;
else
{
print_rle(count, prevChar);
count = 1;
prevChar = currChar;
}
}
print_rle(count, prevChar);
return 0;
}
これは、独自のソース コードで実行したときの出力です (タブではなくスペースを使用していることに注意してください)。「偽の文字」メッセージは、標準出力ではなく標準エラー出力に出力されます。
/* RLE - Run Length Encoding */
Bogus character 2 read - ignored
Bogus character 4 read - ignored
Bogus character 8 read - ignored
Bogus character 5 read - ignored
Bogus character 2 read - ignored
Bogus character 8 read - ignored
Bogus character 5 read - ignored
/* SO */
/*
Bogus character 0 read - ignored
Bogus character 9 read - ignored
** Input: stream of data except for digits -
Bogus character 3 read - ignored
** Output: stream of data with adjacent sets of or more of the same
Bogus character 3 read - ignored
**9 character represented by Z (for 3Z), etc.
*/
#include <stdio.h>
#include <ctype.h>
static void print_rle(int count, int repchar)
{
Bogus character 2 read - ignored
4 if (count > )
8 printf("%d%c", count, repchar);
Bogus character 2 read - ignored
4 else if (count == )
8 printf("%c%c", repchar, repchar);
4 else if (repchar != EOF)
8 printf("%c", repchar);
}
int main()
{
Bogus character 1 read - ignored
4 int count = ;
4 int currChar;
4 int prevChar = EOF;
4 while ((currChar = getchar()) != EOF)
4 {
8 if (isdigit(currChar))
12 fprintf(stderr, "Bogus character %c read - ignored\n", currChar);
8 else if (currChar == prevChar)
12 count++;
8 else
8 {
12 print_rle(count, prevChar);
Bogus character 1 read - ignored
12 count = ;
12 prevChar = currChar;
8 }
4 }
4 print_rle(count, prevChar);
Bogus character 0 read - ignored
4 return ;
}
他のヒント
この行を見ます:
if ( ( (currChar='A')&&(currChar='Z') ) || ( (currChar='a')&&(currChar='z') ) )
あなたがcurrChar
に「Z」を割り当てるされ、次にcurrChar
する「A」を割り当てているので...
あなたはそれの代わりに割り当てを比較するために=
に==
を変更する必要があります。
また、あなたは(currChar='A')&&(currChar='Z')
によって何を意味するのですか? currChar
が同時に「A」と「Z」にすることはできません、私はあなたがここに置くことを意味することは、特定の区間に含まれているcurrChar
のチェックだったと思います。だから、それはおそらくする必要があります:
(currChar>='A')&&(currChar<='Z')
同じことがあなたの状態の第二の部分に適用されます。