ページ 11

入力ファイルから読み込むプログラムが途中で動作が停止してしまいます

Posted: 2012年12月28日(金) 18:21
by blade
Visual Studio 2010を使っています。
入力テキストファイルの内容を読み込んで欲しい部分だけを抽出するプログラムを作っています。
テキストの内容を1行ずつ読み込み、コード内のwhile内でbase、posの内容を出力します。
しかし、
出力結果//////////
原型はaです、品詞はDTだ
原型はbrokenです、品詞はJJだ
原型はbikeです、品詞はNNだ
原型はbeです、品詞はVBZだ
原型はrepaiedです、品詞はVBNだ
////////
の後に実行ファイルが動作を停止してしまいます。
一行ずつステップインしてどこが悪いか見ていったところ
5回目のループが終わり、6回目のループ(dataにはNULLが入っているとき)に39行目のstrtok_sの内容がおかしいらしく、止まってしまうようでした。strtok_s自体は私がつくったわけではないですし、かつ動作が停止するまではちゃんと動いていたのでどこが悪くて
動作停止するかわかりません。
現段階で出力したい部分は出ているのであとはただプログラムが正常終了すればいいのですが、どうすれば正常終了するようになるでしょうか。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>

#define MAXLEN 3000  //文字列の長さ

int main (int argc, char **argv)
{
	typedef struct{
		char* base; 
		int id; 
		char *pos; 
		char arg; 
	}_token;

	_token p;
	
  FILE *fp;
  

  char data[256]; //単語のデータを格納
	FILE *fp2; //fp2は入力ファイル
	errno_t error;
	char* ctx;
	

	if ((error = fopen_s(&fp2, "RESULT4.txt", "r")) !=0) {
			printf("file open error!!\n");
			exit(EXIT_FAILURE);	/* エラーの場合は通常、異常終了する */
	}
		
		while(fgets(data, sizeof(data), fp2) != NULL){
			
		p.base = strstr(data, "base");
		p.base = strtok_s((p.base)+6, "\"", &ctx);
		printf("原型は%sです、", p.base);

		p.pos = strstr(data, "pos");
		p.pos = strtok_s((p.pos)+5, "\"", &ctx);
		printf("品詞は%sだ\n", p.pos);
		
 
		}
		fclose(fp2);
	
		return 0;	
}
RESULT4.txt

コード:

0	1	tok id="t0" cat="D" pos="DT" base="a" lexentry="[<D>]N" pred="det_arg1" type="noun_mod" arg1="c3"
2	8	tok id="t1" cat="ADJ" pos="JJ" base="broken" lexentry="[<ADJP>]N" pred="adj_arg1" type="noun_mod" arg1="c5"
9	13	tok id="t2" cat="N" pos="NN" base="bike" lexentry="[D<N.3sg>]" pred="noun_arg0"
14	16	tok id="t3" cat="V" pos="VBZ" base="be" lexentry="[NP<V.be.bse>VP.pas]_sctl-singular3rd_verb_rule" pred="aux_arg12" aux="be" arg1="c1" arg2="c8"
17	25	tok id="t4" cat="V" pos="VBN" base="repair" lexentry="[NP.nom<V.bse>NP.acc]-passive_verb_rule-drop_by_rule" pred="verb_arg12" tense="present" aspect="none" type="none" voice="passive" aux="minus" arg1="unk" arg2="c1"


Re: 入力ファイルから読み込むプログラムが途中で動作が停止してしまいます

Posted: 2012年12月28日(金) 23:35
by softya(ソフト屋)
まず、インデントを綺麗に揃えましょう。それだけでもバグが減ります。
それと、どんなエラーが出るのでしょうか? 
できるだけ正確に、ここに記載してください。

Re: 入力ファイルから読み込むプログラムが途中で動作が停止してしまいます

Posted: 2012年12月29日(土) 02:18
by かずま
blade さんが書きました:一行ずつステップインしてどこが悪いか見ていったところ
5回目のループが終わり、6回目のループ(dataにはNULLが入っているとき)に39行目のstrtok_sの内容がおかしいらしく、止まってしまうようでした。strtok_s自体は私がつくったわけではないですし、かつ動作が停止するまではちゃんと動いていたのでどこが悪くて
動作停止するかわかりません。
現段階で出力したい部分は出ているのであとはただプログラムが正常終了すればいいのですが、どうすれば正常終了するようになるでしょうか。
RESULT4.txt は 5行です。
5回ループを回った後、6回目の while () では、fgets() が NULL を返すので、
6回目のループに入ることなく正常終了します。

実は、RESULT4.txt は最後に空行があって 6行になっているんだと思います。
この掲示板のコードタグは、なぜか最後の空行は削除されて表示されるようです。

空行の場合、fgets() の結果、data[0] = '\n', data[1] = '\0' となります。
あるいは、data[0] = ' ', data[1] = '\0' かもしれませんが、data = NULL
とはなりません。

そして、35行目の strstr() で "base" が見つからず、p.base = NULL となります。
次の行の srtok_s() には NULL + 6 という参照してはいけないアドレスを渡す
のでここで、異常終了となります。

正常終了させるには、RESULT4.txt に余計な行を入れない。
または、strstr() や strtok_s() の結果の p.base や p.pos が NULL でないか
どうかをチェックし、そうだった場合は、そこで終了了させるか、continue; など
で、その行を無視して次の行の読み込みに行くかでしょう。

Re: 入力ファイルから読み込むプログラムが途中で動作が停止してしまいます

Posted: 2013年1月07日(月) 17:07
by blade
かずま さんが書きました: または、strstr() や strtok_s() の結果の p.base や p.pos が NULL でないか
どうかをチェックし、そうだった場合は、そこで終了了させるか、continue; など
で、その行を無視して次の行の読み込みに行くかでしょう。
35行と36行の間に
if(p.base==NULL)break;
を追加して正常終了を確認しました。
ありがとうございます。

また、41行以降に新たに

コード:

 while(fgets(buf, sizeof(buf), fp_v) != NULL) {      //fp_vはテキストファイル。ここは問題ないので割愛させていただきます。
                if(strncmp(p.base, buf, sizeof(p.base))==0){ //p.baseの内容とfp_vの1行ずつを比べて一致したならば
                    if(p.pos=="JJ" ){  //p.posの内容が"JJ"なら
                        .
                        .
                        .
                        break;
                    };
                };
            }
            rewind(fp_v);      
のような処理を加えたいのですがプログラムが

コード:

if(p.pos=="JJ" ){  //p.posの内容が"JJ"なら
の部分を認識してくれず、以下の...の処理を行わずプログラムが終了してしまいます。
デバックして確認したところ、p.posの中身は確かに"JJ"が入っているのですがifの中に入ってくれません。
おそらくこの条件分岐の表記が誤っていると思うのですが
何が誤っているのでしょうか。

Re: 入力ファイルから読み込むプログラムが途中で動作が停止してしまいます

Posted: 2013年1月07日(月) 17:33
by box
blade さんが書きました:

コード:

                    if(p.pos=="JJ" ){  //p.posの内容が"JJ"なら
このif文は、p.posというアドレス値と、メモリー中のどこかにある
文字列リテラル"JJ"のアドレス値とを比較しています。
おそらく両者は一致しないでしょう。
strcmp()を使って比較してください。

Re: 入力ファイルから読み込むプログラムが途中で動作が停止してしまいます

Posted: 2013年1月07日(月) 18:30
by blade
box さんが書きました:
blade さんが書きました:

コード:

                    if(p.pos=="JJ" ){  //p.posの内容が"JJ"なら
このif文は、p.posというアドレス値と、メモリー中のどこかにある
文字列リテラル"JJ"のアドレス値とを比較しています。
おそらく両者は一致しないでしょう。
strcmp()を使って比較してください。
posはポインタでしたね。
if(strcmp(p.pos, "JJ") == 0 )
を条件にしたらできました。

ありがとうございます。