ファイル読み込みについて

[戻る]
初心者 2002/12/02(月) 15:47:49
あるテキストファイルをCで呼び出そうと思っているのですが
1行ごとに行数指定をした呼び出し方法が分かりません。
gets関数では最初の行から順番に取ってくるので
私のやりたいこととは違う気がします。
行を指定するには自作しなくてはならないのでしょうか?

それとGets関数ですが呼び出すたびに次の行、次の行・・・・
となっていますが、これはなんだか不思議な感じがします。
なぜ呼び出すごとに違う処理をするのでしょうか?
ご存知の方がいましたら教えてください。

よろしくお願い致します。

tib 2002/12/02(月) 15:59:40
>あるテキストファイルをCで呼び出そうと思っているのですが
>1行ごとに行数指定をした呼び出し方法が分かりません。
自作してください。

とりあえずfseek()とfor文とfgets()だけあればできそうですが、任意の行へのアクセス
が多く、よほどファイルが大きくない限りは一度ファイルをメモリに展開してしまった方
がラクでしょう。


>それとGets関数ですが呼び出すたびに次の行、次の行・・・・
>となっていますが、これはなんだか不思議な感じがします。
>なぜ呼び出すごとに違う処理をするのでしょうか?
fileポインタが「どこまで読み込んだか」を覚えているから。fgets()は「fileポインタ
が指しているところから行の終わりまでを読み込む」という動作を毎回繰り返しているに
過ぎません。

アイススケーター 2002/12/02(月) 19:22:29
処理するデータ量が少なければ、一度配列に読み込んでから処理する。
または、ListBoxにデータを読み込んでから処理する。

等々、いろいろなやり方がありますよ。

初心者 2002/12/02(月) 20:20:04
ご回答ありがとうございます。
できました。

void FileRead_Line(int line,FILE *fp,char *buf)
{
  for(int i = 0; i < line ;i++)
  {
    buf = fgets(buf,512,fp);
  }
}

もう1つお聞きしたいのですが
ファイルがカンマ区切りで保存されています。
これをばらばらにして取得できるような関数は無いでしょうか?
自作しかないでしょうか?

///////////条件///////
◆ファイルの中身(aaa.txt)
123,34,2321,2342,5
2134,234,4,5,4
[EOF]

◆fgetBaraのような関数が欲しい。
int aaa[10];
fgetBara(fp,10,aaa);

◆期待する結果
aaa[0]--123,aaa[1]---34,,,,aaa[9]---4

/////////////////
ちなみにデーター量は半端ではないためファイルに一旦書き込み
後で処理をするという方式になっているためメモリには入りきりません。
構造体配列1400がそれぞれ120の数値データを出力したかったので
最初120のINT型配列を構造体メンバーに入れました。
結果、エラーで起動しませんでした。

初心者 2002/12/02(月) 20:23:46
要は与えられた文字列を指定区切り文字で分割して
なおかつINT型で返すような都合のいい関数は無いでしょうか?

int aaa[10]
bara2(10,",",aaa);

上の例の方が良いかもしれませんね。
aaa配列を","区切りで分割して10メンバーを返す

お願いします。

YuO [E-Mail] 2002/12/02(月) 20:33:12
strtokとstrtolでできますが。

tib 2002/12/02(月) 21:18:10
学校の課題かなんかだったんですか?
どこまで自分で考えた上で質問していますか?
まず自分が、「ファイルから文字列を読み込み、指定の文字で分割し、数値配列に格納し
なさい」と言われたときに何をどうするか見えていますか?

wood 2002/12/02(月) 23:15:24
>初心者 2002/12/02(月) 20:20:04>YuO [E-Mail] 2002/12/02(月) 20:33:12
をあわせて考えさせていただくとこんな感じなんですかね

void FileRead_Line(int line,FILE *fp,char *buf)
{
char token[10];
int  atai[10]
int  hairetu;
  for(int i = 0; i < line ;i++)
  {
    buf = fgets(buf,512,fp);
    if(buf != NULL ) {
      strtok(buf,',');
      hairetu = 0;
      while( token != NULL )
        { atai[hairetu] = atoi(token) * -1;  }
    }
  }
}

>aaa[0]--123,aaa[1]---34,,,,aaa[9]---4
ここで行っているマイナスの意味よく分かりませんけど

>初心者 2002/12/02(月) 20:23:46
これよく意味が伝わらないのですけど

>int aaa[10]
>bara2(10,",",aaa);
>上の例の方が良いかもしれませんね。
>aaa配列を","区切りで分割して10メンバーを返す

これって本当は
char xxx[255];
int  aaa[10];

xxx = "123,456,55,6,7,8999"
aaa = bara2(10,",",xxx);

のようなこといいたいんでしょうか
また期待する結果と言うのは文字列5バイト右詰を期待してますか?


なお、タイトルは「ファイル読み込みについて」ですよね
文字列変換または抽出についてではないですよね

もうひとつ、もうひとつ、と質問増やしていったらキリがないので
>初心者 2002/12/02(月) 20:20:04
>ご回答ありがとうございます。
>できました。
出来たんだったらこのスレッド一度クローズして新たに質問あげるべきでは
ないでしょうか?

その他
「呼び出す」と「読み出す」の意味全然違いますけど

>これはなんだか不思議な感じがします。
関数がどんな処理をしてくれているのか理解しないで
使っている現われです
何かお手持ちの参考書持ってますか
コンパイラの言語ヘルプなど見てますか

ただ他人の言う関数を使うのではなく
良く理解してから使うようにしないと
身につきませんよ
デバック作業はキチンと出来ていますか

言語ヘルプの解説の理解や机上シュミレーションできれば
「不思議な感じ」なんて発言できないと思いますけど・・・

自分を「初心者」と言うのであれば「言語解説」を繰り返しよく読みこみましょう
基本は「言語解説」を良く見ておくこと、必要とする関数も見つけやすく
なるとおもいますよ

wood 2002/12/02(月) 23:18:18
>>aaa[0]--123,aaa[1]---34,,,,aaa[9]---4
>ここで行っているマイナスの意味よく分かりませんけど
日本語間違ってますね
訂正
ここで言っているマイナスの意味よく分かりませんけど

初心者 2002/12/03(火) 10:22:24
[[解決]]
やはり自作しかないのですね。
strtokは当然知っていましたがすでに用意されている関数があるなら
そちらを使いたいと思って質問しました。
また、以後は同系列の質問も新たにスレッドを建てさせていただきます。

////////
とりあえずYuOさんの関数を参考にwoodさんのソースを改良して自作してみました。
(ソースの方は"文法"と"アルゴリズム"と"関数の使い方"が間違っていたので
ほとんど作り変えましたが・・・)
どうもありがとうございました。
尚好みの問題かもしれませんがリターンではなくアドレスを渡して内部で変換する
方法をとりました。
また、トークンはカンマで固定のため、今回は引数として渡しませんでした。

//ファイルと行数を指定すると整数の値を設定する関数
void FileRead_Line(int line,FILE *fp,int *kekka)
{
    char *token;
    char buf[512]; //行読み込み

    for(int i = 0; i < line ;i++){
        fgets(buf,512,fp);
        if(buf != NULL ) {
            token = strtok(buf,","); //最初のトークン
            for(int s = 0 ;token != NULL; s++)
            {
                *(kekka+s) = atoi(token);
                token = strtok(NULL,","); //次のトークン
            }
        }
    }
}

RAPT 2002/12/03(火) 10:41:04
疑問列挙
・ファイルの1行の長さは512バイト未満固定なのか
・line行に達するまで、毎回読み込んだデータを解析する必要はあるのか
・line行にデータがないとき、*kekkaの中身は不定になるが、いいのか

Windows98/VC++6.0std/SDK-may2002/ATL3.0/WTL7.0

初心者 2002/12/03(火) 11:03:37
[[解決]]
その通りですね、5分ほどで作ったやつなので形だけになってしまいました。
このまま導入するつもりは無いのですが今はちょっと無理なので
今週中には作り変えようと思います。

作り変えたら報告に来ます。

ASR 2002/12/03(火) 11:58:58
すみません。
細かい指摘で申し訳ないんですが、前から気になってたので…

バクを「デバック」するのではなく、バグ(bug)を「デバッグ(debug)」
するのですよね^^;
あと「シミュ」レーション…

それでは失礼します。

初心者 2002/12/03(火) 13:25:34
あはは
じゃあついでなんで何方か私の間違いと分からなかったところを教えてもらえますか?

>「呼び出す」と「読み出す」の意味全然違いますけど
読み出すはRead、呼び出すはCall
私は関数を「Callするたびに」の意味で使ってるんですけど何が違うでしょうか?

>ここで言っているマイナス
マイナスじゃありません。
aaa[0]に数値の123
aaa[1]に数値の34
,,,,(aaa[2]〜aaa[8]略)
aaa[9]に数値の4
が設定されるということを言いたかったのです。
分かりにくくて申し訳ありませんでした。

>また期待する結果と言うのは文字列5バイト右詰を期待してますか?
期待する結果は

>要は与えられた文字列を指定区切り文字で分割して
>なおかつINT型で返すような都合のいい関数
なのですけど「"文字列"5バイト右詰」が良く分かりません。INT型なのでしょうか?
文字列??

wood 2002/12/03(火) 23:39:51
>あるテキストファイルをCで呼び出そうと思っているのですが
私はテキストファイルを読み込んで何らかの処理をする関数を
呼び出す(call)するのだと解釈できなかったもので
大変失礼しました

>///////////条件///////
>◆ファイルの中身(aaa.txt)
>123,34,2321,2342,5
>2134,234,4,5,4
>[EOF]

>◆fgetBaraのような関数が欲しい。
>int aaa[10];
>fgetBara(fp,10,aaa);

>◆期待する結果
>aaa[0]--123,aaa[1]---34,,,,aaa[9]---4

私個人的に
”123,34,2321,2342,5”
”2134,234,4,5,4”
のようにクオーティションで囲んでもらえば文字列と解釈できたんだと
思いますけど、ま!最初から「テキストファイル」といっているんだから
勝手に変な解釈している私が悪いんでしょうけど

aaa[0]=123
aaa[1]=34
  ・
  ・
  ・
aaa[9]=4

マイナスと解釈し文章の桁埋め代替文字として使用していたんですね

データ型 INT と 言うのはシステムに依存してサイズが決められる
のですが一例では 「-32,768 から 32,767」こんな範囲のデータを
あらわすことが出来るはずなのでマイナスと解釈しました

だからわざわざ * −1 なんて 下記のようなコード書きました
     { atai[hairetu] = atoi(token) * -1;  }


>ASR 2002/12/03(火) 11:58:58
>あと「シミュ」レーション…

質問者本人の「初心者 さん」に何が回答になっているのか分かりませんけど

pie 2002/12/04(水) 01:19:29
間違いを指摘されたら礼を言うものです。

RAPT 2002/12/04(水) 01:44:26
こんばんは、RAPTです。

何だか、言葉について議論されているので、突っ込まれないうちに修正しとこう…

> line行にデータがないとき、*kekkaの中身は不定になるが
「不定になるが」→「不変だが」

あと、
> 形だけになってしまいました
の件、了解です。安心しました。

Windows98/VC++6.0std/SDK-may2002/ATL3.0/WTL7.0

トスポ 2002/12/04(水) 01:45:59
名前の割に態度は初心者じゃないように見える。
気をつけた方がいいね。

古いスレッドには追加発言できません。