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

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

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

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

Q&A

解決済

4回答

3285閲覧

C++によるテキストファイルからのパラメータ読み込みの方法について

oknd1

総合スコア17

C++

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

0グッド

0クリップ

投稿2017/10/25 13:50

C++を用いて配列を含む、パラメータが保存されたテキストファイルを読み込む処理を行いたいと思っています。
具体的には、例えば以下のようなファイル

#Setting parameters #Set Value1 Value1 = 1 #Set Value2 Value2 = 2.0 #Set Value3 Value3 = 3.0 #Set Array1 Array1 = 1.0 2.0 3.0 #Set Array2 Array2 = 4.0 5.0 6.0

のようなファイルが有ったときに, #のあるコメント行は読み飛ばして, intやdouble型の数値Value1,Value2,Value3と配列Array1,Array2を読み込めるようにしたいと思っています。

色々検索していて見つかった方法の一つとして, 配列がなく一つの行に一つの数値があるだけならば

f = fopen("parameter.txt", "r"); while(fgets(line, 256, f) != NULL){ if((line[0] == '#') || (!strcmp(line, "\n"))) ; else{ sscanf(line, "%s %s %s\n", &name, &equal, &value); if((!strcmp(name, "Value1")) .....

のようにして各行読んでwhileやifを使えばコメントの読み飛ばしやValue1やValue2の識別も可能だと思うのですが, Array1のように空白などのセパレータでわけられた複数の数値を配列として一括に読み込む機能をどうつければ良いのかわからず困っております。また, Array1に入る数値の個数も不明な状態で実行できるようにしたいと思っています。

何か, 良い方法はあるでしょうか。お知恵を貸していただければと思います。
よろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

1.コメントをスキップして一行取り出す関数を作る

C++

1bool ReadLine(string & readline) 2{ 3 while(getline( cin, readline )){ 4 if(readline.find_first_of("#") == string::npos){ 5 break; 6 } 7 } 8 return !cin.eof(); // ファイル読み込みが終了すると偽が返る 9} 10

のようなもの・・・・

2.KSwordOfHasteさんの回答にあるように数値を1つづ切り出す関数を作る。(返り値は読み込んだ数値の数・・・int mysplit(std::string & line, std::vector<double> value)・・・自前のsscanf()のようなもの)

3.vectorを処理する・・・

とか、どうでしょう?
「追記」
エラー処理はまったく考えていません。読み込むデータが自前でないのなら、空行の処理や数値がなかった場合など対応が必要と思います。

投稿2017/10/25 14:36

編集2017/10/25 16:25
cateye

総合スコア6851

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

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

oknd1

2017/10/25 16:57

cateye様 ありがとうございます。 2., 3.の方法で試してみようと思います。 ちなみにデータは自前なのである程度やりやすいようにはデータのフォーマットを変えることもできます。
guest

0

ベストアンサー

こんにちは。

取り敢えず、標準入力から読むだけなら以下のイメージでできます。
読み取ったものを変数に入れる場合は、何をどのようにしまうのかよく検討が必要です。
とりあえず動的配列(実行中に要素数が変わる配列)にはstd::vectorを使うのが常道です。

C++

1#include <iostream> 2#include <string> 3#include <sstream> 4 5int main() 6{ 7 std::string line; 8 while(std::getline(std::cin, line)) 9 { 10 if (line[0] == '#') 11 continue; 12 if (line.find('=') == std::string::npos) 13 continue; 14 15 std::stringstream ss(line); 16 std::string name; 17 ss >> name; 18 ss.ignore(line.size(), '='); 19 std::cout << name << " = "; 20 double temp; 21 while(ss >> temp) 22 { 23 std::cout << temp << " "; 24 } 25 std::cout << "\n"; 26 } 27}

wandboxサンプル

たぶん、初めて見る関数が多数あると思いますが、std::で始まるものは標準ライブラリですので検索すると解説が直ぐに見つかりますので、参考にされて下さい。

投稿2017/10/25 14:29

Chironian

総合スコア23272

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

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

oknd1

2017/10/25 16:56

Chironian様 ありがとうございます。調べながら見てみてなんとなくですがわかりました。 ご指摘の通りstd::vectorを用いるのがセオリーのようなのでそのようにしようと思います。 とりあえず、上げていただいたコードをベースに試してみようと思います。
guest

0

皆様ありがとうございました。
とりあえず望んでいたことはできるようになりましたので、備忘録も兼ねてコードを掲載しておきます。

#include <iostream> #include <string> #include <stdio.h> #include <fstream> #include <sstream> #include <vector> using namespace std; int main() { std::ifstream fin("parameter.txt"); if (!fin) return 1; int value1; double value2; double value2; std::vector<double> vec1; std::vector<double> vec2; double temp; std::string line; while (std::getline(fin, line)) { if (line[0] == '#') continue; if (line.find('=') == std::string::npos) continue; std::stringstream ss(line); std::string name; ss >> name; ss.ignore(line.size(), '='); //std::cout << name << " = "; if (name == "value1") { ss >> value1; } else if (name == "value2") { ss >> value2; } else if (name == "value3") { ss >> lgauss_width; } else if (name == "array1") { while (ss >> temp) { vec1.push_back(temp); } } else if (name == "array2") { while (ss >> temp) { vec2.push_back(temp); } } } }

投稿2017/10/26 12:08

oknd1

総合スコア17

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

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

0

多くの言語で文字列クラスに「split=区切り文字を指定した分割」機能がついてたりしますが、C++のstd::stringにはそれがないのだろうかと思い調べてみるとなさそうだと思いました。

一次資料でなくてすみませんが自分は以下などいくつかのサイトでそうなっているのをみてそう思いました。
http://vivi.dyndns.org/tech/cpp/string.html

自分で作るしかないのだとしたら' 'を探しつつ数字部分を切り出してそれを整数へ変換してvectorに詰め、最終的にvectorを返すという感じにすればよいと思います。そうしてsplitを用意しておけば指定されたパラメータの種類によってスカラー値を取るべきパラメータについてはvectorの要素が1であることを確認した上で先頭要素を値とし、配列を取るパラメーターならvectorの値そのものを用いるといった感じにすればよいと思います。

投稿2017/10/25 14:12

KSwordOfHaste

総合スコア18394

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

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

oknd1

2017/10/25 16:53

KSwordOfHaste様 ありがとうございます。確かに、std::stringにはそのような機能はないのかと思います。 地道な方法ではありますが、ご教授の方法を検討してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問