ファイル読込処理をすっきりしたいのですが – 固定ページ 2 – プログラミング – Home

ファイル読込処理をすっきりしたいのです...
 
通知
すべてクリア

[解決済] ファイル読込処理をすっきりしたいのですが

固定ページ 2 / 3

Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> Container& operator+(const Container& line) const
> {
> static Container temp;

将来ハマる可能性(並列実行したりとか)も考えると、
汎用的に作るなら素直に実体を返した方がよくないですか。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 14年前
投稿: 40
 

> 「'_'で開始する識別子はコンパイラが予約語として使用できる」ので非推奨だった
> と思ったけど、今、調べたら「'_'二つで始まる、または'_'に続いて大文字で始ま
る」
> ってのしか見つからない。本当の所はどうなんでしょうね。

「本当の所」が知りたいなら規格にあたればいいやん。
C++ working draft N3090 によると:

17.6.3.3.2 Global names [global.names]
1 Certain sets of names and function signatures are always reserved to the
implementation:
— Each name that contains a double underscore _ _ or begins with an
underscore followed by an uppercase
letter (2.12) is reserved to the implementation for any use.
— Each name that begins with an underscore is reserved to the implementation
for use as a name in the
global namespace.

なので '_'から始まる名前は予約されてて、僕らが使っちゃダメ。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 14年前
投稿: 40
 

> Container& operator+(const Container& line) const
> {
> static Container temp;
> ...
> return temp;
> }

...ダメダメじゃねぇの?


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> なので '_'から始まる名前は予約されてて、僕らが使っちゃダメ。

> Each name that begins with an underscore is reserved to the implementation
> for use as a name in the global namespace.

ご自身でも引用されているように、__ならばany useなのでご指摘どおりですが、
_で始まって大文字が続かない名前は *グローバルネームスペース内で*
予約されてるだけですから(ISO/IEC 14882:2003でも一緒です)、
それ以外についてはmaruさんの発言が正しいかと思いますが…。

# 但し、環境依存のヘッダやらがマクロ定義とかしてる可能性があったりするわけで、
# 使わない方が安全だとは思います。


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

すみません、誤読してましたので訂正です。

> 「'_'二つで始まる、または'_'に続いて大文字で始まる」

アンダスコア二つの時は アンダスコア二つで始まる必要はない
(途中や最後にあっても予約される)ので、正しいと言い切れませんでした。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 14年前
投稿: 40
 

> _で始まって大文字が続かない名前は *グローバルネームスペース内で*
> 予約されてるだけですから(ISO/IEC 14882:2003でも一緒です)、
> それ以外についてはmaruさんの発言が正しいかと思いますが…。

ええ。とはいえ'わざわざ'使う合理的な理由はなさげっすねー。


返信引用
初心者++ になりたい
 初心者++ になりたい
(@初心者 になりたい)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

hirocco さんお世話になります、ツッコミを入れるほどの器量はありませんが
他の方が書かれていた、初期化子リストによる、コンストラクタの初期化程度しか、
気づきませんでした。ことεπιστημη 氏による
> Container& operator+(const Container& line) const
> {
> static Container temp;
> ...
> return temp;
> }
この部分ですが、なぜだめなのかさえ、理解できません・・・・
さて。
掲示して頂いた、コードですが、どストレートで、コンストラクタに数値と、
文字列 を持たせるというアイデアでユニークだと思います、勉強になります。
私は、templateクラスを用いて文字列、数値のキャストを実装してみました
肝のlexical_cast クラスは、επιστημη 氏の「C++テンプレートテクニック」
からの引用となります。

// lexical_cast.h
#pragma once
#include <sstream>
#include <boost/lexical_cast.hpp>

template <class To, class From>
To lexical_cast(From from)
{
To result;
std::stringstream ss;
ss << from;
ss >> result;
return result;
}

template <class From>
class lexical_cast_t {
From from_;
public:
lexical_cast_t (From from)
:from_(from){}
template <class To>
operator To() const
{
return lexical_cast<To>(from_);
}
};

template <class From>
lexical_cast_t<From> lexical(From from)
{
return lexical_cast_t<From>(from);
}

// Container.h
#pragma once
#include stdafx.h
#include <fstream>
#include <string>

template <typename T, size_t N=8>
class Container
{
public:
T m[N];
Container<T> operator+(const Container<T>& rhs) const
{
Container tmp;
for(int i=0; i<N; ++i)
tmp.m[i] = tmp.m[i] + rhs.m[i];
return *this;
}

Container<T> operator=(const Container<T>& rhs) const
{
Container tmp;
for(int i=0; i<N; ++i)
tmp.m[i] = rhs.m[i];
return *this;
}

Container(void){}
~Container(void){}
};

// Container.cpp
#include <iostream>
#include Container.h
#include lexical_cast.h

using namespace std;

int main(void)
{
Container<string> container;

const int DATA_MAX = 8;
char buffer[20];

//文字列データをコンテナいれる

for(int i = 0; i < DATA_MAX; ++i)
{
sprintf(buffer,0.%1.1x,i);
container.m[i] = buffer;
}

// コンテナクラスで+ 演算を行うと、予想通り単なる文字列の結合が行われ
る。
container.m[0] = ";
container.m[0] = container.m[1] + container.m[2];
cout << 0.1+0.2 文字列結合処理結果 << endl;
cout << container.m[0] << endl;

// そこでlexical クラスを使い、std::string → doubleの変換を行う。
double dlhs = lexical(container.m[1]);
double drhs = lexical(container.m[2]);
double result = dlhs + drhs;
cout << 0.1+0.2 数値演算処理結果 << endl;
cout << result << endl;

return 0;
}


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 14年前
投稿: 40
 

>> Container& operator+(const Container& line) const
>> {
>> static Container temp;
>> ...
>> return temp;
>> }
> この部分ですが、なぜだめなのかさえ、理解できません・・・・

struct hoge {
int val;
hoge(int v) : val(v) {}
hoge(const hoge& h) : val(h.val) {}

hoge& operator+(const hoge& h) {
static hoge result(0);
result.val = val + h.val;
return result;
}
};

#include <iostream>

int main() {
hoge one(1), two(2), three(3);
hoge& five = two + three;
hoge six = one + five;
std::cout << five.val << std::endl; // こいつまで6になる
std::cout << six.val << std::endl;
}

あるいはマルチスレッド環境だとリエントラントじゃないのでイッパツでコケます。


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> Container<T> operator+(const Container<T>& rhs) const
> {
> Container tmp;
> for(int i=0; i<N; ++i)
> tmp.m[i] = tmp.m[i] + rhs.m[i];
> return *this;
> }
>
> Container<T> operator=(const Container<T>& rhs) const
> {
> Container tmp;
> for(int i=0; i<N; ++i)
> tmp.m[i] = rhs.m[i];
> return *this;
> }

tmpの結果が使われていないようですが…。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> 「本当の所」が知りたいなら規格にあたればいいやん。
そりゃそうなんですが、その規格を探せていないもんで。orz

standardってdraftの段階では公開されているんだけど、制定されるとお金を出して
購入しないと手に入らないものが多くて。まあ、著作権の問題から何だろうけど。

と、言い訳を言ってみる。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 14年前
投稿: 40
 

>> 「本当の所」が知りたいなら規格にあたればいいやん。
> そりゃそうなんですが、その規格を探せていないもんで。orz

Working draft N3090
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3090.pdf


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

JIS版(日本語)でいいなら、以下からX3014が閲覧のみ可能。
http://www.jisc.go.jp/


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> CString* _data;
> int _size;
自力でnew[]/delete[]するならメンバにstd::vector<CString>でも
大差ないように思いますし、その方がすっきりするのでは。

…とか考え出すとtypedef std::vector<std::string>でも大差ないか、となって、
そもそもクラスは必要ですか、というところに至りそうですが。
> ということは、クラスにすること自体が冗長かな?www

元コードにしても、一行=8の実装が switch(num % DATA_MAX)でよいくらいの制限で、
非常に大きなデータ数を扱うなど固定サイズ化によるの性能改善を意識しないならば、
一番素直なのはstd::vector<std::vector<std::string> >にでも
(せいぜいreserve程度で)全部つんでしまうのがありかなぁと。

ちゃんと動作確認してませんが、Containerクラス作らない版?

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <boost/tokenizer.hpp>
#include <vector>

using namespace std;

template<typename T>
struct to
{
// tokenizerも使ってますし、boost::lexical_castでもいいとは思います。
T operator()(const std::string& str)
{
T tmp = T();
std::istringstream iss(str);
iss >> tmp;
return tmp;
}
};

template<> // std::string -> std::wstring等も用意した方がいいかも。
struct to<std::string>
{
std::string operator()(const std::string& str)
{
return str;
}
};

int main(void)
{
typedef boost::char_separator<char> char_separator;
typedef boost::tokenizer<char_separator> tokenizer;

static const int DATA_MAX = 8;

try
{
typedef std::string type;
// typedef double type; どちらなりと

vector<vector<type> > vcontainer;

ifstream ifs(d:/work/0301.csv);
if( !ifs || !ifs.is_open()) return -1;

char_separator sep(,, ", boost::keep_empty_tokens);
for(string line; getline(ifs,line); /**/)
{
vector<type> container;
container.reserve(DATA_MAX);

tokenizer tokens(line, sep);
// stringにするだけならcopyでもいいのですが。
std::transform(tokens.begin(), tokens.end(),
std::back_inserter(container), to<type>());
vcontainer.push_back(container);
}
}
catch(...) {
;// 握りつぶして捨ててるだけ
}

return 0;
}


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

typedef double type;に変えるとdoubleのvectorのvectorができる。

# でも簡単に動かしてみたら(doubleとか関係なく)、
# boost::keep_empty_tokensにしてるとtokenizerで余分な要素が取れちゃうっぽい。
# 何だろ。(XPpro,VC2008,boost1.45.0)


返信引用
初心者++ になりたい
 初心者++ になりたい
(@初心者 になりたい)
ゲスト
結合: 14年前
投稿: 7
Topic starter  

皆様お世話になります。
επιστημη さん
理解できました。このような場合、static にしてしまうと問題がありますね。
Ban さん
>tmpの結果が使われていないようですが…。
うまく説明できないのですが、私がtemplate クラスにこだわるのは、
template の柔軟さと、クラスの強力なコンストラクタの力を合わせて、取得する
データの型を判別して、実装者が欲する型のインスタンスを、多態的に
生成できないのだろうか?という発想からです。
>元コードにしても、一行=8の実装が switch(num % DATA_MAX)でよいくらいの制限で、
>非常に大きなデータ数を扱うなど固定サイズ化によるの性能改善を意識しないならば、
>一番素直なのはstd::vector<std::vector<std::string> >にでも
>(せいぜいreserve程度で)全部つんでしまうのがありかなぁと。
たしかにそうですね、紆余曲折、シンプルにたどり着く、それもありだと思います。
一旦解決とさせていただきます。


返信引用
固定ページ 2 / 3

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました