固定幅フィールドのテキストデータをifstreamを使って読み込む方法
について教えてください。
計算結果の出力ファイルに1行につき8カラム、20カラム、10カラムのデータがあるとします。
例えば
1.2345671.2345678912345678911.23456789
このデータ行には
1.234567(8カラム幅) 1.234567891234567891(20カラム幅) 1.23456789(10カラム幅)
の3つの固定小数点の数字が書かれています。 上記例のように3つ(複数)の数字が必ずしもホワイトスペース区切りにはなっていないものとします。
これをC++標準ライブラリのifstream や stringstreamを用いて読み込む場合、どのような記述をしなければならないのでしょうか?
たとえば、
int main(int argc, char** argv) {
double data[3];
char buf[BUFSIZ];
ifstream ifs( argv[1] ); // argv[1] には上記データが書かれたファイル名が入っているとします。
stringstream str;
while( !ifs.eof() ) {
if( !ifs.getline( buf, BUFSIZ, '\n' ) ) break;
str << buf;
str >> setw(8) >> data[0] >> setw(20)>> data[1] >> setw(8) >> data[2];
}
cout << data[0] << " " << data[1] << " " << data[2] << endl;
return 0;
}
のような書き方だと、以下のように出力されてしまい、幅を指定しているsetw()が効いていません。
1.23457 0.234568 0.234568
恐らく、'.'がセパレータとして使われて読み込まれているものと思います。
sscanf( buf, "%8lf%20lf%10lf", &data[0], &data[1], &data[2] );
を使うしか方法が無いのでしょうか?
開発環境は ubuntu上のg++ 4.4.3 です。
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
あー、すまん。
おっしゃるとおり、setprecisionは出力方向に有効なのでした。ifstreamにfscanfの書式指定読み込みのようなI/Fはなかったと思う。
fscanfを使わない場合は、自分で処理を書くしかないかなぁ。
今回のケースなら、書いてもしれているので、それがよいかと思います。
書式指定入力を行う場合には、Cのライブラリを使うしかなさそうですね。
今までC++の機能はclassの関係のみ使用して、ライブラリ関係は全てCのライブラリ関数を
使用した20年以上前?の状態でプログラミングしていました。
最近のネット上のサンプルコードを見ると、template<>, ~~stream などが満載のコード
ばかりで、目で追うこともできなくなっていたので、本を1冊購入して勉強し始めたとこです。 「C++標準ライブライリ」とは言っても、Cの標準ライブライリを完全に置き換えるとこまでは意図していないのですね。
No.2
- 回答日時:
たとえばこんなやりかたが。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
template<typename T> void get_value(const string& input, T& v) {
istringstream stream(input);
stream >> v;
}
int main() {
// ↓ファイルから読み出された一行
string input = "1.2345672.3456789012345678903.45678901";
double value;
// 8, 20, 10 に区切ってdouble値を読み出す
get_value(input.substr(0,8),value);
cout << value << endl;
get_value(input.substr(0+8,20),value);
cout << value << endl;
get_value(input.substr(0+8+20,10),value);
cout << value << endl;
}
回答ありがとうございました。
文字列側で区切っておけば良いわけですね。
標準C++ライブラリの解説本を使って勉強し始めたのですが、Stringコンテナにsubstr()なる
メンバー関数があることを、epistemeさんの回答で気付きました。
参考にさせて頂きます。
No.1
- 回答日時:
setwに加え、setprecisionも使おう。
この回答への補足
hidebunさんへ
str >> setw(8) >> setprecision(6) >> data[0] >> setw(20)>> setprecision(18)>> data[1] >> setw(10) >> setprecision(8) >> data[2];
のような書き方をしても全く効果ありません。
解説書によると
setw()は入出力、setprecision()は出力のみのマニピュレータとなっています。
P.S.
質問の記述に誤りがありました。
リスト中に3つあるsetw()の内、最後のsetw(8)はsetw(10)です。
(どちらにしても、効いていませんが・・・・)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- その他(プログラミング・Web制作) pythonでDBのカラム名で取得したオブジェクトの値を表示したい 1 2022/05/13 03:41
- C言語・C++・C# pythonのファイルの並びでの読み込みとリストについて 4 2022/04/13 03:52
- その他(プログラミング・Web制作) Python - Excel で Webからデータを連続取得したいのですが エラーが出ます 1 2023/07/06 20:08
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- Visual Basic(VBA) vbaのループ処理について 6 2022/05/06 15:35
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
value内に変数を入れたい
-
%の計算の仕方
-
クリックの度に加算していくには?
-
3桁区切りのカンマをつけたい...
-
セレクトボックスの初期選択状...
-
VB.NET DateTimeの型について
-
演算対象の数字と演算子を入力...
-
javascriptにてHTMLのhiddenエ...
-
ダミーフォームの内容を送信用...
-
hiddenのvalueの値を変えたい
-
jsで、配列内の文章を改行する...
-
クイズ作成:15個の問題から5個...
-
javaで name=id[?] を指定...
-
ホームページビルダーのスクリ...
-
ループで連続したフォームの値...
-
関数名などの固有名詞(?)を...
-
sessionStorageを調べています。
-
HTML ローカルストレージへの保存
-
自動的に連番生成したURLにリン...
-
複数のsubmitボタンで押された...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
hiddenのvalueの値を変えたい
-
value内に変数を入れたい
-
引数に数値、文字列の混在
-
複数のsubmitボタンで押された...
-
VB.NET DateTimeの型について
-
3桁区切りのカンマをつけたい...
-
javascriptでhiddenに二次元配...
-
フォームで入力した値を別のフ...
-
setIntervalの間隔を途中で変更...
-
jsで、配列内の文章を改行する...
-
Pythonで会員サイトの自動ログ...
-
selectboxのoptionタグのvalue...
-
テキストボックスに入力された...
-
フォーカスすると初期値が消去...
-
ラジオボタンと連動して文字列...
-
セレクトボックスの初期選択状...
-
sessionStorageを調べています。
-
VBAをJavaScriptに変換したいです
-
ダミーフォームの内容を送信用...
-
javascriptで複数の計算を同時...
おすすめ情報