掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.30141

strtokでのファイル分解について
投稿者---喜太郎(2007/05/17 00:06:15)


ファイル(例)の中身のデータ↓
―――――ココから―――――
23,144,53,-12,

-23,4,

455,65,
567,-543,


32,
―――――ココまで―――――

という、数字と改行がランダム、そして、1つの数字ごとに","で区切ってるファイルがあります。
これをstrtokを使ってファイルの中身の数値を取得したいと思いました。

int suji[100],i=0,cnt;
char str[256];

while(fgets(str,256,fp) != NULL)
{
suji[i] = atoi(strtok(str,","));
i++;

while(strtok(NULL,",") != NULL)
{
suji[i] = atoi(strtok(NULL,","));
i++;
}
}

cnt=i;
for(i=0;i<cnt;i++)printf("%d\n",suji[i]);

私の考えではこれでファイルの数値を取り出し、
表示できると思ったんですが、期待通りの値が得られません。

この処理がうまくいかず行き詰っています。
どう修整したらよいか、もっと簡単な方法がある、など
アドバイスください。よろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:strtokでのファイル分解について 30142 PSB 2007/05/17 00:14:08
<子記事> Re:strtokでのファイル分解について 30143 Blue 2007/05/17 00:15:17
<子記事> Re:strtokでのファイル分解について 30145 επιστημη 2007/05/17 00:20:08


No.30142

Re:strtokでのファイル分解について
投稿者---PSB(2007/05/17 00:14:08)


>while(strtok(NULL,",") != NULL)

ここでstorokの戻り値が捨てられてます。



この投稿にコメントする

削除パスワード

No.30143

Re:strtokでのファイル分解について
投稿者---Blue(2007/05/17 00:15:17)


データの存在チェックをしていますかね?
strtokのも度地理がNULLかチェックすべきでしょう。
NULLであれば次の行へ。NULLでなければatoiで配列に入れる。

>strtok(str,",")
は改行文字も入れておいたほうがいいでしょう。

strtok(str, ",\n");


それと、ソースコードを張るときはHTML変換ツールをつかって、見やすくしてください。
また、
>期待通りの値が得られません。
とだけ記述せず、どのような期待をしていて、逆にどうなるのか等
具体的に記述しましょう。


>ソースの添付は「HTML変換ツール」で字下げします。
>環境(OSとコンパイラ)や症状は具体的に詳しく書きます。


この投稿にコメントする

削除パスワード

No.30146

Re:strtokでのファイル分解について
投稿者---Blue(2007/05/17 00:20:54)


>strtokのも度地理がNULLかチェックすべきでしょう。
訂正。
戻り値ですね。

それと、気づかなかったのですがPSBさんのおっしゃるとおり、
whileの条件がおかしいですね。
const char* p;

p = strtok(str,",\n");
if (p != NULL)
{
    /* 省略 */

    while(1)
    {
        p = strtok(NULL, ",\n");
        if (p == NULL) break;
        /* 省略 */
    }
}


としたほうがいいでしょう。


この投稿にコメントする

削除パスワード

No.30145

Re:strtokでのファイル分解について
投稿者---επιστημη(2007/05/17 00:20:08)
http://blogs.wankuma.com/episteme/


>私の考えではこれでファイルの数値を取り出し、
>表示できると思ったんですが、期待通りの値が得られません。

どんな値が得られるのですか?
strtok で切り出した文字列を printf して調べましたか?

おそらくは '\n' に atoi かけてヘンな値になってるのでしょう。
fgets は末尾の改行を読み飛ばしませんから。



この投稿にコメントする

削除パスワード

No.30147

Re:strtokでのファイル分解について
投稿者---喜太郎(2007/05/17 13:57:42)


皆さんありがとうございます。
書き直しました。


ファイル(例)の中身のデータ↓
―――――ココから―――――
23,144,53,-12,
-23,4,

455,65,
567,-543,


32,
―――――ココまで―――――
ファイルがこれだったとしたら

23
144
53
-12
-23
4
455
65
567
-543
32

という風に表示させたいと思いました。



int suji[100],i=0,cnt;
char str[256];

while(fgets(str,256,fp) != NULL)
{
    printf("%s\n",str); //確認
    suji[i] = atoi(strtok(str,",\n"));
    printf("%d\n",suji[i]) //確認
    if(suji[i] != NULL)
    {
        i++;
        while(1)
        {
            suji[i] = atoi( strtok(NULL,",\n") );
            printf("%d\n",suji[i]); //確認
            if(suji[i] == NULL)break;
            i++;
        }
    }
}

cnt=i;
for(i=0;i<cnt;i++)printf("%d\n",suji[i]);



これを実行すると

23,144,53,-12,

23
144
53
-12

と、なってここで終了してしまいます。
(途中で実行が途切れてしまいます。)

行読み込みが次の行に進めてないんだと思いますが、
どう修正すればいいのでしょうか?



この投稿にコメントする

削除パスワード

No.30148

Re:strtokでのファイル分解について
投稿者---acid(2007/05/17 14:48:30)


おそらく終了するのではなくて、コアダンプ(Segmentation fault)しているのではないでしょうか。
(borlandならダイアログが出てきて終わる)

問題はstrtokとatoiの組み合わせです。
まずstrtokは文字が切り取れない時はNULLを返します。
しかしatoiは引数にNULLを渡すと、強制終了してしまいます。
ですので、atoi(strtok(str,",\n"));はマズい。(2箇所とも)

さらに終了条件をsuji[i] == NULLとしてますが、sujiはint型です。
int型にはNULLは入りませんので、ここも間違いです。

終了条件と、atoiの使い方を考えてみてください。
同じ処理の入れ子になってるあたり、若干効率悪いソースですが、
もう少しです。



この投稿にコメントする

削除パスワード

No.30149

Re:strtokでのファイル分解について
投稿者---喜太郎(2007/05/17 15:10:40)


返信ありがとうございます。

>おそらく終了するのではなくて、コアダンプ(Segmentation fault)しているのではないでしょうか。
>(borlandならダイアログが出てきて終わる)

そのとおりです。

struct s{
    int suji;
    char str[6];
}data[100];

int i=0;
char moji[256];

    while(fgets(moji,256,fp) != NULL)
    {
        printf("%s\n",moji);//確認

        strcpy( data[i].str, strtok(moji,",\n"));
        printf("%s\n", data[i].str);//確認
        if (data[i].str != NULL)
        {
            i++;
            while(1)
            {
                    strcpy ( data[i].str, strtok(NULL, ",\n") ) ;
                printf("%s\n",data[i].str);//確認
                    if( data[i].str == NULL )break;
                i++;
            }
        }
    }

cnt = i;

for(i=0;i<cnt;i++)deta[i].suji = atoi( data[i].str );   //数値に変換
for(i=0;i<cnt;i++)printf("%d\n",data[i].suji);



こう直してみたんですが、
上で書いたプログラムと同じようになって、コアダンプしてしまいます。

質問ばかりで申し訳ないのですが、
どうやったらいいんでしょうか?



この投稿にコメントする

削除パスワード

No.30150

Re:strtokでのファイル分解について
投稿者---acid(2007/05/17 16:42:44)


strcpy ( data[i].str, strtok(NULL, ",\n") ) ;ですね。

やってみれば分かると思いますが、strcpyの第二引数にNULLを渡すと、
コアダンプします。

ポインタってもう習いました?
strtokを使う段階なら、ポインタはもう習っていると思います。
strtokの戻り値を、ポインタで受け取るようにしましょう。
で、NULL判定をして、NULLじゃなかったら配列にコピー。
NULLだったらbreak。



この投稿にコメントする

削除パスワード

No.30167

Re:strtokでのファイル分解について
投稿者---金魚ちゃん(2007/05/22 17:02:42)


♪模範解答です。

// 宣言部
char str[ 256 ];
int suji[ 100 ];
int i, max = 0;

// 読み込み部
while ( fgets(str,sizeof(str),fp) != NULL ){
 for ( token = strtok(str,",\r\n") ; token != NULL ; token = strtok(NULL,",\r\n") ){
  if ( max >= 100 ){ ←安全対策
   break;
  }
  suji[ max++ ] = atoi( token );
 }
}

// 表示部
for ( i = 0 ; i < max ; i++ ){
 printf( "%d\n", suji[i] );
}



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧