プロが教えるわが家の防犯対策術!

C言語で、ファイルを読み込んで数字と名前に分けて配列に格納に関する質問です!
ファイルを開いた後でエラーとなるのですが、何が足りないのでしょうか?

ファイル内容
20
田中
10
鈴木

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

int main(int argc,char *argv[])
{
FILE *fp;
char str[256];
char *tp;
int k,i=0;
int num[10];
char na[10][20];

fp=fopen(argv[1],"r");
if(fp==NULL){
printf("ファイルを開けません\n");
return 1;
}else{
printf("開けた\n");
}

while(fgets(str,sizeof str,fp)!=NULL){

tp=strtok(str," ");
num[i]=atoi(tp);
tp=strtok(NULL," ");
strcpy(na[i],tp);
i++;
}
printf("%d\n%s\n",num[0],na[0]);
printf("%d\n%s\n",num[1],na[1]);

fclose(fp);
return 0;
}

A 回答 (3件)

こんにちは。



ご提示の「入力データファイル」のフォーマット(形式)と、プログラム上の
データ読込み処理の想定フォーマットに、くい違いがあるようです。

入力データファイルのフォーマットでは、
 1行につき1データとし、2行で1組分の以下のデータ形式
   1行目: 数値 ─┬─ 1組目(1レコード目)
   2行目: 名前 ─┘
   3行目: 数値 ─┬─ 2組目(2レコード目)
   4行目: 名前 ─┘
     :    :
となっているのに対し、プログラム上のデータ読込み処理では、
   1行目: 数値 [スペース] 名前  ・・・ 1組目(1レコード目)
   2行目: 数値 [スペース] 名前  ・・・ 2組目(2レコード目)
     :    :         :
という形式を想定したものになってしまっているようです。

fgets関数では、改行文字を区切りとしてファイル上のデータ(文字列)を
指定されたバッファに読み込みます。
※その際、読込みバッファの終端に改行文字も含まれます。

ご提示のプログラムでは、ファイルから1行読込む度に、スペース区切りで
【数値】と【名前】の2データ分を読込むようになっていますが、実際の読み
込みバッファには、1個のデータ(数値or名前)しか格納されていないので、
2回目のstrtok関数では読込むデータがないため、戻り値 tp には NULL値
が返されているはずです。

その状態(コピー元ポインタ=NULL)で、strcpy関数により文字列コピーを
実行しようとしているため、例外エラーが発生しているものと思われます。

上記の問題を回避するためには、
 【1】ファイルデータフォーマットを以下の形式に変更する。
   1行目: 数値 [スペース] 名前  ・・・ 1組目(1レコード目)
   2行目: 数値 [スペース] 名前  ・・・ 2組目(2レコード目)
     :    :         :
または、
 【2】ファイル読み込み処理を、データファイルの形式(1行=1データ)に
   合わせて変更する。
 ※この場合、2行毎に、1行目で【数値】の読み込み、2行目で【名前】の
  読み込みを行う必要があります。
の何れかの処置を行う必要があると思います。

また、プログラム上のデータ格納用の配列の確保要素数は、10個が上限
となっていますので、仮にデータファイル上のデータ数が10個を超えていた
場合は、読み込み途中で配列の確保分をオーバーしてしまう可能性があり
ます。
↑この対策(10個分読込んだらループを抜けるなど)も採っておく必要がある
と思います。

あと、細かい事ですが、【名前】格納用の文字列バッファのサイズは、20文字
(終端コード'\0'も含めて)となっていますが、仮にデータファイル上の【名前】が
20文字以上だった場合は、文字列コピー時にバッファの確保分を超えてコピー
される可能性があります。
↑この対策(コピー文字数を上限20文字とするなど)も採っておく必要があると
思います。

参考までに(なるかどうか判りませんが)、以上を踏まえて、データファイルの
フォーマットが、前述の【1】のパターンだったものとして、ご提示のプログラム
を改造したソースを下記に掲載しました。(※下記リンク先参照)
※宜しければ試してみて下さい。

■改造版ソース
http://ideone.com/3xAR9

■改造版プログラムでの実行例
<入力データファイル>
20 田中
10 鈴木
30 佐藤
40 鈴木
50 伊藤
60 小林
70 藤田
80 渡部
90 桜井
100 安藤
99 松本

<実行結果>
開けた
レコード件数=10
No= 1: 20    田中
No= 2: 10    鈴木
No= 3: 30    佐藤
No= 4: 40    鈴木
No= 5: 50    伊藤
No= 6: 60    小林
No= 7: 70    藤田
No= 8: 80    渡部
No= 9: 90    桜井
No=10: 100   安藤

以上です。
    • good
    • 0
この回答へのお礼

詳細まで丁寧に説明していただきありがとうございます!
学びだしたばかりで、すぐには理解できないので助かりました!^^

お礼日時:2010/07/21 19:00

 


 何故、strtok?
 
    • good
    • 0

「strtok の返り値をちょっと調べてみよう」とは, これっぽっちも思わなかったと?

    • good
    • 0

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