質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

2125閲覧

C言語 dumpコマンド作成 file読み込みが上手くいかない

kokok

総合スコア145

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2019/08/19 02:49

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}

ここの部分に問題がある気がするのですが、なかなか解決できません。  
ご指摘いただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2019/08/19 03:09

「上記のコードをコマンドラインから実行しても、エラーも出力も何もでません。」この時どう実行したのかコマンドラインに打ち込んだそのままを書いてもらわないと、なんとも判断できません。
kokok

2019/08/19 03:40

mydump ファイル名 です。
mit0223

2019/08/19 03:46

ちょっとやってみましたが、mac でも linux でも、それらしきものが出力され、動作しました。環境の問題かもしれません。OS, コンパイラのバージョン、コンパイル時のコマンド、テスト実行時のコマンドと結果を貼ってください。
kokok

2019/08/19 04:09

os : windows10 コンパイラのバージョンとコンパイル時のコマンドとテスト実行時のコマンドとはなんでしょうか? Visual Studioの標準のコンパイラを使っていると思います。
KoichiSugiyama

2019/08/19 04:23 編集

指定したファイルが0バイトということはないですか?私の環境(mac)で $ touch test.bin で作ったファイルを使って実行してみると何も出ませんが、 $ dd if=/dev/zero of=test.bin bs=1024 count=1 で1024バイトのファイルを作り直して実行するとdump結果が表示されます。
KoichiSugiyama

2019/08/19 04:40

Windows10 Visual Studio 2017でビルドしたものでも指定したファイルのサイズが1024バイトだとちゃんとdump結果が出ます。0バイトだと出ません。 ( > fsutil file createnew test.bin 1024 で作成)
kokok

2019/08/19 05:04

1024バイトで作成してみましたが、ファイルがありません。となってしまいます。
tatsu99

2019/08/19 07:04

実行ファイルとダンプ対象のファイルを同じフォルダ内に格納して、そのフォルダ内でコマンドを実行してください。
kokok

2019/08/19 07:33

ありがとうございます。 pathを通してもフォルダ内まで移動して実行しないとダメなのでしょうか?
tatsu99

2019/08/19 07:44 編集

pathを通してOKとなるのは、実行ファイルに対してです。 ダンプ対象のファイルは、フルパスで指定するか、そのファイルがあるフォルダまで移動して、コマンドを打たないとだめです。そもそも、そのあたりの事情が不明なので、まずは、確実に成功する方法として、 実行ファイルとダンプ対象のファイルを同じフォルダに格納し、そのフォルダでコマンドを実行してくださいと書きました。この方法で、「ファイルがありません」という件をまず解決するのが先決かと。
kokok

2019/08/19 07:54

ありがとうございます。 「ファイルがありません」という件は、そのファイルがあるフォルダまで移動して実行したところ解決できました。
tatsu99

2019/08/19 08:13 編集

それでは、本件は解決でしょうか。それとも、何の出力結果もなく終了してしまうということでしょうか。
guest

回答1

0

ベストアンサー

VisualStudioを使ってるならデバッグしましょう。
ファイルのオープンが問題だと思うなら、そこんところにブレークポイントを設置して実行を止め、各変数の値を確認してください。また、その実行結果が何を返しているか確認しましょう。
そして1行づつ実行させ、あなたの想定から外れる動作のところを確認します

投稿2019/08/19 04:25

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kokok

2019/08/19 05:12

コマンドラインから引数など渡す場合は、どのようにデバッグすれば良いのでしょうか?
y_waiwai

2019/08/19 05:18

プロジェクトのプロパティでコマンド引数の設定があります このコードではファイル名の設定がうまくいかないですね
kokok

2019/08/19 05:40

プロジェクトのプロパティでコマンド引数の設定は一応しております。
y_waiwai

2019/08/19 05:51

ならそれでデバッグしましょうよ。 1行づつ実行させてみたらどうですか
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問