- ベストアンサー
strtok関数の使い方 その2
http://oshiete1.goo.ne.jp/kotaeru.php3?q=2376843 で、質問させて頂いた者です。 先日は大変にお世話になりました。 先日の質問の続きという感じなんですが… ------------------ 「ex」ファイルのデータ 41 100000 42 110000 43 120000 --------- これらのデータを kihokyu[1].tosi=41 kihokyu[1].kan=100000 kihokyu[2].tosi=42 kihokyu[2].kan=110000 という感じで格納したいのです。 ------------------------ お陰様で、kihokyu[].tosiの方は 格納する事が出来ました。 ただ、 kihokyu[].kanの方が 格納することが出来ません。 「1245015」という値が 格納されてしまいます。 この原因は strtokの第一引数にNULL を渡したときの動作を 理解していないのかも知れません。 ------------------------ バッファにいったん蓄えて >buff = "41 100000\n" 41を構造体「kihokyu[i].tosi」に格納 >kihokyu[i].tosi = atoi(strtok(buff , " ")); ここが上手く行かない 10000を構造体「kihokyu[i].kan」に格納したつもり >kihokyu[i].kan = atoi(strtok(NULL , " \n")); 私の理解では、説明文の方に >2回目以降の呼び出しでは s1 に NULL を指定します と、ありましたので この時点で、NULL変数には 「10000」が蓄えられていると 理解しています。 この認識は間違っているのでしょうか? ご教示して頂けたら幸いです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct nentbl_ { int tosi; int kan; } nentbl; int main(void){ char buff[16]; FILE *fp; int i=0; nentbl kihokyu[50]; fp = fopen("ex.fil","r"); while(fgets(buff,sizeof buff,fp) != NULL){ if ( i == 50 ) break; kihokyu[i].tosi = atoi(strtok(buff , " ")); kihokyu[i].kan = atoi(strtok(NULL , " \n")); printf("toshi:%d\n",kihokyu[i].tosi); printf("kan:%d\n",kihokyu[i].kan); i++; } fclose(fp); return 0; } ---------------------------------------------------------------- を試してみてどうなるか、教えていただけますか? あと、コンパイラは何をお使いでしょうか?
その他の回答 (2)
- chie65536
- ベストアンサー率41% (2512/6032)
char buff[16]; buff = "41 100000\n"; kihokyu[i].tosi = atoi(strtok(buff , " ")); 上記のようにstrtokにリテラルな文字列へのポインタを渡してはいけません。 上記の処理は kihokyu[i].tosi = atoi(strtok("41 100000\n" , " ")); と同じで、これを実行するとプログラムメモリを壊します。 この後は、メモリが壊れているので何が起きるか判りません。変な所に変な物が格納されたり、暴走したり、フリーズしたりするでしょう。 buff = "41 100000\n"; は「buffに文字列を格納せず、16バイトの作業用メモリを指していたbuffのアドレスを忘れ去り、新たにbuffが文字列定数"41 100000\n"の内部アドレスを指すようにする」って事です。 buffの中に文字列をセットしたいなら char buff[16]; strcpy(buff,"41 100000\n"); kihokyu[i].tosi = atoi(strtok(buff , " ")); と書かないとなりません。 「ポインタの変更」と「文字列のコピー」は見た目の実行結果は同じですが意味が全然違います。
補足
ご返事有り難うございました。 お陰様で正常に出力されました。 ただ、幾つか質問したいことがありましたので お手数かとは思いますが ご教示して頂けたら幸いです。 1. >「buffに文字列を格納せず、16バイトの作業用メモリを指していたbuffのアドレスを >忘れ去り、新たにbuffが文字列定数"41 100000\n"の内部アドレスを指すようにする」 >って事です。 ということは、 buff = "41 100000\n"; とした場合は、 buffに「41 100000\n」というアドレスが 格納されてしまうと理解して宜しいのでしょうか? 2.ファイルのデータから入力をする場合、 以下のようにしないといけないのでしょうか? ------------ 二つのバッファ変数を用意して、 char buff[16]; char buff2[16]; FILE *fp; ・ ・ ・ いったん仮のバッファに入れて、 while(fgets(buff2,sizeof buff2,fp) != NULL){ それから本当のバッファに入れる strcpy(buff , buff2); のような感じで 処理をするのでしょうか? 3.もう一つ分からないのは NO,3で回答して頂いた方の方法でも 正常に処理することが出来たのですが strcpyを使用した方が良いのでしょうか? 申し訳ありませんが よろしくお願いします。
- Tacosan
- ベストアンサー率23% (3656/15482)
その例だと, 期待通りの結果になると思うんですが, 違いますか? 「どのようなデータに対して」 「どのような結果を期待して」 「どのような (期待に反する) 結果が得られたのか」 を挙げてもらえませんか?
お礼
ご返事有り難うございました。 今日実行したところ 期待通りの結果が得られました。 どうしてだろう…
お礼
ご回答して頂いたプログラムを 試してみました。 正常に出力されました。 ただ分からないのは 私も同じようなプログラムだと思うのですが どこがおかしいのか 分からないのです。 それで今日、 私のプログラムを実行してみたところ 正常に出力されるのです。 ちょこまかといじっていたので その辺りが原因なのかとは思いますが ハッキリとしないところが気持ち悪いです。 >あと、コンパイラは何をお使いでしょうか? borlandのbcc32.exe というのを使用しています。