もっとスマートなコーディングありませんか? – プログラミング – Home

もっとスマートなコーディングありません...
 
通知
すべてクリア

[解決済] もっとスマートなコーディングありませんか?


wood
 wood
(@wood)
ゲスト
結合: 23年前
投稿: 895
Topic starter  

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の学習はしていませんが使って簡単になるなら教えてください
多少変なコーディングあるけど、独学なのでご容赦ください
なお、使い方の間違いもご指摘いただけるとありがたいです

コンパイルはとおり、実行も可能なコードです
例に載せた内容の結果は取得できています

よろしくお願いします


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

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;
}


返信引用
wood
 wood
(@wood)
ゲスト
結合: 23年前
投稿: 895
Topic starter  

επιστημη さん 早々のご回答ありがとうございます
C++の基礎が出来ていない私ですが
ご掲示いただいたコードを参考に学習させていただきます

ここで「済み」つけたいところですが
自分なりにどう取り込めるか試してみてからにします

> std::remove_copy_if(input.begin(), input.end(),
> std::back_inserter(result), not_numeric());
これで何でresultがdouble型で四則演算可能な値として取得出来るのか、
私自身わかっていないのも理由のひとつです

今晩帰ってきてから、早速試してみたいと思います
ありがとうございました

ごめんなさい「四則演算可能な値」なんていってませんでしたね


返信引用
Kazuki
 Kazuki
(@Kazuki)
ゲスト
結合: 22年前
投稿: 41
 

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;
}


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

> 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;
}


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

いたたた、一箇所ちょんぼ。

// 余分な文字を取り除き、ストリームに流し込む
×: std::stringstream strm(input);
○: std::stringstream strm;

失礼ぶっこきました。


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

おっと、読み流してた...

>> std::remove_copy_if(input.begin(), input.end(),
>> std::back_inserter(result), not_numeric());
> これで何でresultがdouble型で四則演算可能な値として取得出来るのか、
> 私自身わかっていないのも理由のひとつです

できません(やってません)よ。余分な文字を抜いた文字列を作っただけです。
文字列から数値への変換はどうにでもすればいい。


返信引用
wood
 wood
(@wood)
ゲスト
結合: 23年前
投稿: 895
Topic starter  

出来ました「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]
のような頭ですから...


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

std::stringを持ち出すまでもなかったかな。
remove_copy_if / remove_if は char[] に対しても
使えるんだし。


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

> 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;
}


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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