Win XP VC++6 MFC
カンマ付き文字列からdouble型の値を取り出す
目的のものです
少数点以下のレングスは不定(double型で扱える範囲内)
整数部は符号を含め18桁以内
例)
(引数)KString → 戻り値
”-123,456.89” → -123456.89
”\-123,456.89” → -123456.89
”\-123,456.89001” → -123456.89001
”abc-123,456.81” → -123456.81
こんなコード書きました(hogehoge.DLL)
double hogehoge::COR_KStoDouble(CString *KString)
{
int PT_SZ;
int PT_INDT_IDX;
int PT_OTDT_IDX;
double m_Anser;
char *m_Str = new char[KString->GetLength() + 1];
PT_SZ = KString->GetLength();
for(PT_OTDT_IDX = 0;PT_OTDT_IDX < PT_SZ;PT_OTDT_IDX++){
*(m_Str + PT_OTDT_IDX)=' ';
}
*(m_Str + PT_OTDT_IDX)='\0';
PT_OTDT_IDX = PT_SZ -1;
for(PT_INDT_IDX = PT_SZ - 1;PT_INDT_IDX > -1;PT_INDT_IDX--){
----------特に ここから ---------------
if(KString->GetAt(PT_INDT_IDX) =='-'||
KString->GetAt(PT_INDT_IDX)=='.'||
KString->GetAt(PT_INDT_IDX)=='0'||
KString->GetAt(PT_INDT_IDX)=='1'||
KString->GetAt(PT_INDT_IDX)=='2'||
KString->GetAt(PT_INDT_IDX)=='3'||
KString->GetAt(PT_INDT_IDX)=='4'||
KString->GetAt(PT_INDT_IDX)=='5'||
KString->GetAt(PT_INDT_IDX)=='6'||
KString->GetAt(PT_INDT_IDX)=='7'||
KString->GetAt(PT_INDT_IDX)=='8'||
KString->GetAt(PT_INDT_IDX)=='9' ) {
----------ここまでの判断方法を何とかしたい---------
*(m_Str + PT_OTDT_IDX) = KString->GetAt(PT_INDT_IDX);
PT_OTDT_IDX--;
}
}
m_Anser = atof((const char *)m_Str);
delete m_Str;
return m_Anser;
}
STLの学習はしていませんが使って簡単になるなら教えてください
多少変なコーディングあるけど、独学なのでご容赦ください
なお、使い方の間違いもご指摘いただけるとありがたいです
コンパイルはとおり、実行も可能なコードです
例に載せた内容の結果は取得できています
よろしくお願いします
VC++7 で動作確認しました。
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <functional>
// 余分な文字 すなわち-.0123456789以外の文字に対し true を返す
struct not_numeric : std::unary_function<char,bool> {
bool operator()(char x) const {
static std::string numeric = -.0123456789;
return numeric.find(x) == std::string::npos;
}
};
int main() {
std::string input = \\-123,456.789;
std::string result;
// inputから余分な文字を抜いたresultを作る
std::remove_copy_if(input.begin(), input.end(),
std::back_inserter(result), not_numeric());
std::cout << '[' << result << ']' << std::endl;
return 0;
}
επιστημη さん 早々のご回答ありがとうございます
C++の基礎が出来ていない私ですが
ご掲示いただいたコードを参考に学習させていただきます
ここで「済み」つけたいところですが
自分なりにどう取り込めるか試してみてからにします
> std::remove_copy_if(input.begin(), input.end(),
> std::back_inserter(result), not_numeric());
これで何でresultがdouble型で四則演算可能な値として取得出来るのか、
私自身わかっていないのも理由のひとつです
今晩帰ってきてから、早速試してみたいと思います
ありがとうございました
ごめんなさい「四則演算可能な値」なんていってませんでしたね
istringstreamを使えば文字列からの変換は簡単です
#include <iostream> //cout cin
#include <string> //string
#include <sstream> //istringstream
int main()
{
std::string str = -3.14;
std::istringstream iss(str);
double value;
iss >> value;
std::cout << value << std::endl;
return 0;
}
> istringstreamを使えば文字列からの変換は簡単です
なるほど。じゃ併せ技で。
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <functional>
// 余分な文字 すなわち-.0123456789以外の文字に対し true を返す
struct not_numeric : std::unary_function<char,bool> {
bool operator()(char x) const {
static std::string numeric = -.0123456789;
return numeric.find(x) == std::string::npos;
}
};
int main() {
std::string input = \\-123,456.789;
// 余分な文字を取り除き、ストリームに流し込む
std::stringstream strm(input);
std::remove_copy_if(input.begin(), input.end(),
std::ostream_iterator<char>(strm),
not_numeric());
// ストリームからdoubleで吸い出す
double result;
strm >> result;
std::cout << '[' << std::setprecision(9) << result << ']' << std::endl;
return 0;
}
いたたた、一箇所ちょんぼ。
// 余分な文字を取り除き、ストリームに流し込む
×: std::stringstream strm(input);
○: std::stringstream strm;
失礼ぶっこきました。
おっと、読み流してた...
>> std::remove_copy_if(input.begin(), input.end(),
>> std::back_inserter(result), not_numeric());
> これで何でresultがdouble型で四則演算可能な値として取得出来るのか、
> 私自身わかっていないのも理由のひとつです
できません(やってません)よ。余分な文字を抜いた文字列を作っただけです。
文字列から数値への変換はどうにでもすればいい。
出来ました「Kazuki さん επιστημη さん」ありがとうございました
結果
--------------------SSMCORE.h------------------
#include imm.h
#include <iostream>
#include <functional>
#include <algorithm>
#include <sstream>
class AFX_EXT_CLASS SSMCORE
{
public:
SSMCORE();
~SSMCORE();
・
・
・
// カンマ、少数付き文字列をdoubleに変換
double COR_KStoDouble(CString *);
private:
・
・
・
struct not_numeric : std::unary_function<char,bool> {
bool operator()(char x) const {
static std::string numeric = -.0123456789;
return numeric.find(x) == std::string::npos;
}
};
};
--------------------SSMCORE.cpp------------------
double SSMCORE::COR_KStoDouble(CString *KString)
{
double result;
std::string input = *KString;
std::stringstream strm;
std::remove_copy_if(input.begin(), input.end(),
std::ostream_iterator<char>(strm),
SSMCORE::not_numeric());
// ストリームからdoubleで吸い出す
strm >> result;
return result;
}
--------------------------------------------------
まだ単純に取り込んだだけで、
>struct not_numeric : std::unary_function<char,bool>
がなんでこう言う定義になっているかわかっていないので
勉強します
>-.0123456789
これだけはわかりますけど
次のステップ
doubleがたを\-123,123.01にすることなので
自力で(本屋さんへ行って STLの本かって)勉強して
やってみたいと思います、本当にありがとうございました
COBOLプログラマーがC++やるの大変です
最初に掲示したのだってコーディング・コンパイル・デバック
に5時間くらいかかって作ってますから
頭の中は 2×3は2+2+2でそのまま
for(i=1;i<3;i++){a=a+2]
のような頭ですから...
std::stringを持ち出すまでもなかったかな。
remove_copy_if / remove_if は char[] に対しても
使えるんだし。
> std::stringを持ち出すまでもなかったかな。
#include <afx.h>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
using namespace std;
struct not_numeric {
bool operator()(char x) const {
static const char numeric[] = -.0123456789;
return std::find(numeric, numeric+12, x) == numeric+12;
}
};
double str2double(CString* KString) {
const char* source = static_cast<const char*>(*KString);
char buffer[128]; // 大きさテキトー
*std::remove_copy_if(source, source+strlen(source),
buffer, not_numeric()) = '\0';
return atof(buffer);
}
int main() {
CString str = -\\123,456.789;
std::cout << std::setprecision(12) << str2double(&str);
return 0;
}