- 締切済み
ランレングス符号化を用いた符号化プログラムについて教えてください
入力用ファイルの情報を読み込み,このファイルの情報をランレングス符号化を用いて符号化し,結果を出力用ファイル名に出力するCプログラムを作成しようとしているのですが正確に符号化することができません(情報の個数が正しくカウントできない)どうすればよいのかわからないので教えていただけないでしょうか。 #include <stdio.h> main(void){ FILE *fi; FILE *fo; int ccs; unsigned char c=1; char a,b,d; fi=fopen("files99.txt","rb"); fo=fopen("files100.dat","wb"); fread(&a,sizeof(a),1,fi); ccs=fread(&d,sizeof(d),1,fi); while(ccs>0){ fread(&b,sizeof(b),1,fi); if(a==b){ c=c+1; } else { fwrite(&a,sizeof(a),1,fo); fwrite(&c,sizeof(c),1,fo); a=b; c=1; } ccs=fread(&d,sizeof(d),1,fi); } これでは入力用ファイルをfiles99.txtとし 出力用ファイルをfiles100.datとしています。 どこを改善すればよいのか手持ちの資料や学校の図書館を全て調べてもわかりませんでした。 どうかよろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス ・最初『ccs=fread(&d,sizeof(d),1,fi);』を読み込んでいるが、 a=d が同じか、違うかをチェックしていない。 ・ループ中で 『fread(&b,sizeof(b),1,fi);』を読み込んだ後に、また 『fread(&d,sizeof(d),1,fi);』を読み込んでいる。 ここでもb=dが同じか、違うのかをチェックしていない。 よって正しく符号化が出来ないのです。 ・直すとしたら次のステップになります。 (1)最初に1文字(a)を読み込む (2)do-while でループを構成 (3)『fread(&b,sizeof(b),1,fi);』を削除 (4)if(a==b){ … }の処理を記述 (5)do-while の直前で次の1文字(b)を読み込む (6)do-while の条件式で fread の戻り値が 0 なら終了 とします。 ・でも1文字取得する場合は fgetc を使えば分かりやすくなりますよ。 fgetc ならばファイルの終わりは EOF が返されます。 あと c カウンタは unsigned char 型ですので同じ文字が 256 以上の場合は c カウンタが 0 にリセットされます。ここの部分を考慮して改良してください。 前回のサンプルにある『else if ( n >= 255 ){』でもファイルに書き出しています。 c カウンタが 255 になったら文字コード、連続する数をファイルに書き出しましょう。 ・以上。まずは fread から fgetc に書き直してみる。この方が分かりやすいと思うよ。
- Oh-Orange
- ベストアンサー率63% (854/1345)
※訂正。 >(3)どうして ccs の値でループして処理をしているのですか? > files99.txt ファイルにNULコードが含まれているの? > ここがおかしい気がします。 ↑ freadの戻り値ならおかしくないね。 ・失礼しました。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス (1)念のために fopen の戻り値をチェックして下さい。 (2)fread よりも fgetc で1文字読み込むほうが分かりやすい気がします。 (3)どうして ccs の値でループして処理をしているのですか? files99.txt ファイルにNULコードが含まれているの? ここがおかしい気がします。 >どこを改善すればよいのか手持ちの資料や学校の図書館を全て調べてもわかりませんでした。 ↑ 手持ちの資料がない。 学校の図書館でも分からない。 それならネットで検索をして下さい。 見つかりますよ。 例えば http://ja.wikipedia.org/wiki/%E9%80%A3%E9%95%B7%E5%9C%A7%E7%B8%AE→『連長圧縮』 などを参考にして下さい。 これは『ランレングス圧縮』の基本です。 サンプル: int n = 1; // ランレングス(文字カウンタ) int b; // 1つ前の文字コード int c; // 今現在の文字コード for ( b = -1 ; (c = fgetc(fi)) != EOF ; b = c ){ if ( c != b ){ if ( b != -1 ){ fputc( b, fo ); fputc( n, fo ); n = 1; } } else if ( n >= 255 ){ fputc( b, fo ); fputc( n, fo ); n = 1; } else{ n++; } } fputc( b, fo ); fputc( n, fo ); 以上。
補足
ccsのループはfreadの返り値が0のときになれば最後まで読み込んだことになるので終了するという意味です。 プログラムを最後まで書き込んでいませんでした。 fclose(fo); fclose(fi); return 0; } が続きますすみませんでした。 情報の個数をカウントするにはどこを改善すればよいでしょうか?