ページ 1 / 1
C言語で作られたバイナリエディタのバグ
Posted: 2018年2月22日(木) 22:08
by fabersid
BMP作成-
どこが間違っていますか?で
BMP以外にもJPGなどを個人でしていた時です。
明らかにバイト数が合わなかったのです。
http://tricky-code.net/mine/c/mc10bine. ... ンパイルしたのですが
16進数でいう00からFFまでをall_char.txtとして保存したとき
0 1 2 3 4 5 6 7 8 9 A B C D E F
0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0e 0f 10 ................
10: 11 12 13 14 15 16 17 18 19 .........
という感じで途中までしか出力できません。
1AであるSUBという制御記号が問題かと思われます。
理由は
「テキストファイルのファイル終端(EOF)を表すのによく使われる。」
という記述があるから。
よくよく見ると0D(CR=復帰)も表示できていません
ほとんど丸写ししたのでtrickyなところが多めです。
► スポイラーを表示
コード:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int checkAscii(int c);
int main(int argc, char *argv[])
{
FILE *fp;
unsigned io = 0;
int i, j[16];
char *psz = "%02x ";
const char *szErrMsgs[] = {
"バイナリ表示をするファイルを指定して下さい。"
, "%sのファイルの読み込みに失敗しました。"
, " 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"
};
if (argc != 2) {
printf(szErrMsgs[0]);
exit(1);
}
if (! (fp = fopen(argv[1], "r"))) {
printf(szErrMsgs[1], argv[1]);
exit(1);
}
printf(szErrMsgs[2]);
while (! feof(fp)) {
for(i = 0; i < 16; j[i++] = fgetc(fp));
if (j[0] == -1)
break;
printf("%4x: ",io);
if (argc == 2) {
for (i = 0; i < 16; i++)
printf( (j[i] != -1) ? psz : " ", j[i]);
printf(" ");
}
for (i = 0; i < 16; i++) {
(j[i] != -1) ? ((checkAscii(j[i]) == 0 && (*(j + i) = '.')), putchar(j[i]))
: putchar(' ');
}
printf("\n");
io += i;
}
return 0;
}
int checkAscii(int c)
{
return c >= ' ' && c <= '\~';
}
Re: C言語で作られたバイナリエディタのバグ
Posted: 2018年2月22日(木) 22:17
by みけCAT
ファイルをテキストモードで開いているため、勝手に変換が行われていると考えられます。
fopenの引数の"r"を"rb"にして、バイナリモードで開いてみてください。
お礼&訂正
Posted: 2018年2月22日(木) 22:32
by fabersid
お礼:みけCAT さんありがとうございます。
すぐに期待した実行結果が出ました。
普段見ているコードよりはやはり簡単なのでしょう。
私にはまだまだ難しいです。
今日、FILE *を初めてネット以外で習いました。
訂正1:
mc10bine.phpでバイナリエディタをコンパイルしたのですが
訂正2:Yahoo知恵袋でも質問しています。と書いていますが、実を言うと
5秒もたたずに取り消しました。なので今の時点でマルチポストを
していません。投稿後にYahooはマルチポストがダメと知ったので。
オフトピック
rとrbでだいぶ変わるのですね。
やはりコンピュータ関係は奥が深いです。
ということで解決方法は
if (! (fp = fopen(argv[1], "r"))) {
を
if (! (fp = fopen(argv[1], "rb"))) {
に変えるだけです。
Re: C言語で作られたバイナリエディタのバグ
Posted: 2018年2月23日(金) 07:16
by かずま
VC++ や gcc では、60行目の '\~' について、
「不正なエスケープシーケンス」という警告が出ます。
'~' と書きましょう。
あと気になったのは、
・このプログラムは、バイナリエディタではなく、16進ダンプである。
・16進表示をするのに、「バイナリ表示」というエラーメッセージがある。
・ファイルのオープンに失敗したのに、「読み込みに失敗」となっている。
・47行目だけ、j
の代わりに *(j + i) と書いている。
・EOF と書くべきところを -1 と書いている。
・<ctype.h> の isprint が使えるのに、checkAscii を定義している。
・fopen しているのに、fclose がない。(なくてもかまわないのですが)
修正版
コード:
#include <stdio.h> // fopen, fclose, fread
#include <ctype.h> // isprint
int main(int argc, char *argv[])
{
FILE *fp; unsigned char b[16]; unsigned addr, i, n;
if (argc != 2) return puts("ファイルを指定して下さい。"), 1;
fp = fopen(argv[1], "rb");
if (!fp) return printf("%s のオープンに失敗しました。\n", argv[1]), 2;
puts(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
for (addr = 0; (n = fread(b, 1, 16, fp)) > 0; addr += n) {
printf("%4x: ", addr);
for (i = 0; i < n; i++) printf("%02x ", b[i]);
printf("%*s", (16 - n) * 3 + 4, "");
for (i = 0; i < n; i++) putchar(isprint(b[i]) ? b[i] : '.');
putchar('\n');
}
fclose(fp);
return 0;
}
Re: C言語で作られたバイナリエディタのバグ
Posted: 2018年2月23日(金) 07:41
by かずま
かずま さんが書きました:
あと気になったのは、
追加です。
・19行目で argc が 2 であるかどうかチェックしているのに、
39行目に不要な argc のチェックがある。
コード:
printf("%*s", (16 - n) * 3 + 4, ""); は
for (i = (16 - n) * 3 + 4; i > 0; i--) putchar(' '); と
書くこともできます。