2017-11-23 7 views
0

私はこれが質問の七面鳥ではないことを願っています。 EOFを検出する私の条件は機能していないようです。コードは、EOFに続き、ステートメント内で処理されます。テキストを再作成すると、適切に表示されますが、ガベージコードを含むbmp全体が、決してエンコードされていないテキストフラグの最後を出力します。私はprintfステートメントを次のelse条件に入れましたが、決してそれを入力して印刷しません。それが私の目の前にあるならば、私は問題が何かを見ることができません。いつものようにありがとう!EOFを検出していない

/******************************************************************************* 
* This code is to take a text document and using steganography techniques, hide 
* the text within a bmp. It will take each character of the text, parse it into 
* four 2 bit pieces and inject those bits into the two least significant bits 
* of each pixel color (BGR) byte as well as the line padding. 
******************************************************************************/ 
#include <stdio.h> 

/******************************************************************************* 
* getIntFromArray (borrowed from class notes). Takes unsigned character array 
* and assembles/returns an int value using bit shifting with OR. 
******************************************************************************/ 
int getIntFromArray(unsigned char bytes[]) 
{ 
    int n = 
      bytes[0] | 
      bytes[1] << 8 | 
      bytes[2] << 16 | 
      bytes[3] << 24; 
    return n; 
} 

/******************************************************************************* 
* bitWise. Take unsigned char pointer and character, parses the character 
* using bitwise manipulation and injects 2 bits into the 2 least significant 
* bits of each pixel color byte as well as padding. 
******************************************************************************/ 
void bitWise(unsigned char* bytes, char character) 
{ 
    int i; 
    char tmpChar; 
    for(i = 0; i < 4; ++i) 
    { 
    tmpChar = character; 
    tmpChar &= 3; 
    bytes[i] &= 252; 
    bytes[i] |= tmpChar; 
    character = character >> 2; 
    } 
} 

int flag = 0; 

int main(int argc, char **argv) 
{ 
    char *infilename = argv[1]; 
    char *outfilename = argv[2]; 

    unsigned char header[54]; 

    FILE *in = fopen(infilename, "rb");/*Command line input.*/ 
    FILE *out = fopen(outfilename, "wb");/*Command line input.*/ 

    int pixelWidth; 
    int pixelHeight; 
    int i; 
    int j; 

    fread(header, 1, 54, in);/* read header into array */ 

    pixelWidth = getIntFromArray(&header[18]); 
    pixelHeight = getIntFromArray(&header[22]); 

    fwrite(header, 1, sizeof(header), out);/* write header to output file */ 

    for(i = 0; i < pixelHeight; ++i)/*Loop to read pixel data from bmp.*/ 
    { 
    for(j = 0; j < pixelWidth; ++j) 
    { 
     unsigned char bytes[4]; 
     unsigned char character = 0; 

     fread(&bytes, 1, 4, in);/*Reads sequentially pixel and padding bytes.*/ 
     if(flag == 0)/*Breakout flag, initially set to 0.*/ 
     { 
     character = getchar();/*Takes in characters from stdin.*/ 
     if(character != EOF)/*Breakout if EOF.*/ 
     { 
      bitWise(bytes, character); 
     } 
     else 
     { 
      bitWise(bytes, 0);/*Sets end of hidden text with 4 bytes LSB to 0.*/ 
      flag = 1; 
     } 
     } 
     fwrite(&bytes, 1, 4, out); 
    } 
    } 
    fclose(in); 
    fclose(out); 
    return 0; 
} 
+0

おそらく、 'fread'の戻り値をチェックすると助けになるでしょう –

答えて

2

あなたはunsigned intからsigned intを割り当てています。結果はあなたが期待するものではありません。すべてのビットが1に設定された値になります。 (EOFの値は-1なので、署名されています)。

短編小説intである必要があります。単純なint characterがこの目的に役立ちます。

また別のものgetchar()intを返します。 int getchar(void);

行うにはいくつか他のものがあります: -

  • fread戻り値をチェックする必要があります。

    size_t fread(void * restrict ptr,size_t size, size_t nmemb,FILE * restrict stream);

fread関数は、読み取りエラーまたはエンドオブファイル が発生した場合nmemb未満であってもよい成功 読み出し、要素の数を返します。 sizeまたはnmembはゼロ、freadリターンである場合、配列の内容とstream の状態が

  • 変わらないゼロと もう一つは、fopen()の戻り値をチェックすることです。失敗した場合の戻り値はNULLです。
+0

ありがとう、訂正されたunsigned int。まだ問題あり。 –

+0

(EOFの値は-1なので、署名されています)が鍵です!私は署名のないcharを削除し、intからのキャストでcharを使用しましたが、これはうまくいきました。 –

+2

@MichaelServilla: 'getchar()'の結果を 'char'、' unsigned char'や 'signed char'ではなく' int'に格納するべきです。 'getchar()'は256文字の値(8ビット文字を前提とする)と特有の値 'EOF'のいずれかを返すことができるからです。文字型に値を格納すると、情報が捨てられます。これは危険です。 EOFを検出することは決してできないか、あまりに早くEOFを検出するかもしれません。 –

1

の2つがあり、深刻なのですが、あなたは評判の良い本を読んでいない、またはあなたが評判の書籍として、それとの深刻な問題を抱えていると信じて私をリードし、ここで共通問題は早期でこれらの問題をカバーします章。

おそらく、あなたが現在使用しているものがあなたのために働いていないので、他のオプションを調べるべきでしょう。あなたは試行錯誤の中で苦労していたこの時間のすべてをあなたの本を読んでいた可能性があり、あなたの本はこれらをきっちりと案内してくれるはずです共通の問題

最終行は:戻り値を尊重する必要があります

  • 戻り値をチェックする前に変換しようとしないでください。unsigned char character; character = getchar();では、getchar manualと書かれているからに変換しようとする前に、intというメッセージがunsigned charに変換されています。その変換は、データが失われる可能性があります。どのデータを失ったのだろうか?

あなたはK & R2Eやマニュアルを理解するのに苦労している場合は、当て推量に依存しているコードを書くために、混乱し、かなりの移動よりも、あなたが理解していないものについての質問を記述する必要があります。任意の当て推量は54を通過し、このようなC.

ます。またfreadの戻り値をチェックしなければならない、と私はsizeパラメータを見ることを期待したいなどの言語では危険であるとcountパラメータは、あなたのケースで1を通過しました。 freadのみ五十から三バイト(または五十から二、または五十から一)を読み込むとき、それはむしろとしてその予想外に短い入力を処理するよりも、入力の終わりだかのようにそのように、あなたは機会を扱うことができます予想されるサイズですが。 getcharマニュアルのように、freadについては、the fread manualからすべてを見つけることができます。

オハイオ州、そして最近では、私は「Youtube videos」という回答をたくさん得ています。 Youtubeは評判の良い本の代用品ではありません。誰でもそこに飛びついて「ちょうどいい」と思っています。あなたが見ているビデオには、あなた自身の推測と同じように欠陥があるでしょう。一方、評判の良い本は、計画、ピアレビュー、テスト(これらの書籍は通常、教授陣を持つ教授によって書かれているので)、リファクタリング(テストに基づいて、発生する「しゃっくり」をよく扱う)。

選択は明白でなければならず、証拠はプディングの食べ物にあります。 「youtube」や「try it and see」メソッドを試してみたら、彼らはあなたのために働いていません。あなたの前にあなたが見ているのは、その結果です。何かを試してみてください。がんばろう!

関連する問題