2016-09-13 8 views
1

構造体の一部を16進値で連結しようとしています。私はループのすべてのバイトを実行し、16進数に変換し、その後、1つの長い文字列にすべての16進数を連結したい。C whileループで文字列を連結します。

しかし、ループの最後には1つの値しかありません。何らかの理由で、文字列が正しく連結されていません。私は間違って何を考えている?

typedef struct OPTIONS_STR 
{ 
    int max; 
    int printName; 
} OPTIONS; 

void set_default_options(OPTIONS *options) 
{ 
    options->max = -1; 
    options->printName = 0; 
} 

void do_file(FILE *in, FILE *out, OPTIONS *options) 
{ 
    char ch; 
    int loop = 0; 
    char buf[81]; 
    buf[0] = '\0'; 
    int sz1; 
    int sz2; 
    int sz3; 

    int seeker = offsetof(struct myStruct, contents.datas); 

    //find total length of file 
    fseek(in, 0L, SEEK_END); 
    sz1 = ftell(in); 

    //find length from beggining to struct beginning and minus that from total length 
    fseek(in, seeker, SEEK_SET); 
    sz2 = sz1 - ftell(in); 

    //set seek location at beginning of struct offset 
    fseek(in, seeker, SEEK_SET); 

    sz3 = sz2 + 1; 
    char buffer[sz3]; 
    char msg[sz3]; 

    buffer[0] = '\0'; 

    while (loop < sz2) 
    { 
     if (loop == sz2) 
     { 
      break; 
     } 

     fread(&ch, 1, 1, in); 
     sprintf(msg, "%02X", (ch & 0x00FF)); 
     strcpy(buffer, msg); 

     ++loop; 
    } 
    printf("%s\n", buffer); 
} 

int main(int argc, const char * argv[]) { 

    OPTIONS options; 
    set_default_options(&options); 

    const char *current = "/myfile.txt"; 
    FILE *f = fopen(current, "rb"); 
    do_file(f, stdout, &options); 
    fclose(f); 

}; 
+3

strcpy()は、ソース文字列を宛先文字列にコピーして前の内容を上書きします。代わりに 'strcat()'が必要でしょう。 –

+4

'int index = 0; index + = sprintf(&buffer [index]、 "%02X"、(ch&0x00FF)); ' – LPs

+3

あなたもバッファを十分に大きくしていないことに注意してください。各入力文字はバッファ内に2桁の16進数を必要としますが、1つの入力文字には十分なスペースしかありません。 –

答えて

3

strcpyの代わりにstrcatを使用してください。それはあなたの問題を解決するはずです。効率のため

はまた、あなたのif(loop == sz2) breakチェックがwhile(loop < sz2)チェックの無駄な重複であるchar *p = bufferのような書き込みポインタを使用してに見て、p += sprintf(p, "%02X", (ch & 0x00FF))

ようなもので、書き込み位置を進めます。 loopsz2以上の場合、whileループは実行されません。

freadを使用する理由が1文字だけの場合は、 fgetcまたはgetcが良い選択であるようです。

また、freadまたはgetcを使用しても、ファイルの最後を確認する必要があります。ファイルがでない場合、にはsz2バイトが含まれていますか?現代のシステムはすべてマルチプロセスとマルチユーザなので、誰かがftellの呼び出しの後でファイルを短くする可能性があります。たとえあなたがそれをチェックしたとしても、それは変わることがあるので、あなたは決して物事を引き受けるべきではありませその仮定を立てることは、TOCTTOU(Time of Use To Time Of Use)バグの原因となります。

+0

こんにちはZanは、ポインタ部分から離れて、すべてのことを理解しました。それを私のコードにどのように含めるのですか?バッファが作成されると、先頭にchar * pが宣言されますか? –

+0

@Ke。それはバッファが作成された後に来なければならないので、何かを指摘する必要があります。そして、それはループの内部にあることはできません。あるいは、各ループのバッファにリセットされます。 –

+0

ok私は今、ポインタのものを取得し、sprintfの仕組みを考えているので、今は、 "\ n \ t \ t \ t \ t"という配列に余分な文字を追加しようとしています。どんなアイデアなの? –

-1

do_file()では、whileループで1バイトの16進値をコピーしています。したがって、whileループの各繰り返しで文字配列bufferの次のバイトに移動する必要があります。buffer++またはstrcpy(buffer[loop], msg);

+0

あなたのメソッドは動作するかもしれませんが、 'loop * 2'が必要です –

関連する問題