c
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#pragma warning(disable: 4996) 5 6#define H_PRT 0x02// ヘッダ印字オプション 7#define C_PRT 0x01// 文字印字オプション 8#define ROW 16 // 1行に表示する文字 9#define TEXTBUF 16 //テキストファイル用のバッファ 10#define FILE_ERR 10// 11#define OPT_ERR 10 12 13 14//オプション 15typedef struct { 16 17 char* infilename; 18 char prt_charflag; 19 char prt_headerflag; 20 char prt_help; 21 int offsetval; 22 int filecheck; 23 int optcheck; 24} opts_t; 25 26//プロトタイプ宣言 27void dump(unsigned char* staddr, int dsize, opts_t* opts); 28 29//オプションの解析 30int opts_analisys(int argc, char* argv[], opts_t* opts) { 31 32 int cnt; 33 int err = 0; 34 for (cnt = 1; cnt < argc; cnt++) { //引数の数ループ 35 if (*argv[cnt] == '/') { //引数の最初の文字が/なら 36 37 switch (*(argv[cnt] + 1)) { 38 39 case'H': 40 case'h': 41 42 opts->prt_headerflag = 1; //16行毎にヘッダーの出力 prt_headerflag; = 1 43 44 break; 45 case 'c': 46 case 'C': 47 48 opts->prt_charflag = 1; //ダンプのあとに文字を表示 49 50 break; 51 case 'o': 52 case 'O': 53 opts->offsetval = 1; 54 55 break; 56 57 case '?': 58 opts->prt_help = 1; 59 break; 60 61 default: //オプションが無いとき、エラー 62 63 opts->optcheck = OPT_ERR; 64 err = OPT_ERR; //opt err 65 66 break; 67 } 68 continue; 69 } 70 if (opts->infilename == NULL) { 71 opts->infilename = argv[cnt]; //ファイル名をopts.infilename へ 72 } 73 else { 74 75 opts->filecheck = FILE_ERR; 76 err = FILE_ERR; 77 78 return err; 79 } 80 } 81 return err; 82} 83 84int main(int argc, char* argv[]) { 85 86 87 char bin_data[TEXTBUF]; // テキストファイル読み込み用 88 int readnum; 89 opts_t opts; 90 int result = 0; 91 92 //構造体の初期化 93 opts.infilename = NULL; 94 opts.prt_charflag = 0; 95 opts.prt_headerflag = 0; 96 opts.prt_help = 0; 97 opts.offsetval = 0; 98 opts.filecheck = 0; 99 opts.optcheck = 0; 100 101 FILE* file; 102 103 result = opts_analisys(argc, argv, &opts); //オプションの解析 104 105 //if(ファイルエラー または オプションで?) 106 if (((result & opts.filecheck) != 0) || ((result & opts.optcheck) != 0) || (opts.prt_help == 1)) { 107 108 if ((result & opts.filecheck) != 0) { 109 fprintf(stderr, "ファイル指定が2つあります"); 110 } 111 if ((result & opts.optcheck) != 0) { 112 113 fprintf(stderr, "オプション指定が間違っています"); 114 } 115 if (opts.prt_help == 1) { 116 fprintf(stderr, "構文: mydump[<opts>] [<inpath>] [<opts>]\n機能: ファイルやデバイスの内容を16進で表示する\nオプション:\n/ o[=]<hex> オフセットアドレスの指定(省略の場合は0000)\n/ h 16行毎にヘッダーの出力(デフォルトは = 0)\n / c ダンプのあとに文字を表示(デフォルトは = 1)\n / ? 使用方法の表示(このメッセージを表示)"); 117 } 118 return 0; 119 } 120 121 if (opts.infilename != NULL) { //コマンドラインからファイルの入力があれば 122 123 124 if ((file = fopen(opts.infilename, "rb")) != NULL) { //ファイルがあれば 125 126 fseek(file, opts.offsetval, SEEK_SET); 127 } 128 else { //ファイルがなければ 129 fprintf(stderr, "ファイルがありません"); 130 return 0; 131 } 132 } 133 else { 134 file = stdin; 135 } 136 137 while ((readnum = fread(bin_data, sizeof(unsigned char), TEXTBUF, file)) > 0) { 138 139 dump(bin_data, readnum, &opts); 140 } 141 142 if (opts.infilename != NULL) { 143 fclose(file); //ファイルが開かれたらクローズ 144 } 145} 146//印刷 147void dump(unsigned char* staddr, int dsize, opts_t* opts) { 148 149 int startcnt = 0;// ダンプするバイト数のカウント 150 int bytecnt; // 16回ループさせる 151 int savecnt; 152 static int address = 0; //アドレスの表示 153 static int onhold = 0; //文字出力が最後のバイトだった時の一時保留 154 155 static int headercnt = 0; 156 157 char addrhead[] = "Addr"; 158 char hexa[] = "0 1 2 3 4 5 6 7 8 9 A B C D E F"; 159 char charprint[] = "0 2 4 6 8 A C E"; 160 161 while (startcnt < dsize) { 162 163 if (onhold != 0) { //前回最後が漢字だった場合、漢字を出力して改行 164 165 printf("%c%c\n", onhold, staddr[startcnt]); 166 } 167 168 //初回ヘッダー表示 opt & H_PRT == 0だった時は16行毎にヘッダー表示 169 if ((headercnt == 0) || ((opts->prt_headerflag & H_PRT) == 0) && (headercnt % ROW == 0)) { 170 //16行毎にヘッダー 171 172 printf(" %s %s ", addrhead, hexa); 173 174 175 if ((opts->prt_charflag & C_PRT) != 0) { //opt が文字表示の場合 文字ヘッダー表示 176 177 printf("%s", charprint); 178 } 179 180 printf("\n"); 181 printf("-------- ---- ---- ---- ---- ---- ---- ---- ----"); 182 183 if ((opts->prt_charflag & C_PRT) != 0) { ////opt が文字表示の場合 文字罫線表示 184 printf(" ----------------"); 185 186 } 187 printf("\n"); 188 } 189 190 headercnt++; 191 192 printf("%08x ", address); 193 194 savecnt = startcnt; 195 for (bytecnt = 0; bytecnt < ROW; bytecnt++) { 196 197 if (startcnt < dsize) { 198 printf("%02x", staddr[startcnt]); //16進数で出力 199 } 200 else { 201 printf(" "); 202 } 203 if (startcnt % 2 != 0) { 204 printf(" "); 205 } 206 startcnt++; 207 } 208 209 //文字の出力 210 211 if ((opts->prt_charflag & C_PRT) != 0) { //optで文字表示の場合 表示 212 213 startcnt = savecnt; 214 printf(" "); 215 216 for (bytecnt = 0; bytecnt < ROW; bytecnt++) { 217 218 if (onhold != 0) { //前回最後が漢字だった場合 次の行の最初にスペースと初期化 219 220 printf(" "); 221 onhold = 0; 222 bytecnt++; 223 startcnt++; 224 } 225 226 if (startcnt < dsize) { 227 228 //漢字だった場合 229 if ((staddr[startcnt] >= 0x81 && staddr[startcnt] < 0xa0) || (staddr[startcnt] >= 0xe0 && staddr[startcnt] < 0xfd)) { 230 231 if (bytecnt < ROW - 1) { //最後のバイトでなければ 232 233 printf("%c%c", staddr[startcnt], staddr[startcnt + 1]); 234 startcnt++; 235 bytecnt++; 236 } 237 else {//漢字で最後のバイトの場合、保留 238 239 onhold = staddr[startcnt]; 240 } 241 } 242 else { 243 244 if ((staddr[startcnt] >= 0x20 && staddr[startcnt] < 0x7f) || (staddr[startcnt] >= 0xa0 && staddr[startcnt] < 0xe0)) { 245 246 printf("%c", staddr[startcnt]); 247 } 248 else { 249 printf(""); 250 } 251 } 252 } 253 else { 254 printf(" "); 255 } 256 257 startcnt++; 258 } 259 if (onhold == 0) { //最後が漢字でなければ改行 260 printf("\n"); 261 } 262 } 263 else { //optが文字表示ではない場合 改行 264 265 printf("\n"); 266 } 267 address += ROW; //addressを出力しただけ足す 268 } 269} 270 271 272
上記のコードをコマンドラインから実行しても、エラーも出力も何もでません。
/? や ファイル名を複数入力した場合、オプションの解析でエラーがでるので
c
1 if (opts.infilename != NULL) { //コマンドラインからファイルの入力があれば 2 3 4 if ((file = fopen(opts.infilename, "rb")) != NULL) { //ファイルがあれば 5 6 fseek(file, opts.offsetval, SEEK_SET); 7 } 8 else { //ファイルがなければ 9 fprintf(stderr, "ファイルがありません"); 10 return 0; 11 } 12 } 13 else { 14 file = stdin; 15 } 16 17 while ((readnum = fread(bin_data, sizeof(unsigned char), TEXTBUF, file)) > 0) { 18 19 dump(bin_data, readnum, &opts); 20 } 21 22 if (opts.infilename != NULL) { 23 fclose(file); //ファイルが開かれたらクローズ 24 } 25}
ここの部分に問題がある気がするのですが、なかなか解決できません。
ご指摘いただけると幸いです。
「上記のコードをコマンドラインから実行しても、エラーも出力も何もでません。」この時どう実行したのかコマンドラインに打ち込んだそのままを書いてもらわないと、なんとも判断できません。
mydump ファイル名 です。
ちょっとやってみましたが、mac でも linux でも、それらしきものが出力され、動作しました。環境の問題かもしれません。OS, コンパイラのバージョン、コンパイル時のコマンド、テスト実行時のコマンドと結果を貼ってください。
os : windows10
コンパイラのバージョンとコンパイル時のコマンドとテスト実行時のコマンドとはなんでしょうか?
Visual Studioの標準のコンパイラを使っていると思います。
指定したファイルが0バイトということはないですか?私の環境(mac)で
$ touch test.bin
で作ったファイルを使って実行してみると何も出ませんが、
$ dd if=/dev/zero of=test.bin bs=1024 count=1
で1024バイトのファイルを作り直して実行するとdump結果が表示されます。
Windows10 Visual Studio 2017でビルドしたものでも指定したファイルのサイズが1024バイトだとちゃんとdump結果が出ます。0バイトだと出ません。
( > fsutil file createnew test.bin 1024 で作成)
1024バイトで作成してみましたが、ファイルがありません。となってしまいます。
実行ファイルとダンプ対象のファイルを同じフォルダ内に格納して、そのフォルダ内でコマンドを実行してください。
ありがとうございます。
pathを通してもフォルダ内まで移動して実行しないとダメなのでしょうか?
pathを通してOKとなるのは、実行ファイルに対してです。
ダンプ対象のファイルは、フルパスで指定するか、そのファイルがあるフォルダまで移動して、コマンドを打たないとだめです。そもそも、そのあたりの事情が不明なので、まずは、確実に成功する方法として、
実行ファイルとダンプ対象のファイルを同じフォルダに格納し、そのフォルダでコマンドを実行してくださいと書きました。この方法で、「ファイルがありません」という件をまず解決するのが先決かと。
ありがとうございます。
「ファイルがありません」という件は、そのファイルがあるフォルダまで移動して実行したところ解決できました。
それでは、本件は解決でしょうか。それとも、何の出力結果もなく終了してしまうということでしょうか。
回答1件
あなたの回答
tips
プレビュー