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

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

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

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

Q&A

解決済

1回答

2204閲覧

16個ずつ表示したい

hinatti

総合スコア14

C

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

0グッド

0クリップ

投稿2017/08/03 00:40

編集2017/08/03 05:49

###前提・実現したいこと
今C言語でファイルダンププログラムを作成しています。
別関数でファイルのデータを一括で読み込んで構造体に持たせ、
その後別関数でファイルの内容を16個ずつ表示させたいです。
(ブロックサイズを256とした場合16行表示させる)

###発生している問題・エラーメッセージ
1行しか表示しない

###該当のソースコード

C言語

1#include <stdio.h> 2#include <conio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <math.h> 6 7#define RET_OK 1 //判定フラグ 8#define RET_ESC 0 //ESCキー判定 9#define DISPLAY_MAX_ONE 16 //表示フォーマット1の出力最大桁数 10#define DISPLAY_MAX_TWO 64 //表示フォーマット2の出力最大桁数 11#define MAX 256 //最大文字数 12 13typedef struct _DumpData{ 14 unsigned char fileName[MAX]; //ファイル名 15 unsigned char data[10000]; //読み込んだデータ 16 long size; //ファイル容量 17 int contents; //freadの戻り値 18 int blockSize; //ブロックサイズ 19 int totalBlock; //総ブロック数 20 FILE* file_pointer; //ファイルポインタ 21 int format; //表示フォーマット 22 int chinese_characters; //漢字表示 23 int blockNumber; //現在のブロック番号 24 unsigned char errorField[40]; //エラー表示フィールド 25} DumpData; 26 27//関数プロトタイプ宣言 28//ファイル名入力関数 29short file_name(DumpData* pointer); 30 31//ブロックサイズ入力関数 32short block_size(DumpData* pointer); 33 34//総ブロック数算出関数 35void totalBlock_calculation(DumpData* pointer); 36 37//ファイル要素表示関数 38void file_element(DumpData* pointer); 39 40//ファイルを読み取る関数 41void file_read(DumpData* pointer); 42 43//表示ファイル形式1関数 44void file_display_one(DumpData* pointer); 45 46//メイン関数 47int main(void) 48{ 49 short ret; 50 char key_data; 51 52 //構造体DATEの初期化 53 DumpData DATA = 54 { 55 {'\0'}, //ファイル名 56 {'\0'}, //読み込んだデータ 57 {0}, //ファイル容量 58 {0}, //freadの戻り値 59 {0}, //ブロックサイズ 60 {0}, //総ブロック数 61 {'\0'}, //ファイルポインタ 62 {1}, //表示フォーマット 63 {0}, //漢字表示 64 {1}, //現在のブロック番号 65 {'\0'}, //エラー表示フィールド 66 }; 67 68 DumpData* data;//構造体のポインタ宣言 69 data = &DATA;//ポインタdataに構造体DATEの先頭アドレスを代入 70 71 printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"); 72 printf("* * * * * * * *\n"); 73 printf("* * * * * * * *\n"); 74 printf("* * * * ファイルダンプ Ver 1.00 * * * *\n"); 75 printf("* * * * * * * *\n"); 76 printf("* * * * * * * *\n"); 77 printf("* * * * * * * *\n"); 78 printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"); 79 80 //ファイル名入力関数の呼び出し 81 ret = file_name(data); 82 if (ret != RET_OK) 83 { 84 return 0;//プログラムを終了 85 } 86 87 //ブロックサイズ入力関数の呼び出し 88 ret = block_size(data); 89 if (ret != RET_OK) 90 { 91 return 0;//プログラムを終了 92 } 93 94 //総ブロック数算出関数の呼び出し 95 totalBlock_calculation(data); 96 97 98 file_element(data);//ファイル要素表示関数の呼び出し 99 100 file_read(data);//ファイル読み込み関数の呼び出し 101 102 file_display_one(data); 103 104} 105 106//ファイル名入力関数 107short file_name(DumpData* pointer) 108{ 109 char key; 110 short judgment_flag;//判定フラグ 111 long character_number;//文字数 112 113 // ファイルを開くか、ESCキーが入力されるまで 114 judgment_flag = RET_OK; 115 pointer->file_pointer = NULL; 116 while ((pointer->file_pointer == NULL) && 117 (judgment_flag == RET_OK)) 118 { 119 printf("\n ファイル名を入力してください\n>"); 120 121 //文字数が256文字以下の間 122 for (character_number = 0; character_number < 255; character_number++) 123 { 124 key = (char)_getch(); 125 126 //ESCキーを押下した時 127 if (key == 0x1b) 128 { 129 judgment_flag = RET_ESC;//判定フラグを0にする 130 break; 131 } 132 133 //エンターキーを押下した時 134 if (key == 0x0d) 135 { 136 break;//入力終了 137 } 138 139 //いずれのキーも押下していないとき 140 putchar(key);//1文字ずつ出力 141 pointer->fileName[character_number] = key;//出力した文字を1文字ずつ構造体のファイル名に格納 142 } 143 144 // ファイル名が入力された場合(=Escキーが押されなかった場合) 145 if (judgment_flag == RET_OK) 146 { 147 pointer->fileName[character_number] = '\0';//ファイル名の最後にヌルを入れる 148 149 // ファイルを開く 150 pointer->file_pointer = fopen((char*)&pointer->fileName[0], "rb"); 151 152 // ファイルが開けなかった場合 153 if (pointer->file_pointer == NULL) 154 { 155 printf("\n<<ファイルが見つかりません>>"); 156 } 157 } 158 } 159 160 return judgment_flag;//判定フラグを返す 161} 162 163//ブロックサイズ入力関数 164short block_size(DumpData* pointer) 165{ 166 short judgment_flag;//判定フラグ 167 char key; 168 169 // ブロックサイズを指定するか、ESCキーが入力されるまで 170 pointer->blockSize = 0; 171 judgment_flag = RET_OK; 172 while ((pointer->blockSize == 0) && 173 (judgment_flag == RET_OK)) 174 { 175 printf("\n ブロックサイズを指定してください\n"); 176 printf(" ( (1)64 (2)128 (3)256 ) >"); 177 key = (char)_getch(); 178 179 //ESCキーが押下された場合 180 if (key == 0x1b) 181 { 182 judgment_flag = RET_ESC;//判定フラグを0にする 183 break; 184 } 185 186 putchar(key); 187 188 switch (key) 189 { 190 //入力した数が1の場合 191 case '1': 192 pointer->blockSize = 64;//構造体のブロックサイズに格納 193 break; 194 195 //入力した数が2の場合 196 case '2': 197 pointer->blockSize = 128;//構造体のブロックサイズに格納 198 break; 199 200 //入力した数が3の場合 201 case '3': 202 pointer->blockSize = 256;//構造体のブロックサイズに格納 203 break; 204 205 //1,2,3,ESCキーのいずれでも無い場合 206 default: 207 printf("\n<<該当する項目がありません>>"); 208 break; 209 } 210 } 211 212 return judgment_flag;//判定フラグを返す 213} 214 215//総ブロック数算出関数 216void totalBlock_calculation(DumpData* pointer) 217{ 218 double calculation;//計算結果 219 double check; 220 int location = 0; 221 222 //ファイルの最後までシーク 223 location = fseek(pointer->file_pointer, 0, SEEK_END); 224 225 //fseekのエラー検査 226 if (location != 0) 227 { 228 strcpy((char*)&pointer->errorField[0], "ファイルリードエラー");//構造体のエラー表示フィールドに格納 229 } 230 else 231 { 232 //ファイルの容量を取得する 233 pointer->size = ftell(pointer->file_pointer); 234 235 //総ブロック数の計算 236 calculation = (double)pointer->size / (double)pointer->blockSize; 237 238 //小数点以下を切り上げる 239 check = ceil(calculation); 240 241 pointer->totalBlock = (int)check;//構造体の総ブロック数に格納 242 } 243} 244 245//ファイル要素表示関数 246void file_element(DumpData* pointer) 247{ 248 printf("\n\n ファイル名:%s", pointer->fileName); 249 printf(" 総ブロック数:%d", pointer->totalBlock); 250 printf(" ブロックサイズ:%d\n", pointer->blockSize); 251 252 //フォーマットが1の時 253 if (pointer->format == 1) 254 { 255 printf("\n 表示フォーマット1"); 256 } 257 //フォーマットが2の時 258 else 259 { 260 printf("\n 表示フォーマット2"); 261 } 262 263 //漢字表示が0の時 264 if (pointer->chinese_characters == 0) 265 { 266 printf(" 漢字表示OFF\n"); 267 } 268 //漢字表示が1の時 269 else 270 { 271 printf(" 漢字表示ON\n"); 272 } 273 274 printf(" ブロック番号:%d", pointer->blockNumber); 275 printf(" [%-40s ]\n", pointer->errorField); 276} 277 278//ファイルを読み取る関数 279void file_read(DumpData* pointer) 280{ 281 int location = 0; 282 283 //先頭ページのとき 284 if (pointer->blockNumber == 1) 285 { 286 location = fseek(pointer->file_pointer, 0, SEEK_SET); 287 } 288 289 //fseekのエラー検査 290 if (location != 0) 291 { 292 strcpy((char*)&pointer->errorField[0], "ファイルリードエラー");//構造体のエラー表示フィールドに格納 293 } 294 else 295 { 296 pointer->contents = fread(pointer->data, sizeof(unsigned char), pointer->size, pointer->file_pointer); 297 298 //freadの戻り値が要素数より少ない時 299 if (pointer->blockSize > pointer->contents) 300 { 301 //feofの戻り値が0以外のときエラー 302 if (feof(pointer->file_pointer) != 0) 303 { 304 strcpy((char*)&pointer->errorField[0], "ファイルリードエラー");//構造体のエラー表示フィールドに格納 305 } 306 else 307 { 308 strcpy((char*)&pointer->errorField[0], "");//構造体のエラー表示フィールドに格納 309 } 310 } 311 else 312 { 313 strcpy((char*)&pointer->errorField[0], "");//構造体のエラー表示フィールドに格納 314 } 315 } 316} 317 318//表示ファイル形式1関数 319void file_display_one(DumpData* pointer) 320{ 321 int key; 322 int output = 0;//出力数 323 int out = 0;//出力文字数 324 int line_number;//行番号 325 short character_flag = 0;//文字フラグ 326 327 printf(" Addr Hex ASCII\n"); 328 329 //選択したブロックサイズ÷16した数が行番号より大きい間繰り返し 330 line_number = 0; 331 while ((pointer->blockSize / DISPLAY_MAX_ONE) > line_number) 332 { 333 //行番号の表示 334 printf(" %05X ", line_number); 335 336 //16個出力するまでループ 337 for (; DISPLAY_MAX_ONE > output; output++) 338 { 339 //freadの戻り値が出力数より大きいとき 340 if (pointer->contents > output) 341 { 342 //8個目と9個目の間に"-"表示 343 if (output == 7) 344 { 345 printf("%02X-", pointer->data[output]); 346 } 347 else 348 { 349 printf("%02X ", pointer->data[output]); 350 } 351 } 352 else 353 { 354 printf(" "); 355 } 356 } 357 358 //16文字出力するまでループ 359 for (; DISPLAY_MAX_ONE > out; out++) 360 { 361 //freadの戻り値が出力数より大きいとき 362 if (pointer->contents > out) 363 { 364 key = pointer->data[out]; 365 366 //漢字表示ONの時(SHIFT-JIS) 367 if (pointer->chinese_characters == 1) 368 { 369 //全角文字の1byte目の時 370 if ((key >= 0x81 && key <= 0x9f) || (key >= 0xe0 && key <= 0xfc)) 371 { 372 //出力文字数が16の時 373 if (out == 15) 374 { 375 putchar('$'); 376 character_flag = RET_OK;//文字フラグを1にする 377 } 378 else 379 { 380 putchar(key); 381 } 382 } 383 else 384 { 385 //文字フラグが1の時 386 if (character_flag == RET_OK) 387 { 388 putchar('$'); 389 character_flag = 0;//文字フラグを0にする 390 } 391 //半角文字の時 392 else if ((key >= 0x20) && (key <= 0x7e)) 393 { 394 putchar(key); 395 } 396 //全角文字、半角文字でもない場合 397 else 398 { 399 putchar('$'); 400 } 401 } 402 } 403 //漢字表示OFFの時(ASCII) 404 else 405 { 406 //半角文字の時 407 if ((key >= 0x20) && (key <= 0x7e)) 408 { 409 putchar(key); 410 } 411 else 412 { 413 putchar('$'); 414 } 415 } 416 } 417 else 418 { 419 putchar(' '); 420 } 421 } 422 423 line_number++;//行番号のカウントアップ 424 printf("\n"); 425 426 //4行出力ごとに改行 427 if ((line_number % 4) == 0) 428 { 429 printf("\n"); 430 } 431 } 432}

###試したこと
最初はファイルの内容を表示する関数内のwhileループの中で16個ずつfreadしていけば出来ると考え、出来たのですがこれだと読み込みの途中でエラーでた場合がダメだと言われ、質問の内容に切り替えた次第です。

###補足情報(言語/FW/ツール等のバージョンなど)
サクラエディタとSDKコマンドプロンプトを使用しています。
関係ない関数はコードが長すぎるかなと思い、省かせていただきました。

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

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

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

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

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

tamy

2017/08/03 02:05

可能であれば,コード部分のインデントを整えていただけますか? すごく読みづらいので...
hinatti

2017/08/03 02:06

了解しました! 確かに読みずらかったですね…
guest

回答1

0

ベストアンサー

1行しか表示しない

一行表示して終了するのかと思ったら、そうではなくて、例えばブロックサイズが128バイトの時、8行表示はするけれど、その8行は最初の一行(16バイト分)の繰り返しになっていて、残りの112(=128-16)バイト分の情報は何も表示されない、ってことのようですね。

表示のバグ。ということは、表示するfile_display_one()関数のバグだろうな・・・そこだけ見ると、ああ確かに(笑)。表示する1バイトはpointer->data[output]でしょ。行が進んでも、毎回同じ所・・・と、ヒントはここまでにしますので、後はご自分で対策してください。

完成には超えなければならない山が、まだいくつか残っていそうです。Enjoy !

投稿2017/08/03 06:27

rubato6809

総合スコア1380

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

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

hinatti

2017/08/03 06:36

回答ありがとうございます! まさにrubatoさんのおっしゃる通りのことがおきてます… ヒントをもとに頑張ってみます~
hinatti

2017/08/03 07:16

HEXをカウントする変数と文字をカウントする変数を宣言してやってそれをdataで指定してあげたら出来ました!! 本当に回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問