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

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

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

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

Q&A

解決済

4回答

1795閲覧

無限ループが発生してしまう

yukkuri

総合スコア624

C

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

0グッド

0クリップ

投稿2019/08/12 02:58

現在、Cの練習も兼ねてアセンブラを作っていました。
そこで気になったバグ?を見つけ、なぜそのようになるのかわかりません。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#define FILE_OPEN_ERROR 1 6#define FILE_WRITE_ERROR 2 7#define MEMORY_OVER_ERROR 3 8 9/* バッファサイズは0未満にならないのでunsigned */ 10typedef unsigned int size_i; 11 12typedef char BYTE; 13typedef unsigned char UBYTE; 14typedef short WORD; 15typedef unsigned short UWORD; 16typedef int DWORD; 17typedef unsigned int UDWORD; 18typedef long QWORD; 19typedef unsigned long UQWORD; 20 21typedef struct 22{ 23 char *buf; 24 size_i bs; /* now buffer size / buffer seek pos */ 25 size_i mbs; /* max buffer size */ 26} BUFFER; 27 28void buffer_w(BUFFER *buf, BYTE data); 29int buffer_tofile(FILE *fw, BUFFER *buf); 30 31int main(int argc, char **argv) 32{ 33 char *inf = argv[1], *outf = argv[2]; 34 fprintf(stdout,"in:%s out:%s\n", inf, outf); 35 36 FILE *fr = fopen(inf, "r"); 37 if(fr == NULL){ 38 fprintf(stderr,"input file open error.\n"); 39 return FILE_OPEN_ERROR; 40 }else{ 41 char buf[256]; 42 /* 改行文字も入れて読み込む */ 43 fgets(buf,255,fr); 44 while(buf != NULL){ 45 /* 改行文字をはじめの位置から探す */ 46 char *end = strchr(buf,'\n'); 47 /* 見つかった場合改行文字を終端文字に置き換え */ 48 /*if(end != NULL)*/ end[0] = 0; 49 fprintf(stdout,"read:%s\\n", buf); 50 /* buffer clear */ 51 fgets(buf,255,fr); 52 } 53 } 54 fclose(fr); 55 56 fprintf(stdout,"buffer allocate\n"); 57 /* バッファの最大サイズ */ 58 size_i buffer_size = 512; 59 /* 書き込み用バッファ */ 60 BUFFER *buff = (BUFFER *)malloc(sizeof(BUFFER)); 61 if(buff == NULL) return MEMORY_OVER_ERROR; 62 buff->buf = calloc(1, buffer_size); 63 if(buff->buf == NULL) return MEMORY_OVER_ERROR; 64 buff->bs = 0; 65 buff->mbs = buffer_size; 66 67 /* テスト */ 68 fprintf(stdout,"buffer write test.\n"); 69 buffer_w(buff, 0x90); 70 buffer_w(buff, 0xfa); 71 buffer_w(buff, 0xfb); 72 73 FILE *fw = fopen(outf, "wb"); 74 if(fw == NULL){ 75 fprintf(stderr,"output file open error.\n"); 76 return FILE_OPEN_ERROR; 77 }else{ 78 int a = buffer_tofile(fw, buff); 79 if(a != 0){ 80 switch(a){ 81 case FILE_WRITE_ERROR:{ 82 fprintf(stderr,"output file can't write data."); 83 break; 84 } 85 } 86 } 87 } 88 fclose(fw); 89 90 return 0; 91} 92 93/* バッファに1バイト書き込む */ 94void buffer_w(BUFFER *buf, BYTE data) 95{ 96 if(buf->bs == buf->mbs){ 97 /* バッファがすべて埋まったので何もしない */ 98 return; /* buffer max */ 99 }else{ 100 buf->buf[buf->bs] = data; 101 buf->bs++; 102 } 103 104 return; 105} 106 107/* 108 * バッファのデータをファイルに書き込む 109 * 書き込むバイトがない場合何もしない 110 * 111 * return: 112 * 0:正常終了 113 * それ以外:例外終了 原因はマクロと同じ 114 */ 115int buffer_tofile(FILE *fw, BUFFER *buf) 116{ 117 if(fw == NULL) return FILE_OPEN_ERROR; 118 119 if(buf->bs > 0){ 120 int a = fwrite(buf->buf, buf->bs, 1, fw); 121 if(a < 1) return FILE_WRITE_ERROR; 122 } 123 124 return 0; 125}

strchr関数を呼んだあと、もし見つからなかったらNULLが帰るようになっているそうなので、if文を使ってNULLでない場合は処理を行う、というようにしました。しかし、その後コンパイルして実行すると、今回の読み込んだファイルでは今回の読み込んだファイルでは3行目が無限にループしてしまいました。

読み込んだファイル

NOP CLI STI

環境は、windows、gccを使用しています。

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

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

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

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

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

guest

回答4

0

while(buf != NULL){
bufは配列先頭アドレスなので、絶対にNULLではないです。

「ファイルを終わりまで読んだら」ということなら、fgetsの返り値を見ます。

C

1 char buf[256]; 2 /* 改行文字も入れて読み込む */ 3 while(fgets(buf,255,fr)){ 4 /* 改行文字をはじめの位置から探す */ 5 char *end = strchr(buf,'\n'); 6 /* 見つかった場合改行文字を終端文字に置き換え */ 7 /*if(end != NULL)*/ end[0] = 0; 8 fprintf(stdout,"read:%s\n", buf); 9 }

ただ、同じ変数に上書きし続けると、結局最後の行しか取れないので、これでは駄目。
全体構造がおかしいので、ゼロから作り直した方が良いです。

投稿2019/08/12 04:44

otn

総合スコア84423

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

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

0

なんかちょっとコードを見ていると、コードがひどいですね

while(buf != NULL){

このwhile ループ、無限ループになってますね。
まあ、その他にも明らかなバグがいくらか散見されます

投稿2019/08/12 04:30

y_waiwai

総合スコア87719

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

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

0

ベストアンサー

まず、私はコード読んでいません。
こういうのはコードを読むより、デバッグしたほうが早いです。

MinGW辺りならGDB、VC++なら内蔵のデバッガ、
その両方でも使えるprintfデバッグ法でデバッグします。

参考: エラーの取り除き方

投稿2019/08/12 03:06

BeatStar

総合スコア4958

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

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

0

一応バグはなくなりました。

/*if(end != NULL)*/ end[0] = 0;```

if(end == 0) break; end[0] = 0

にしました。
なぜこのようになったのかはわかりません。
また、すこしコードをいじって調べたらわかったので、BeatStarさんをベストアンサーにしたいと思います。

投稿2019/08/12 03:26

yukkuri

総合スコア624

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問