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

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

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

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

Q&A

解決済

2回答

17840閲覧

データファイルからvectorへの値の読み込み

pteryx

総合スコア16

C++

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

0グッド

1クリップ

投稿2016/09/05 14:09

編集2016/09/06 02:10

###発生している問題
プログラミング初心者です。814行2列のデータファイルから値を読み込んでvector配列に格納したいのですが、Segmentation faultになってしまいました。

###該当のソースコード

C++

1#include <iostream> 2#include <cmath> 3#include <vector> 4#include <string> 5#include <fstream> 6 7int main() 8{ 9 std::vector<float> input; //データの値を格納する配列 10 int datanum = 814*2; //データの個数 11 12 std::ifstream fin; 13 14 fin.open("datafile.dat", std::ios::binary); 15 fin.read((char *)&input[0], datanum*sizeof(float)); 16 fin.close(); 17 fin.clear(); 18 19 std::cout << "checkpoint" << std::endl; 20 std::cout << input[0] << std::endl; 21 22 return 0; 23} 24 25```datafile.dat 260.0001 443.916 270.00010202 452.558 280.00010408 461.364 290.00010618 470.334 300.00010833 479.512 310.00011052 488.853 320.00011275 498.358 330.00011503 508.068 340.00011735 517.942 350.00011972 528.02 360.00012214 538.304 370.00012461 548.792 380.00012712 559.442 390.00012969 570.339 400.00013231 581.438 41 42###質問 43"checkpoint"は出力されるのですが、input[0]が出力されずSegmentation faultになってしまいます。原因を特定できず困っています。どうすれば解決するのでしょうか?

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

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

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

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

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

guest

回答2

0

エラー処理もなんもなく、さらっと書けばこんなかんじ。

C++

1#include <iostream> 2#include <fstream> 3#include <iterator> 4#include <vector> 5 6int main() { 7 using namespace std; 8 9 // ↓ この一行でオシマイ。 10 vector<float> input((istream_iterator<float>(ifstream("datafile.dat"))), istream_iterator<float>()); 11 12 // かくにん 13 for ( float item : input ) { 14 cout << item << endl; 15 } 16}

列分割版:

C++

1#include <iostream> 2#include <fstream> 3#include <iterator> 4#include <vector> 5#include <utility> 6 7namespace std { 8 std::istream& operator>>(std::istream& stream, std::pair<float,float>& ff) { 9 return stream >> ff.first >> ff.second; 10 } 11} 12 13int main() { 14 using namespace std; 15 16 vector<pair<float,float>> input((istream_iterator<pair<float,float>>(ifstream("datafile.dat"))), istream_iterator<pair<float,float>>()); 17 18 // かくにん 19 for ( pair<float,float> item : input ) { 20 cout << item.first << '\t' << item.second << endl; 21 } 22}

投稿2016/09/06 02:30

編集2016/09/06 06:15
episteme

総合スコア16614

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

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

pteryx

2016/09/06 02:54

ありがとうございます。こんな簡単に読み込めるんですね。
guest

0

ベストアンサー

こんにちは。

読み込む前に、resize()してstd::vector<>に領域を確保しましょう。
input.resize(datanum);で確保できます。

投稿2016/09/05 14:54

Chironian

総合スコア23272

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

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

pteryx

2016/09/05 15:35

ありがとうございます。resize()したら読み込みできました。 ただ、読み込まれた値がめちゃくちゃで、元のデータを再現しないのです。これについて思い当たる点などありましたらご教授くださるとありがたいです。
Chironian

2016/09/05 15:47

そのような時に疑うべきはファイル・フォーマットと思います。 できれば、単純な値を保存して、それが意図どおりに保存されているか確認すると良いです。 https://ja.wikipedia.org/wiki/%E5%8D%98%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0 を見ると、float型で 1.0 のバイト列は3f 80 00 00となるそうです。 インテルCPU、もしくは、互換CPUなら、00 00 80 3fと並んでいる筈です。 保存したファイルをバイナリ・エディタで見てみましょう。 1.0を保存して、00 00 80 3fになっていないなら、保存側の不具合の筈です。(wikipediaのミスの可能性も一応考慮ください。) そのようになっているのに化けているとしたら、う~ん、ちょっと分かりません。
episteme

2016/09/06 00:54 編集

"814行2列のデータファイル"なんて表現をバイナリファイルで使うかな? テキストデータじゃないですよね? メモ帳かなんかで開けてみて、数値が並んでたらテキスト/バケバケだったらバイナリです。
Chironian

2016/09/06 01:26

epistemeさん。 ああっ、その可能性もありますね。 pteryxさん。 もし、datafile.datがテキスト・ファイル(ソース・ファイルを編集しているエディタで開いて文字化けせずに中身を読める)なら、頭の部分を少し質問に記載してみて下さい。
pteryx

2016/09/06 02:14

datafile.datは普通のdatファイルで、中身を見ることができます。冒頭の15行を記載しました。これを、例えば input[0] = 0.0001, input[1] = 443.916, input[2] = 0.00010202, input[3]= 452.558 .... というように格納したいと思っています。
episteme

2016/09/06 02:19

テキストファイルじゃん!!
Chironian

2016/09/06 02:26

なるほど。 文字列に変換して保存したものを内部データに直接読み込むと化けてしまいます。きちんと文字列から内部データへ逆変換する必要が有ります。(一般に内部データは人が目で読み取れる形式で記録されていません。) そこで、下記で読めると思います。 for (int i=0; i < datanum ; ++i) {   fin >> input[i]; } なお、オープンはtxtモード(std::ios::binaryを指定しない)で行わないと不可解な動作をするかも知れません。
pteryx

2016/09/06 02:51

ありがとうございます。うまく読み込めました。単純にfor文で入れていけばよかったのですね。 お二方とも、ありがとうございました。
episteme

2016/09/06 02:55

for-loopで指定回数回すのはあんま賢くないですよ。 データ数がちょろっと変わっただけでアウトです。
Chironian

2016/09/06 03:05

次のステップはその辺りですね。 データが尽きるまで(EOFになるまで)読むと好ましいです。それが出来るのがコンテナのメリットですしね。 真面目に作るなら、読めたデータが奇数個の時や途中で変換エラーが発生した際のエラー処理も必要になるでしょう。
episteme

2016/09/06 03:51

0列 と 1列 とを組にして扱いたいなら vector<pair<float,float>> input; でしょうしね。
pteryx

2016/09/06 04:02

うーん、いろいろと試しているのですが賢い方法でやろうとするとなかなかうまくいきません。 inputをそのように列を分けて扱い、データ行数が未知の場合に読み込むとなるとどうなるのでしょう?
Chironian

2016/09/06 04:13

列をわけない場合は、簡単です。例えば下記ですね。 while(!fin.eof()) {   float data;   fin > data;   input.push_back(data); } > 賢い方法でやろうとするとなかなかうまくいきません。 epistemeさんの回答のような1ライナーは難易度高いかも。 イテレータって要するにポインタの拡張ですが、中々派手に拡張されているので結構難しいです。
pteryx

2016/09/06 04:59

ありがとうございます。while文でeofまで詰め込むやり方でうまくいきました。 イテレータのやり方はもう少しプログラミングに慣れないと難しいですかね…。 お二方とも、ここまでお付き合いくださいまして、大変ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問