質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

4回答

6130閲覧

C++でCSVファイル処理

oohata_mk3

総合スコア12

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2015/07/14 12:06

編集2015/07/14 14:40

大学の研究で実験データをC++を使って処理しようと考えて,
実験によってデータ点数は5万点前後とまちまちなのですが,
0000や0001のように連続した番号の名前のCSVファイルをC++で1度読み込んで行数をカウントして,
カウントした行数nを配列定義の要素数に代入しようとしているのですが,
データ点数が多くなってしまったからなのか,
”segmentation foult”
と出てしまいました.
これを解決したいのですが,どのようにすればいいでしょうか?

追記
segmentation faultを解決しようとしてvectorを使ってみたのですが,
”note : template argument deduction/substitution failed :”
というエラーが出てしまいました.

lang

1#include <stdio.h> 2#include <vector> 3using namespace std; 4 5int main() 6{ 7 int nlin=0 , header=17; 8 int i,cnt,c,n; 9 vector<double> x1[cnt],x2[xnt],x3[cnt],x4[cnt]; 10 double sum1,sum2,sum3,sum4; 11 double I1,I2,I3,I4; 12 double I1_,I2_,I3_,I4_; 13 double dt=0.0000001; 14 char bff[100]; 15 FILE* fp; 16 FILE* save; 17 FILE* gp; 18 char fname[]={"file[n].csv"}; 19 char save_fname[]={"save[n].csv"}; 20 21//file loop 22for(n=0 ; n<=cnt ; n++) 23{ 24 25//line count part 26 fp =fopen(fname,"r"); 27 28 if(fp) 29 { 30 while(c=getc(fp)!=EOF); 31 { 32 if(c=='\n')cnt++; 33 } 34 35 } 36printf("%d\n",cnt); 37 38//return first line 39 rewind(fp); nlin=0; 40 41//file & gnuplot open for save 42 save = fopen("save[n].csv","w"); 43 gp = popen("gnuplot -persist","w"); 44 45//header cut part 46 while(fgets(bff,100,fp)!=NULL) 47 { 48 if(++nlin <= header)continue; 49 } 50 51//calibration value ~ integrater 52for(i=17 ; i<=2000 ; i++) 53{ 54 while(fscanf(fp,"%lf%lf%lf%lf",&x1[cnt],&x2[cnt],&x3[cnt],&x4[cnt])==4) 55 { 56 sum1 += x1[i]; 57 sum2 += x2[i]; 58 sum3 += x3[i]; 59 sum4 += x4[i]; 60 } 61} 62for(i=17 ; i<=cnt ; i++) 63 { 64//first point at each column 65 I1_= (x1[17] - sum1) * dt; 66 I2_= (x2[17] - sum2) * dt; 67 I3_= (x3[17] - sum3) * dt; 68 I4_= (x4[17] - sum4) * dt; 69 70//second ~ final point at 4each column 71 I1 = I1_ + (x1[i+1] - sum1) * dt; 72 I2 = I2_ + (x2[i+1] - sum2) * dt; 73 I3 = I3_ + (x3[i+1] - sum3) * dt; 74 I4 = I4_ + (x4[i+1] - sum4) * dt; 75 76//writing part on file 77 fprintf(save,"%f \t %f \t %f \t %f \n",I1_,I2_,I3_,I4_); 78 fprintf(save,"%f \t %f \t %f \t %f \n",I1,I2,I3,I4); 79 80 fprintf(gp,"plot %f with lines \n",I1); 81 fprintf(gp,"plot %f with lines \n",I2); 82 fprintf(gp,"plot %f with lines \n",I3); 83 fprintf(gp,"plot %f with lines \n",I4); 84 } 85 86 87pclose(gp); 88fclose(save); 89fclose(fp); 90} 91return 0; 92} 93 94コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

archiver

2015/07/14 12:51

ひとまず、処理させようとしているプログラムを載せていただけませんか。 その方が、より多くのアドバイスを受けられると思います。
guest

回答4

0

基本的なことですが

宣言部分
int i,cnt,c,n;
vector<double> x1[cnt],x2[xnt],x3[cnt],x4[cnt];

ここでエラーが出ていませんか?
まずcntが初期化されていないのでx1[cnt]の領域自体確保はおかしくなりますし、
x2[xnt]のxnt自体宣言がされていませんね(キーが隣り合っているのでcntのタイプミス??)
特にcntはmain関数の中で宣言されているのでスタック変数です。
グローバル変数であれば気の利くコンパイラならば初期値は自動的に0になっていることが多いので
うまくいけば x1[cnt]はx1[0]の宣言になりますがスタック変数の宣言時の初期値には何が入っているかわかりません。
int宣言なので下手をすれば 負の値が入っている可能性もあります。

先ずは宣言部分から見直されたらいかがでしょうか

投稿2015/07/14 14:51

Fritha

総合スコア33

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

lang

1 vector<double> x1[cnt], ...

これだとx1の型がvector<double>[]
(double型を格納するvectorクラスの配列,要するに二次元配列)になってしまいます。
後のコードを見る限りこれは意図通りではないと思います。
vector<T>[]を意図して使う場合はこんな感じになります。

lang

1int main(void){ 2 vector<int> x[2]; //vector<int>が格納された配列を生成 3 x[0].push_back(1); //[0]のほうのvector<int>の末尾に1を追加 4 cout <<x[0][0]<<endl; // "1" 5} 6

一次元ならこうです:

lang

1 vector<double> x1, ...

投稿2015/07/15 00:07

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

環境が分からないのでなんともいえないのですが・・・
配列はどのような構造になっていますか? 構造体の配列? ただの整数の配列?

”segmentation foult” が起こっているとすれば、配列の要素数が足りない可能性があります。
(配列にデータを入れようとしたが、そこは確保された領域外だった・・・とか)

64ビットのWindowsなら1Gぐらい確保しても問題ないですよd^^
再度、確保する領域とデータ数が合ってるかどうか確認されたらどうでしょう?

投稿2015/07/14 13:58

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2015/07/14 15:36 編集

行数を数える部分ですが if(fp)がNGの処理が抜けているようです。また、while(c=getc(fp)!=EOF);では、下のブロックに入ったときにcにはEOFが入っています。(;が余計です) あと、getline()を使われたらいかがでしょうか? 1文字ずつ読み込むより早いですよd^^ また、fscanf()よりもgetline()で1行読み込んでsscsnf()を使ったほうが安全です。
guest

0

質問の内容から言えるのは、メモリも配列サイズも有限だ。ということです。
segmentation fault はプログラム実行中に予定の利用範囲を超えちゃったよ、というお知らせなので、有限の資源で切り盛りする考え方を持つ必要があります。
また、C言語はfail-safeも原始的なので、スクリプト言語のようによろしくやって貰おうと思っているとメモリ周りでつまづき易いです。

下記の辺りを確認してください。

・配列サイズを必要充分に確保しているか。
・意図しない配列範囲にアクセスしていないか。
・利用可能なメモリ量に対して、読み込んでいるデータサイズが大きすぎないか。
・動的に確保したメモリがある場合にきちんとリリースできているか。

下記は考える範囲を絞ったり、全部自分で書かずに他にお任せする場合の補足です。

・CSVの読み込みを一括で行っている場合、実行速度は落ちるが一旦行単位にして動作を確認する。
・iostreamや動的配列(std::vectorなど)を使う。
・行数をカウントするだけで良い場合、既存の行数を出力してくれるプログラム(linuxのwcコマンドとか)を呼び出して、結果だけ集める処理を書く。


segmentation faultについては簡単にまとめている方がいらっしゃいましたので、参考までに。

ttp://minus9d.hatenablog.com/entry/20140121/1390314231

投稿2015/07/14 13:57

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/07/14 15:39 編集

コード拝見しました。 ・ハードコードは極力避けた方が後で混乱せずに済みます。 ・std::vector は push_backで要素を動的に増やせます。わざわざ予め要素数を決め込まない方が良いように思います。(処理する個数が固定なら決め込んでも実害ないかもしれません) ・forループで i=17; i < 2000; .. となっている部分などは、ヘッダー17行を削るなら必要ないように思います。vectorに必要な分を格納してあれば、必要回数反復処理するだけです。反復処理にはイテレータも活用しましょう。 …と、ここまで書いておいてこんなことを書くのは微妙かもしれませんが、この処理を書くのでしたら、まずはC++よりスクリプト言語の利用をお勧めします。(敢えてC++の勉強で書かれているようでしたら、読み流してください。) ※個人的には、Pythonなどが良いかと思います。 スクリプトで書いてみて、あまりにも処理が重い、データ処理的にメモリ操作が面倒、やたらにビット操作が必要…という話が出てきたらCで書いてみる。という選択の仕方もあると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問