最新閲覧日:

タブ又はカンマ、又はスペースで区切られた配列が書かれたテキストを、配列として読み込みたいのですが、どのようプログラムしたらいいのでしょうか。

つまりは、下の例みたいに書かれたテキストを、そのまま3行4列の配列として読み込みたいのです。
例)
1222,2337,593,3488
2338,384,34,2229
534,23333,234,444

ちなみに、私は下のような1列で書かれたものなら読み込めます。
例)
123
343
23
253

A 回答 (6件)

既に解決なさってるようですが一応・・・


No.2の補足に対する回答です。
>こんなかんじでいいでしょうか?

 いいと思いますよ。


>列が非常に長いときは、strtokを使うしかないのでしょうか?

 あまり長いと、sscanfで指定するフォーマットが長くなってしまうので、
よくないですね。("%d,%d,%d,%d,・・・"という感じになってしまうので)
 strtokの方がスマートに書けると思います。
(No.3の補足に書いてあるとおりです)
    • good
    • 0

方法としては、No.4の回答でほとんど問題はないと思います。


実際にコードを書く場合には、ループの回数=配列の大きさを #define で定義して
使用すると、間違いが少なくなるでしょう。
また、fscanfではなく、fgetsとstrtokの組合せを勧めたのもミスを防ぎ、配列の
大きさに柔軟に対応させるためです。
たとえば、読み込むファイルをExcelで作成し、CSV形式で保存すれば、上の例に
あるファイルを作成できますが、行末にもカンマが付くことがあります。
例)
1222,2337,593,3488,
fscanfを使用すると、書き方によっては最後のカンマのために、2行目以降の
データが全てずれる可能性がありますが、No4の回答の例では、カンマがあっても
無くても正確に読み込めます。
どのようなフォーマットにしろ、テキスト(ascii)形式のファイルは、1行ずつ
fgetsで読み込んでから処理する事をお勧めします。
    • good
    • 0

# No.3お礼より


こんな感じでどうでしょうか?

for (i = 0; i < 3; i++) {
  a[i][0] = atoi( strtok( fgets(str,50,fp),"," ) );
  for (j = 1; j < 4; j++)
    a[i][j] = atoi( strtok( NULL,"," ) );
}

# 括弧の対応に要注意!
# データを間違えて読むことより、不正な配列アクセスをする方が危険なので、確実に3行4列を超えないようにループを組む必要があります。
  ↑非常に大事!

またfscanfループの1つの解として、こんなのもあります。が、、、

for (i = 0; i < 3*4; i++)
  fscanf(fp, "%d,", *a + i);

これは必ずしも「よいプログラム」ではありません。
なぜなら「理解しにくい」からです(笑)

# 理解しやすいコーディングというのはとても大切なことなのですが、プロでもできてない人が大勢いるんです。
# こういうことをやる人に限って、自分のコードは素晴らしいと思ってる人が多くって・・・
# 素直なプログラムを書けるように頑張りましょう。

leaz愚痴モードでした。
    • good
    • 0

# No.1の補足に対して


strtokは癖の強い関数なので、最初は悩みますよね。
この関数は内部に参照ポインタを持っていて、前回どこまで調べたかを覚えていてくれるのです。
2回目以降調べる場合は、第1引数にNULLを指定します。
最後まで調べ尽くすとNULLを返します。まぁ今回は数が分かっているので使いませんが。

以上を参考に改良をしてみてください。

# ただ、このような単純なフォーマットのテキストファイルならば、普通はfscanfのループで十分だと思いますが。

この回答への補足

fscanfの方法も分かりました。どうもありがとうございます。
単純なフォーマットならfscanfかsscanfが便利で、複雑なフォーマットや列が長い場合は、strtokを使えばいいことが分かりました。

補足日時:2001/05/31 21:58
    • good
    • 0
この回答へのお礼

ありがとうございます。
なるほど、下のように書けばうまくいきました。

for(i=0;i<3;i++)
{
fgets(str,50,fp);
j=0;
a[i][j]=atoi(strtok(str,","));
while(1)
{
j++;
if((a[i][j]=atoi(strtok(NULL,",")))==NULL)break;
}
}

この書き方でうまくいきますが、もっと効率のいい書き方ないでしょうか。
また、fscanfのループでうまくいくってのが分かりません。毎回先頭の数字を読み込みそうな気がしますが。

お礼日時:2001/05/31 21:28

1列のデータは4つの数字がカンマで区切られたものですので、


 sscanf
を用いればできると思います。

1列のデータを読み込んで、sscanfで数字を取り出して・・・。

と、ここまでにしておきます。
頑張って下さいね。
    • good
    • 0
この回答へのお礼

ありがとうございます。下のように書いたところ、うまくいきました。
こんなかんじでいいでしょうか。
列が非常に長いときは、strtokを使うしかないのでしょうか?

for(i=0;i<3;i++)
{
fgets(str,50,fp);
sscanf(str,"%d,%d,%d,%d",&a[i][0],&a[i][1],&a[i][2],&a[i][3]);
}

お礼日時:2001/05/31 21:48

こんにちは。


ご自身の勉強のために、あえてヒントだけを書きますと、
for
fgets
strtok
を使用すればできます。ヘルプを見て下さい。
strtokの使い方がポイントです。
これで分からなければ、再度投稿します。

この回答への補足

ありがとうございました。とりあえず、こうやってみました。でも無理でした。
int a[3][4];
char str[50];
FILE *fp;

if((fp=fopen("test","r"))==NULL)exit(0);

for(i=0;i<3;i++)
{
fgets(str,50,fp);
for (j=0;j<4;j++)
{
a[i][j]=atoi(strtok(str,","));
}
}

上の例で試したところ、配列aは以下のようになってしまいました。
1222,1222,1222,1222
2338,2338,2338,2338
534,534,534,534

strtokが、forループの中で毎回初めの数字を読み込んでいます。

補足日時:2001/05/31 20:21
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード


このカテゴリの人気Q&Aランキング

おすすめ情報

カテゴリ