• 締切済み

[C,C++]テキストファイルの読み込み

はじめまして C++をはじめてまだ半年の初学者です。 テキストの読み込みについての質問なのですが、 以下のような形式(csv形式)のテキストのヘッダーと項目名を除く 数字の部分と文字の部分を読み込みたいのですが どのようにプログラムを書けばよいですか? ヘッダーと項目は不要です。 動物の名前とそのXYZは20個、日付は結構な数並んでいます。 時間と動物のデータは読み込み後、動物の種類ごとに構造体に格納します。 したがって、動物のデータはループで読み込めると良いのですが、 その方法が分かりません。 よろしくお願いします。 ************************** animal.txt by tanaka.tarou ************************** DATE, NAME, X, Y, Z, NAME, X, Y, Z, NAME, X, Y, Z, ・・・ 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, ・・・ 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, ・・・ 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, ・・・ 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, ・・・               ・               ・               ・

みんなの回答

回答No.3

// ざっくりこんなもんかしら。 // VC++ 10 でコンパイル/動作確認済 #include <iostream> #include <fstream> #include <set> #include <cstring> #include <string> #include <algorithm> using namespace std; struct record { string date; string name; int x, y, z; record() {} record(const string& n) : name(n) {} }; inline bool operator<(const record& x, const record& y) { return x.name < y.name; } ostream& operator<<(ostream& stream, const record& r) { return stream << r.date << ' ' << r.name << ':' << r.x << ',' << r.y << ',' << r.z; } inline string trim(const string& s) { return s.substr(s.find_first_not_of(" ")); } int main() { multiset<record> animals; set<string> names; ifstream stream("animal.txt"); if ( !stream.is_open() ) return 1; string line; bool skip = true; while ( getline(stream,line) ) { if ( skip ) { if ( line.substr(0,4) == "DATE" ) skip = false; } else { record rec; char* token; char* p = &line[0]; p = strtok(p,","); if ( !p ) break; rec.date = trim(p); while ( true ) { p = strtok(nullptr,","); if ( !p ) break; rec.name = trim(p); p = strtok(nullptr,","); if ( !p ) break; rec.x = atoi(p); p = strtok(nullptr,","); if ( !p ) break; rec.y = atoi(p); p = strtok(nullptr,","); if ( !p ) break; rec.z = atoi(p); names.insert(rec.name); animals.insert(rec); } } } stream.close(); for ( auto iter = names.begin(); iter != names.end(); ++iter ) { auto range = animals.equal_range(record(*iter)); for_each( range.first, range.second, [](const record& rec) { cout << rec << endl; }); cout << endl; } } #if 0 /* 以降を切り取って animal.txt とすべし。 */ ************************** animal.txt by tanaka.tarou ************************** DATE, NAME, X, Y, Z, NAME, X, Y, Z, NAME, X, Y, Z, ・・・ 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, sheep, 1, 2, 3 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, cat, 2, 3, 4 2011.05.23, rabit, 2, 5, 6, pig, 5, 3, 9, cow, 6, 3, 8, dog, 3, 4, 5 #endif

myuras
質問者

お礼

コード付きの回答ありがとうございます。 手持ちの古いBorlandコンパイラだとエラーをはくので、 後でVC++で試してみます。 コードを見て思ったのですが構造体を書き忘れていましたね、 重ねて感謝です。

回答No.2

こんな感じではどうですか? ファイルが終わるまで、一行まるまる読みこむ。(fgets推奨)    文字位置を何らかの形で持って、行頭にセット。    最初の文字が数字だったら、       頭から日付を解釈し、文字位置を','の次に進める。       文字位置の文字が行端でない間、          ','の前までを動物名として、取得。          文字位置を','の次に進める。          次はXを取得。          文字位置を','の次に進める。          次はY。          文字位置を','の次に進める。          次はZ。          文字位置に改行文字が来なければ、文字位置を','の次に進める。          ここまで取得した各情報を、構造体にセット。 幾つあるかわからない情報を持つには、構造体は動的に確保するのがいいでしょうね。

myuras
質問者

お礼

回答ありがとうございます おっしゃるとおりにfgetsやifstreamを使ってみたのですが、 やはりべた書きでした。 少しでもループで処理できたらと思っています。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

そんなヘッダがあるのがcsvファイルと言えるか? と言う問題も…。 ヘッダ中に','があらわれることはない。 というのであれば… 1行ずつ読み込み、','が無い間はヘッダなので読み捨てる。 最初に','が含まれる行があったら項目名の行なので読み捨てる。 その後に読み込まれるのはデータが含まれる行なので読み込み後、各データを構造体へつっこむ。 ファイルの最後まで繰り返し… という感じに処理していくことになろうかと。 # ヘッダとやらに','が含まれる場合はこの方法は使えませんが。

myuras
質問者

お礼

回答ありがとうございます。 csvってヘッダー無いんですね、勉強になります。 1行読み込みの際に使うfscanfだと書式が必要になると思うのですが、 読み捨て部分と必要なデータ部分で書式が違う点はどのようにすればいいでしょうか? また、20個分の動物データの構造体への突っ込みは、 やはりべた書きでじゃないとできませんか? 多少、プログラムコードを交えてもらえると助かります

関連するQ&A

  • C#でのテキストファイルの扱い

    C#初心者ですが、よろしくお願いします。 次のようなテキストファイルがあります。 ----------------------------------- データリスト time    = 00:00:00 name    =Tanaka height   =170[cm] weight   =55[kg] ID     =00000000 time    =00:01:10 name    =Shimizu height   =165[cm] weight   =53[kg] ID     =00000001 ~以下同様に続きます~ ------------------------------------ このテキストファイルからC#で、timeの数値部分(00:00:00の部分)、身長の数値部分(一番上だと170)、同様に体重の数値部分、IDの数値部分を取得したいのですが、どのようにすればよいでしょうか? ※timeと=の間のスペースはテキストファイルの方は半角で入ってますが、 ここでは半角スペースが認識されないので、上では全角スペースを入れています。 また、なぜか書いたときに「=」が縦にそろわないのですが、 実際のテキストファイルではそろっています。

  • visual basic6.0でのテキストファイルからの読み込みについて。

    vb初心者です。 数値をテキストファイルに保存しています。その数値は、x方向に10個、y方向に3個、つまり10列3行の数値を保存しています。 そのデータを2次元配列 D(x,y)として読み込みたいのです。 for x=0 to 9, for y=0 to 2 と範囲を指定して、数値全部を読み込むときは、D(x,y)の値は正しく入っているのですが、 ある範囲だけを読み込みたいとき、たとえば for x=0 to 5, for y=0 to 1 としたとき、D(x,y)は別の数値が読み込まれてしまいます。 これは、テキストファイルの数値が配列になっていないということですよね?? どうすれば、テキストファイルの数値を2次元配列として読み込むことができるのでしょうか? 文章が解りにくくてごめんなさい!!よろしくお願いします! 

  • C言語におけるtxtファイルの読み込みと出力

    環境:WinXP,Borland C++compiler 以下のようなプログラムを考えました。 ・sample.c #include <stdio.h> float func(float x,float y,float z); int main(void) { float x,y,z; scanf("%f",&x); scanf("%f",&y); scanf("%f",&z); printf("%f",func(x,y,z)); return 0; } float func(float x,float y,float z) { return x+y+z; }//ここまで。 例えば(x,y,z)=(1,2,3)と入力すると6が出力されます。 このプログラムを、任意のn組の(x,y,z)の記述されたテキストファイルを読み込んで出力outを計算し、別のテキストファイルにn組の(x,y,z,out)を書き込むようにするにはどのような変更を加えればよいのでしょうか。 具体例は以下のような感じです。用意しておいたinput.txtをsample.cで読み込んで計算し、また作成されていないoutput.txtに出力するのが目標です。 (n=3の場合) ・input.txt //x y z 1 2 3 1 8 9 -1 7 5 ・output.txt //x y z out 1 2 3 6 1 8 9 18 -1 7 5 11

  • C言語でファイルから読み込んだデータの処理

    こんにちは C言語についてかじった程度でほとんど初心者なので、どうぞよろしくお願いします。 テキストファイルからデータを読み込み、そのデータをもとに計算してその結果を違うファイルに出力する。 というプログラムを組みたいと思っています。 例えば、 1 2 3 4 5 … 400 401 …     440 : 1600 …    2000 というデータだとします。 4項目ごとのデータを(a,b,c,d)として、このデータを x=a+b y=a+c z=a+d といったように計算して、これを [x y z] [ …  :  … といったように出力したいんです。 この場合では [3 4 5] [11 12 13] … [  ]  : [ ]… [ ] となると思います。 ファイルの入出力だけならいろんなところで例題にもなっているので何とかなると思っていたのですが [ ] [ ] : といったように下につながるか [ ][ ][… といったようにすべて横につながってしまいます。 対応するように並べるにはどのようにすればいいのでしょうか。 うまく説明できず、非常にわかりにくい質問だとは思いますが、皆さんどうぞヒントだけでも与えてくれるとうれしいです。 よろしくお願いします。

  • C++ファイルからデータ入力して計算、ファイル出力

    C++初心者です。 ファイルの数値データを入力して、それらを計算してからファイルに出力する方法がわかりません。 たとえば、 入力ファイル   出力ファイル 行数  x y z (1)  1 1 6   y(1)*exp(z(1)-x(1))+y(2)*exp(z(2)-x(1))+... (2)  3 5 2   y(1)*exp(z(1)-x(2))+y(2)*exp(z(2)-x(2))+... (3)  5 6 9  y(1)*exp(z(1)-x(3))+y(2)*exp(z(2)-x(3))+... (4)  9 1 3   y(1)*exp(z(1)-x(4))+y(2)*exp(z(2)-x(4))+… (5)  1 7 8   y(1)*exp(z(1)-x(5))+y(2)*exp(z(2)-x(5))+... 入力したデータを上記のように計算してから出力ファイルにしたいのですが、複雑なのでプログラムをどう組み立てれば良いのかわかりません。 ちょっとしたことでも結構です、参考になりそうなサイトや、ロジック、プログラムに関するアドバイスいただけませんか。

  • gnuplot:テキストファイルからのコンター図

    4.4.3win32を使っています。 現在テキストファイルにスペースで区切られたデータ□が、下のように並んでいます。 □□□□□□□□□ □□□□□□□□□ □□□□□□□□□ □□□□□□□□□ □□□□□□□□□ □はZ軸、縦の並びがX軸、横の並びがY軸に対応しています。 gnuplotを用いてテキストファイルからコンター図を作成する場合は、 下のようにX軸、Y軸の値も書いて、さらに配列を変えてから行うしかないのでしょうか。 11□ 22□ 33□ 44□ 55□ 元のテキストデータから簡単に作成する方法があれば教えていただけないでしょうか。

  • ファイルの作成・書き込み・読み込みについて

    ファイルの取り扱いについて、どのように記述すればいいのかが分かりません。 分からないことが多いので(1)~(4)の質問に分けています、Cの勉強は趣味程度にしかできていないので、詳しくご回答いただけると嬉しいです。 自分なりに書いてみます、間違いがあればご指摘宜しくお願いします。 (1)Aを頭文字にして100個のcsvファイルを作成 (a1,a2…a100) char A[100] FILE *fp; for(i=1;i<101;i++) { snprintf(A,sizeof A,"A%d.csv",i); if((fp = fopen(A,"w"))!=NULL) {exit(1);} } (2)A1を開きデータを入れる、この動作を同様に2~100で繰り返す。 A1に入れたいデータはx,y,zで1000行 fp = fopen("A1.csv","a"); for(z=1;z<11;z++) { for(y=1;y<11;y++) { for(x=1;x<11;x++) { fprintf(fp,"%d,%d,%d\n",x,y,z); } } } fclose(fp); これでこんな感じに書き込まれるはず・・・ 1,1,1 2,1,1 3,1,1  ・  ・  ・ 10,10,10 これを同様に2~100のファイルに対して一気に行いたいですが、書き方が分かりません。 (3)再びA1を開きx=10,Y=10の時のzの値を知りたい。 こんな事はできるのでしょうか? もし無理なら~行目のデータを呼び出す (4)そしてA1を開きx=10,Y=10の時の、zだけを上書き。 長くなってすいません、分からない事だらけなので宜しくお願いします。

  • テキストからあるキーワードの入った行の抜き出し

    質問させて頂きます。 下記のようなデータがテキストであったとして、「name」「ID」の行だけ取り出し、 CSV、もしくはテキストなどでも良いので出力する方法はないでしょうか。 言語はPHPだと助かります。 ----------------------- name tanaka blood B birthday 10/24 ID 1002324 time 14:15 ----------------------- name hashimoto blood O birthday 6/11 ID 1002325 time 14:50 ----------------------- name yamaguti blood AB birthday 1/3 ID 1002326 time 18:29 ----------------------- ×500くらい 出力結果(例) name tanaka ID 1002324 name hashimoto ID 1002325 name yamaguti ID 1002326 または name tanaka,ID 1002324 name hashimoto,ID 1002325 name yamaguti,ID 1002326 質問内容に説明不足な部分などがありましたら申し訳ありません。 どなたかご存じの方がいらっしゃいましたら、宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 外部テキストファイルから座標データを読み込み,その座標にムービークリップを配置する

    タイトル通りなのですが, 外部テキストファイルから座標データを読み込み, その座標にムービークリップを配置させたいと考えています. 外部テキストファイルは name=0, x=10, y=20 &name=1, x=11, y=21 &name=2, x=12, y=22  ・      ・   ・  ・      ・   ・  ・      ・   ・ として,1行ごとに名前と座標のデータがあります. 行数は可変で,行数だけムービークリップを配置したいと考えています. いろいろ調べてsplit関数などを使えば1行ごとに読み込めそうだということはわかりましたが, オブジェクト指向はほとんど使ったことが無いので悪戦苦闘しています(C言語はそれなりに使えます). どのようにすれば上記のようなプログラムをかけますでしょうか. どなたかよろしくお願いいたします. 環境 FLASH MX, WINDOWS XP

    • ベストアンサー
    • Flash
  • テキストファイルからの読み込みにつきまして

    はじめまして。Flash初心者です。 ただいま、「プロとして恥ずかしくないFlashの大原則」のP94ページの 外部テキストからの設定が可能な縦メニューを挑戦しているのですが、テキストファイルからの日本語の読み込みが表示できません。アルファベットでしたら表示ができるので、どこがおかしいのかわからなくなってしまいました。 以下、使用中のロジック // 外部テキストのエンコード設定 System.useCodepage = true; i = 0; // メッセージウィンドウに1文字ずつ表示する関数を作成 function msgWindow( winObj, mObj ){ if( i <= mObj.mMsg.length ){ winObj.msgStr.text = mObj.mMsg.substr( 0, i ); i++; } else{ i = 0; clearInterval( _root.tID ); } } // ロード時に外部テキストを読み込む onLoad = function(){ if( _root.textUrl != null ){ this.loadVariables( _root.textUrl ); } else{ this.loadVariables( "menu.txt" ); } } // データを読み込み後の処理 onData = function(){ // メニューボタンをステージに配置 for( cnt = 1; cnt < 2; cnt++ ){ if( eval( "menu" + cnt ) !== undefined ){ mObj = "mBtn" + cnt; _root.attachMovie( "menuBtn", mObj, cnt ); _root[mObj]._x = 5; _root[mObj]._y = 60 * cnt; _root[mObj].m_name.text = eval( "menu" + cnt ); _root[mObj].mUrl = eval( "url" + cnt ); _root[mObj].mTarget = eval( "target" + cnt ); _root[mObj].mMsg = eval( "msg" + cnt ); } // メニューボタン上でマウスボタンを離した時 _root[mObj].onRelease = function(){ getURL( this.mUrl, this.mTarget ); } // マウスオーバー時の処理 _root[mObj].onRollOver = function(){ eval(this._name).gotoAndStop( 2 ); with(_root) { objMsgWin = "newMsgWin"; attachMovie("msgWin", objMsgWin, 100 ); _root[objMsgWin]._x = this._x; _root[objMsgWin]._y = this._y + 25; tID = setInterval( msgWindow, 20, _root[objMsgWin], this ); } } // ポインタをメニューボタン外に移動した時 _root[mObj].onRollOut = function(){ eval(this._name).gotoAndStop( 1 ); _root[_root.objMsgWin].removeMovieClip(); clearInterval( _root.tID ); } // マウスボタンがメニューボタン外で離された時 _root[mObj].onReleaseOutside = function(){ eval(this._name).gotoAndStop( 1 ); _root[_root.objMsgWin].removeMovieClip(); clearInterval( _root.tID ); } } } stop(); 以下、テキストファイル &menu1=あいうえお& &menu2=123456& &menu3=MENU03& &menu4=MENU04& &menu5=MENU05& &menu6=MENU06& &menu7=MENU07& &menu8=MENU08& &url1=http://www.mdn.co.jp/& &url2=http://www.mdn.co.jp/& &url3=http://www.mdn.co.jp/& &url4=http://www.mdn.co.jp/& &url5=http://www.mdn.co.jp/& &url6=http://www.mdn.co.jp/& &url7=http://www.mdn.co.jp/& &url8=http://www.mdn.co.jp/& &target1=_blank& &target2=_blank& &target3=_blank& &target4=_blank& &target5=_blank& &target6=_blank& &target7=_blank& &target8=_blank& &msg1=現在のページです& &msg2=現在のページです& &msg3=現在のページです& &msg4=ここにメニュー04の説明が入ります。& &msg5=ここにメニュー05の説明が入ります。& &msg6=ここにメニュー06の説明が入ります。& &msg7=ここにメニュー07の説明が入ります。& &msg8=ここにメニュー08の説明が入ります。& 結果 『&menu1=あいうえお&』で出したい、「あいうえお」が表示できません。他の&menuと&msgの日本語は表示されるのですが、どこかおかしいでしょうか。 もしお時間ありましたら宜しくお願い致します。 ちなみにですが、今回のロジックのサンプルはhttp://www.mdn.co.jp/content/view/962からダウンロードしたものです。

    • ベストアンサー
    • Flash

専門家に質問してみよう