• 締切済み

しつもんです

cygwinでc言語を使っています。同じディレクトリに na.txtというテキストファイルがあるとします。 そのファイルには 2,3,4,5,6 7,8,9,10,11 12,13,14,15,16 と5つずつカンマ区切りのデータが入力されているとします。このファイルのデータを読み込んで二次元配列に入れたいです。この例でいえば、5つのデータで3行あるので a[3][5]の配列が必要でそれにa[0][0]=2 a[0][1]=3, .... a[2][4]=16と入れていきたいです。 ただ、ファイルが何行あるのかわからないとします。つまりこの場合なら3行あるのですが、それはわからないとします。 たぶんファイルポインタを用意するんだと思うですがどうしてもよくわかりません。教えてください

みんなの回答

  • matsu-td
  • ベストアンサー率31% (5/16)
回答No.4

参考になるかどうか。。。 BLUEPIXYさんのおっしゃる「vectorみたいな機構」みたいなやつを書いてみました。main関数の中のforループ回数をいろいろと変えて試して見て下さい。 余談ですが、ここでの見栄えを良くするために、全角スペースを使っています。コピペする場合は注意して下さいね。 #include <stdio.h> #include <malloc.h> struct MyData {   MyData* prev;    // 前のアイテムへのポインタ   MyData* next;    // 次のアイテムへのポインタ   int   data;    // データ }; /// /// 引数itemで指定されたアイテムの次に、 /// 新しいアイテムを追加します。 /// MyData* AddItem(MyData* item, int data) {   // メモリを確保する   MyData* pItem = (MyData*)malloc(sizeof(MyData));   // アイテムが指定されている場合   if(item != NULL)   {     // 次のアイテムとして、今新しく追加されたアイテムをセット     item->next = pItem;   }   // メモリが正常に確保できなかった場合   if(pItem == NULL)   {     // ここで抜ける     return NULL;   }   // 新しく追加されたアイテムのプロパティを設定   pItem->prev = item;   // 前のアイテムへのポインタ   pItem->next = NULL;   // 次のアイテムへのポインタ   pItem->data = data;   // データ   // 新しく追加されたアイテムのポインタを返す   return pItem; } /// /// 全てのアイテムを削除します。 /// void DeleteAll(MyData* pFirst) {   while(pFirst)   {     // 次のアイテムへのポインタを取得     MyData* pNext = pFirst->next;     // アドレスをデバッグ出力     printf("free(%p)\n",pFirst);     // メモリを解放     free(pFirst);     // ポインタを次のアイテムに更新     pFirst = pNext;   } } /// /// メイン関数 /// void main() {   int i;   MyData* pCurrent = NULL;   MyData* pFirst = NULL; /// /// リストの作成 ///   // 100回ループ(回数は変更可)   for(i = 0; i < 100; i++)   {     // データとしてiの値を持つアイテムを追加する     pCurrent = AddItem(pCurrent, i);     // 最初のアイテムのポインタが初期化されてない場合     // (1回目のみ)     if(pFirst == NULL)     {       // 最初のアイテムのポインタを保存       pFirst = pCurrent;     }     // データ追加に失敗した場合     if(pCurrent == NULL)     {       // ループを抜ける       break;     }   } /// /// リストの内容の確認 ///   // 最初のアイテムのポインタを取得   pCurrent = pFirst;   do   {     // アイテムの内容をデバッグ出力     printf("[%p] data = %d\n",pCurrent, pCurrent->data);     // 次のアイテムのポインタを取得     pCurrent = pCurrent->next;   } while(pCurrent); /// /// リストの削除 ///   // 全てのアイテムを削除(メモリ解放)   DeleteAll(pFirst); }

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

#2>正直なにをいっているのか理解できないです #2の方針でのプログラムのサンプルを作ってみました。 あんまり、参考にならないところもあるかもしれません。^^; ------------------------------------------------------------------ #include <stdio.h> #include <string.h> #include <stdlib.h> int countComma(const char *str){ int count=0; const char *pos; for(pos=str;NULL!=(pos=strchr(pos, ','));pos++){ count++; } return count; } int main(void){ FILE *fp; char buff[64]; char *p; int count=0; int (*a)[5], *wk; int i,j; fp=fopen("na.txt","r");//カンマで区切られた1行に5個のデータがあるファイル while(NULL!=(fgets(buff,64,fp))){ count+=countComma(buff)+1;//コンマがn個あるときデータはn+1個 } // printf("データ数:%d\n",count); if(NULL==(a=(int (*)[5])calloc(count/5, sizeof(int [5])))){ printf("メモリが確保できません\n"); return -1; } rewind(fp); wk=(int*)a; while(NULL!=(fgets(buff,64,fp))){ p=buff; while(1){ *wk++=atoi(p); if(NULL==(p=strchr(p, ','))) break; p++; } } fclose(fp); for(i=0;i<count/5;i++){ for(j=0;j<5;j++) printf("a[%d][%d]=%d ",i,j,a[i][j]); printf("\n"); } return 0; }

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

2次元配列をあらかじめ余分をみて確保するのではなく、動的に確保したいということでしょうか? C言語では、動的に2次元配列を確保するような宣言ができないので、 callocとかを使ってメモリを確保し、そのポインタを使って配列アクセスみたいな形になるかと思います。 その時の確保するサイズが判らないので、 いったん、ファイルを読み出して、必要な要素の数を数えて それで確保し 2回目の読み出しで、実際に値をセットするようなことをすればいいかと思います。 2度読みするのでムダみたいですがしょうがないです。 C++でいうvectorみたいな機構(実行時にメモリの確保や拡張を自動的にやってくれるようなの)を実装すると楽ですが、そういうのが必要なのかどうかは、処理する人の考え次第。

benzousandazoyo
質問者

補足

すいません、正直なにをいっているのか理解できないです。どうしてもこれらを格納するためのプログラムがわからないのです。

  • yyamagu
  • ベストアンサー率40% (21/52)
回答No.1

配列を使う方法もいろいろありますが、こういう場合、配列は使わないのが普通です。 リスト構造を覚えたほうがよいですよ。

参考URL:
http://www005.upp.so-net.ne.jp/h-masuda/cl/CAlgo/list02.html
benzousandazoyo
質問者

補足

リスト構造を大学でならったんですが、よくわからないです、、、、。

関連するQ&A

  • この問題がわかりません・・・

    この問題がわかりません(-_-;) 7個×2行分のデータをdata配列に読み込みというところが理解できず何度もやってみたのですが解けませんでした・・・答えが載っておらず困っています(@_@;) C言語詳しい方よかったら回答お願いします<m(__)m> 次の2行の内容でtest614.txtファイルを作成しなさい。 1 2 3 5 8 13 21 1 2 2 4 8 32 256 ※スペース区切りで7個の数字2行分。 int型2次元配列変数data[2][7]を宣言後、test614.txtファイルを開いて7個×2行分のデータをdata配列に読み込み、その内容を右のように表示する。続いて、test614.txtファイルを閉じてから、右のようにdata配列を用いて縦に並んだ数値を加算した結果を表示するプログラムを作成しなさい。 実行結果例 (実行結果例) 1 2 3 5 8 13 21 1 2 2 4 8 32 256 ------------------- 2 4 5 9 16 45 277

  • 二次元配列について

    C#を使っています。 エクセルのデータを、カンマ区切り(CSV)にして保存しました。 そのデータをそのまま二次元配列に代入していきたいのですが、うまくできません(><) データの一行目しか代入しなかったりします。。二行目にうつってくれません。まだまだ初心者なのですが、どうか教えてください(><)

  • 2次元配列のデータをファイルへ保存

    教えて下さい。 a(100,200)の2次元配列のデータをファイルに保存したいのですが、 a(0,0),a(0,1),a(0,2).......a(0,200) a(1,0)....... a(2,0)... . . . a(100,0)...................a(100,200) といった感じでカンマ区切りでCSV形式で保存したいのですが、これを簡単にファイルに保存する方法を 教えて下さい。 よろしくお願いします。

  • PHPで、○番目のカンマの文字を呼び出す方法

    0,123,45,678,999 など、カンマ区切りの情報がある data.txt というファイルがあり、 別のPHPファイルにdata.txtの内容を書き出したい場合、 <?php echo file_get_contents("data.txt"); ?> と書くと全部表示されてしまいます。 data.txtの1行目で、2番目と3番目のカンマの間の数字(上の例ですと123)を書き出すには、どのように書いたらよいか、お分かりになる方教えて頂けませんでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • ■質問事項

    ■質問事項  C言語にて、txtファイルを読み込んで検索した文字列が存在した場合、  その行の1行下の行を出力する方法について ■背景  事務系の仕事で、余計なデータが多く含まれるtxtファイルがあります。  そこで、必要なデータだけ出力できるように、C言語にてプログラミング  してみました。  しかし、検索した文字列の存在する行を出力することはできるのですが、  必要なデータは検索した文字列のひとつ下の行にあります。  ポインタに関してはまだ勉強不足な点もあり、  なかなかうまく動作してくれません。  ご教授いただければ幸いです。

  • Javaでのカンマで配列を分ける方法

    こんにちは。 カンマ区切りで入力されているデータを2次元配列に格納したいのですがよくわかりません。 それとデータをtxtファイルから入力する方法で配列を入力した分だけ作ることはできますでしょうか? 現在のプログラムは最初に配列を1000個用意する形になっているので効率的とは言えないと思うのですが・・・。 以下プログラムを載せます。 public String[] datain(){ String[] data = new String[1000]; String inputFileName; int i = 0; // 読み込むファイルの名前 inputFileName = "D:\\a.txt"; // ファイルオブジェクトの生成 File inputFile = new File(inputFileName); try { // 入力ストリームの生成 FileInputStream fis = new FileInputStream(inputFile); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); // テキストファイルからの読み込み String d; while ( ( d = br.readLine()) != null ) { data[i] = d; i += 1; } br.close(); } catch(Exception e) { e.printStackTrace(); } return data; } というメソッドです。 戻り値を返した後でも前でもいいので、 --データ-- (a.txt) あ,い,う,え,お か,き,く,け,こ さ,し,す,せ,そ ↓このように取り込みたいのです。 --配列-- [0,0] = あ  [0,1] = い  [0,2] = う  [0,3] = え  [0,4] = お [1,0] = か  [1,1] = き  [1,2] = く  [1,3] = け  [1,4] = こ [2,0] = さ  [2,1] = し  [2,2] = す  [2,3] = せ  [2,4] = そ よろしくお願いします。

    • ベストアンサー
    • Java
  • テキストデータの読み込みについて

    C言語のテキストデータの読み込みについてです。 C言語のプログラムについてです。 2444,1114,2807, 1984,2845,2086, 658.1,-1564.0,1239.7, -102.0,958.4,123.1, 12.7,6.0,82.7 2439,1110,2802, 1973,2865,2108, 658.8,-1563.7,1239.6, -102.0,957.1,121.9, 12.8,6.0,82.7 2441,1106,2806, 1967,2888,2124, 659.4,-1563.5,1239.5, -102.2,956.4,121.0, 12.8,6.1,82.8 2440,1109,2808, 1964,2896,2127, 660.0,-1563.3,1239.4, -102.7,956.2,120.7, 12.8,6.1,82.8 2441,1112,2807, 1981,2894,2120, 660.6,-1563.0,1239.4, -103.3,956.2,120.1, 12.8,6.1,82.8                                       ↑ 上の様なカンマとスペースで15個に区切られているtxtファイルがあるのですが、このtxtデータの10コ目と11コ目をを計算で使いたく、取り出したいと考えているのですがscanfを使いどのように取り出すことが出来るのか、また取り出したデータから数値を引くことを教えて頂きたいです。 つまり -102.0   958.4 -102.0   957.1 -102.2 と 956.4 -102.7   956.2 -103.3   956.2,             を取り出して計算に使いたいです。 そして1番上の数値だと、 -102.0と958.4 を読み込み、例えばそれぞれ100を引いた値を配列に入れたいです。 -102.0と958.4 → -202.0 と 858.4 のように取り出したいです。 教えて頂きたいです。お願いします。

  • CSVファイルを読み込み、ファイル名を変更。

    CSVファイルを読み込み、ファイル名を変更。 使用言語はperlです。perlは初心者です。 アルゴリズムが、 CSVファイルを読み込み→2次元配列に格納→ファイル名変更 という流れになっているプログラムを作成中です。 CSVファイルの中身は あ.txt , a.txt い.txt , b.txt う.txt , c.txt です。 CSVファイルを読み込み2次元配列に格納するプログラムは以下のようにしました。 ----------------------------------- $i= 0; open IN, "sample.csv"; while (<IN>) { my @data = (); @data = split (/,/); for (0..@data) {$jdata[$i][$_] = "$data[$_]";} $i++; } close IN; ---------------------------------------- 「あ.txt」を「a.txt」に変更しようとして、この中に rename $jdata[0][0] , $jdata[0][1] ; と書いてみましたが、変換されません。 どう書けばよいのでしょうか。よろしくお願いします。

    • ベストアンサー
    • Perl
  • 連想配列の操作方法について

    A,B,C,D,E 1,3,4,5,7 2,4,6,7,10 4,5,1,4,8 このようなコンマ区切りテキストファイルを読み込み、次のような配列をつくるには、どうのようにしたよいか悩んでいます。 ご教授ください。 [A,1,2,4],・・・,[E,7,10,8] (行と列を置き換えるように配列を作成したい)

    • ベストアンサー
    • Perl
  • ファイルから読み込んで配列へ

    PerlでCGIスクリプト(掲示板もどき)を作成しています。 配列の操作がうまくいかず、ご教授頂きたいと思います。 <やりたい事> 1.ブラウザ上のフォームからの入力を、カンマ区切りでテキストファイルに追記して保存。 2.そのテキストの一部を使ってHTMLで表を作る。 <実際の作業> 1.フォームからのデータはcgi-lib.plで連想配列として受け取り、unshiftでテキストファイルへ追記する。 &ReadParse; #フォームからデータを受け取る $o=$in{'name'}; $p=$in{'mail'}; $q=$in{'title'}; $r=$in{'comment'}; open(IN,"xxx.txt"); @tmp1=<IN>; close(IN); #1件1行として新規データを追加する unshift (@tmp1,"$oo" , "," , "$pp" , "," , "$qq" , "," , "$rr","\n"); open(OUT,">xxx.txt"); print OUT @tmp1; close(OUT); 2.xxx.txtのデータを読み込んで、1列目(name)と3列目(title)だけを使った表を作る。 データを読み込む時点でつまづき、先に進めません。 <テキストファイルの例> 1行目:a,b,c,d 2行目:e,f,g,h 3行目:i,j,k,l 以下同様 <症状> print @tmp1;とすると、a~lの全てのデータが表示される。 $tmp1[0];とすると、(a)のみ表示される。 $tmp1[1];とすると、カンマ(,)が表示される。 $tmp1[2];とすると、(b)が表示される。 <質問> 一つの行(配列)に対して2回繰り返す処理(nameとtitle)と、行単位で繰り返す処理(1行目、2行目…)を合わせればいいのだろうと思っていますが、どうすればいいのかわかりません。 気分的には↓こんな感じです。 foreach { "行の処理" foreach { "列の処理" } } そもそも、区切り文字であるカンマが、配列に格納されている時点で失敗しているのかな?とも思っています。 宜しくお願いします。 なお、不足している情報がありましたら補足いたします。

    • ベストアンサー
    • Perl

専門家に質問してみよう