- ベストアンサー
構造体とfscanfでファイルから文字列を読み込む方法
- ファイルをfscanfを使って文字列を構造体に格納して読み込む方法について知りたいです。
- ソースコードの記述方法がわからず困っています。どのようにしたら読み込むことができるでしょうか?
- 例えば、yasa.txtというファイルに以下のようなデータが入っていて、それを構造体に格納したいです。オレンジ ● みかん ● いちご × もも ● ぶどう × キウイ ●
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>//2回目の呼び出し方法での記述の仕方がわからない deta2はポインタ変数しか持っていませんのでmalloc()などで必要な領域を確保してから、 その場所(ポインタが指している先)に読み込んで下さい。 問題は「確保するべき領域のサイズが判らない」ということですが…。 char ReadTemp1[100],ReadTemp2[100]; とかを用意して、 fscanf( fp, "%s %s",ReadTemp1,ReadTemp2 ); deta2.name = malloc(strlen(ReadTemp1)+1); //'\0'の分が必要 strcpy(deta2.name, ReadTemp1); deta2.mb = malloc(strlen(ReadTemp2)+1); //'\0'の分が必要 strcpy(deta2.mb, ReadTemp1); という感じで入れます。 # 使い終わった後の開放を忘れずに。 ちなみにdeta2は1個分子かありませんから、続きのデータは読めません。 detaと同じように、その場で使うだけならその都度開放して下さい。 deta3は、ポインタの配列が6個分ありますからそれぞれに領域確保して読み込ませておくこともできるでしょう。 やり方自体はdata2の時のように作業用領域に読み込んでメモリ確保して、コピーして…の繰り返しです。
その他の回答 (5)
- wormhole
- ベストアンサー率28% (1626/5665)
>そのため、サーバー管理会社は使いません。迷惑をかける可能性が少しでもあるから そのため多額な賠償請求もされません。 ちょっと考えが甘いです。 もし、あなたが運用されるサーバーが踏み台にされ他者に迷惑をかけた場合、加害者扱いになる可能性がありますので迷惑をかけたところからの賠償請求はありえます。
お礼
その話は聞いてますよ そのためアタック対策は万全にしようって話ですね もちろん忘れてはいませんよ 今はまだ少ししか対策していませんがこれからゆっくり対策していきますよ どんなものでも一気に全部できるわけではないので、少しづつ作っていきます
- kmee
- ベストアンサー率55% (1857/3366)
> あふれたデータ云々はよくわからないようなことになりそうなら、プログラムとして問題ないなら放置。 > バグがでてきたらその時処理するでしょうね。 こんな考えでC言語、特にポインタ絡みの操作を使ってほしくないです。 御自身のPCが壊れるだけなら自業自得で済みますが、これでCGIを作ろうとしてますよね? 被害が全世界に及ぶ可能性とか、サーバー管理社から多額の賠償請求される可能性とか、考えたことありますか?
お礼
ちなみにこうは言いますが、決していい加減なものを作るつもりはありませんよ 何せ私が作る作品を愛していますからね。 例え他の人が私のやり方では愛していないように見えるのでしたら、それでもかまいませんよ ですが他の人がなんと言おうとも私は自分の作品を愛してます。 確かに私はバグがでるまで待っているところはありますが、師事する先生も教科書もないならバグと向き合ってバグの対処法を覚える事で、いろいろな可能性が見えてくるのです。 試行錯誤はけっこうしますが、それは決して無駄な事ではないと考えています。
補足
といいますか私は教科書もなければ師事する先生もいないのでCGIを作って完成させたとしても 私から見れば正常なプログラムでももしかしたら「おかしなプログラム」を作っている可能性は十分ありえる。 その点はCGIを作る時に常に考えてますよ。 何せちゃんと動いてるのかわからないですからね。 そのため、サーバー管理会社は使いません。迷惑をかける可能性が少しでもあるから そのため多額な賠償請求もされません。 私が使うのは自宅サーバーですよ。 ですから、壊れたとしても自業自得ですみますよ。 それにPCはすでに壊れてますしね。 それに私がどんな考え方だとしても。 C言語を使って楽しむのは非常に面白いのですよ。 皆さんが何の理由でC言語を使っているのかは分かりません。 仕事のため、プログラムの勉強のため等さまざまな理由でしょう。 私はC言語を使って楽しみたいからと言うのも理由であれば少しづつ目的となるプログラムを作っていくのが面白いのです。 材料が全くなくてもできますしね。
- Wr5
- ベストアンサー率53% (2173/4061)
>1が必須の理由が分からないです。 >なぜなのでしょうか?(長さを指定しなくても動いたので) バッファオーバーランを実施することができるから…です。 現在は20バイト確保していますが、そこに200文字読み込ませることもできます。 未指定ですからね。 そして、あふれたデータがどこに書き込まれるのか? ということです。 # セキュリティホール関係で「バッファオーバーランにより任意のコードが実行できる云々」というのはそういうモノです。 まぁ、そういう意味ではNo.1での私の回答もバッファオーバーランできるのですが。
補足
おやよく見たらお久しぶりです♪ 元気そうで何よりですね もうしばらくしたらクリスマスですよ おいしいご飯が楽しみです。 Wr5さんもクリスマスはたのしみますか? 世間話はここまでにして、バッファオーバーランをここで聞く事になるとはおもいませんでした なるほどです。 一定数の文字以上になったら禁止にしていたので気づきませんでした。 (練習用には書いてませんが) あふれたデータ云々はよくわからないようなことになりそうなら、プログラムとして問題ないなら放置。 バグがでてきたらその時処理するでしょうね。 ただ、こう書くとバグになるでしょうっと思っていたものが書いた後は正常に動く事もあって面白いですよね
- kmee
- ベストアンサー率55% (1857/3366)
読み込み方法そのものは同じです ・fscanf( fp, "%s %s",nameを一時的に読み込む領域のポインタまたは配列,mbを一時的に読み込む領域のポインタまたは配列 ); ・構造体のname,mbに、上記で読んだ内容を反映させる struct info の場合、name,mbをそのまま「一時的に読み込む領域」として利用する方法もあります。それがそこに書かれているプログラムです。 それで、それぞれの構造体と、そのメンバーはどんな使い方をしたいのですか? たとえばinfo2。 infoでのcharの配列をポインタにしてます。 ポインタは、対象へのアドレスでしかありません。fscanfで読み込むなら、別途その内容を記憶する領域が必要です。 その領域をどう用意するつもりなのでしょうか? ・mallocで動的に確保 ・記憶用の大きな配列を用意して、その一部を使う ・記憶用info構造体を用意して、各メンバーへのポインタにする それぞれに使い方が違います。 info3に至っては、なんでこんな構造体のデザインにしたのかがわかりません。 ファイルは1行にnameとmbで1セットで、それが6行ある、ってことですよね? それなら、infoの配列とか、info2の配列にするのが自然でしょう。
補足
<<それで、それぞれの構造体と、そのメンバーはどんな使い方をしたいのですか? ええっとこれは練習用のプログラムなのですが本当に作りたいプログラムは ・ログイン名、IP、リモートホストの3っつを記録して ・ログアウトしたら、記録から内容を消して ・『その内容を読み込んでログイン名のみ表示させる』 プログラムを作りたかったのです。 2番目の処理も苦戦中ですが、今回聞いてるのは3番目の処理をするときにどうしたらいいかの処理ですね <<・mallocで動的に確保 ・記憶用の大きな配列を用意して、その一部を使う ・記憶用info構造体を用意して、各メンバーへのポインタにする それぞれに使い方が違います。 ですので、こう聞かれてるのですが幸いmallocならある程度使った事があるので1番目で記述する方法はある程度分かります 2番目や3番目がどういったものか分からないのですが、作りたいプログラムが無事できるのであれば2番目や3番目の方法で書くこっとも考えます。(ただあんまり知らない方法や関数で書かれると分からなくなるので1番目の方法で書くつもりではあります) <<info3に至っては、なんでこんな構造体のデザインにしたのかがわかりません。 ファイルは1行にnameとmbで1セットで、それが6行ある、ってことですよね? それなら、infoの配列とか、info2の配列にするのが自然でしょう。 その理由はあくまでこのプログッラムが練習用であることとinfo2とinfo3がもしかしたら書き方がぜんぜん違う可能性を考えて質問しましたし、処理の仕方の2番目でそこらへんを知っておくとうまく処理の方法を思いつくのではないかと思って質問しました。 他にも私のプログラムの覚え方が特殊だから変な質問をしてると感じるかもしれませんが
- notnot
- ベストアンサー率47% (4900/10361)
いろいろ、考え方がおかしいです。変数の使い方も、scanfの使い方も。ついでに、「データ」のスペルも。 1. fscanfの %s では長さ指定が必須 2. char * のようなポインタ宣言した変数を使って文字列を扱うためには、mallocでメモリを割り当てる必要がある
補足
教えていただいた 1が必須の理由が分からないです。 なぜなのでしょうか?(長さを指定しなくても動いたので)
お礼
できました こんな感じですね #include <stdio.h> #include <string.h> #include <stdlib.h> struct info //1回目の呼び出し方法 { char name[20]; char mb[20]; }deta; struct info2 //2回目の呼び出し方法 { char *name; char *mb; }deta2; struct info3 //3回目の呼び出し方法 { char *name[6]; char *mb[6]; }deta3; void main(void){ FILE *fp; char n[100],m[100]; char a[6][100],b[6][100]; int i=0; fp=fopen("yasa.txt","r+"); while( !feof( fp ) ){ fscanf( fp, "%s %s",deta.name,deta.mb); printf("%s %s\n",deta.name,deta.mb); } printf("\n"); rewind( fp ); while( !feof( fp ) ){ fscanf( fp, "%s %s",n,m); deta2.name= (char*)malloc(strlen(n)+1); strcpy(deta2.name, n); deta2.mb= (char*)malloc(strlen(m)+1); strcpy(deta2.mb, m); printf("%s %s\n",deta2.name,deta2.mb); free(deta2.name); free(deta2.mb); } printf("\n"); rewind( fp ); while( !feof( fp ) ){ fscanf( fp, "%s %s",a[i],b[i]); deta3.name[i]= (char*)malloc(strlen(a[i])+1); strcpy(deta3.name[i], a[i]); deta3.mb[i]= (char*)malloc(strlen(b[i])+1); strcpy(deta3.mb[i], b[i]); printf("%s %s\n",deta3.name[i],deta3.mb[i]); free(deta3.name[i]); free(deta3.mb[i]); i++; } fclose(fp); }
補足
なるほどmallocを使うのですね ぜんぜん思いつきませんでした ソースも書いていただきありがとうございます。 開発可能なPCに戻して試してみますね