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