サンプル入力文字列:
char *str = "12345.567675";
また、小数点以下3桁の精度が必要な場合は、次の出力が必要です。
str = "12345.568";
double
文字列を文字列に変換したり、文字列に戻したりせずにこれを行う方法はありますか?
ええ、高レベルで:
1。「。」を検索します。文字列で。
2.「。」の位置の場合 +3はあなたがした長さよりも小さいです。
3.それ以外の場合は、文字列を「。」の位置に連結します。+ 3.
4.ここでは注意が必要です。次の文字が存在する場合は('。'+ 4)、値が5以上の場合は4.1に移動する必要があります(それ以外の場合は5に移動します)
。文字列を左側にもう1つスペースがある新しい文字列にコピーし(「4」ループで9.9999が10.0000に変更されるため)、その文字列の最後の文字にポインタ(P)を設定します。
4.2。* Pが0から8の場合、それに1を追加し、5に進みます
。4.3。* Pが9の場合は、ゼロに設定し、ポインターを1つ左(-1)に移動して、4.24.4に進み
ます。* Pが'。'の場合、ポインタを1つ左(-1)に移動し、4.2に進みます。
5.小数点の右側にあるすべての0(および必要に応じて小数点自体)を削除すると、完了です!!!
6.すべてを削除し、二重変換方法を使用します。
これは、再帰を使用して行うことができます。
void roundstr(std::string& strp) {
char clast;
char nlast;
int sl(strp.length()), ipos(0);
if (strp[sl - 1] == '.') { // skip the dot
strp.erase(strp.end() - 1);
nlast='.';
roundstr(strp);
return;
}
if (strp[sl - 2] == '.') { // handle dot is next char
ipos = 1;
}
if (sl == 1) { // handle first char
nlast = '0'; // virtual 0 in front of first char
clast = strp[1];
} else {
clast = strp[sl - 1]; // current (last) char
nlast = strp[sl - 2 - ipos]; // next to last char
}
if (clast >= '5') { // need to operate only if meet 5 or larger, otherwise stop
nlast++;
strp.erase(strp.end() - 1); // remove the last char from the string
if (nlast == ':') { // if need to round further
strp.replace(strp.end() - 1 - ipos, strp.end() - ipos, 1, nlast);
clast = '0'; // keep current char value
roundstr(strp);
} else {
strp.replace(strp.end() - 1 - ipos, strp.end() - ipos, 1, nlast);
if(clast==':') clast = '0';
}
}
sl = strp.length();
if (nlast == ':') {
if (ipos == 1) {
strp += '.';
} else {
strp += '0';
}
} else if (nlast=='.' && strp[sl-1] != '.') {
strp += '.';
} else {
if (ipos == 1 && strp[sl-1]!='.') {
strp += '.';
} else {
strp += clast;
}
}
return;
}
そしてあなたはそれをこのように呼びます:
#include <string>
#include <iostream>
#include <iterator>
#include <stdlib.h>
void roundstr(std::string&);
int main(int argc, char* argv[]) {
int p;
std::string strp;
switch (argc) {
case 2:
p = 2;
break;
case 3:
p = atoi(argv[2]);
strp = argv[1];
break;
default:
return 1;
break;
}
std::cout << strp << " " << p << std::endl;
roundstr(strp);
strp.erase(strp.end()-p, strp.end());
std::cout << strp << std::endl;
return 0;
}
ご覧のとおり、余分な数字の削除を処理する必要がありますが、ラッパー関数を作成することは難しくありません。また、構築中にこれを自動的に実行するクラスを作成することも難しくありません。
の代わりにc-stringsを使用すると、これが高速になる可能性もありますstd::string
。ヘビーデューティーシンボリック演算を実行する場合は、すべてstd::string
とchar
を置き換えることをお勧めしchar *
ますが、値の加算を削除するときはさらに注意する必要があります。
文字列内のドットを見つけます。次に、その位置に続く4番目の文字を見つけます。サブ文字列を0からドット+3の位置に戻し、最後の文字を調整します-元の文字列のドットの後の4番目の文字が5以上の場合は、最後の文字をインクリメントします(または、'9の場合は'0'に設定します'そしてprievousなどをインクリメントします)。5未満の場合は、何もせずに元の文字列のサブ文字列のみを返します。
フロートに変換しただけではパフォーマンスに影響はないと思いますが、例えば)boost::format
を使って丸めてください。
これにより、最初にフロートにキャストされます。
int main()
{
std::string f = "12345.567675";
std::ostringstream ss;
float x = boost::lexical_cast<float>(f);
ss << std::fixed << std::setprecision(3);
ss << x;
std::string s = ss.str();
std::cout << s << "\n";
return 0;
}
結果は次のとおりです。
./a.out
12345.567
常にドットとその後ろに少なくとも3桁あると仮定すると、次のようになります。
char *str = "12345.567675";
char *p = str;
while ( *p != '.' )
{
printf( "%c", *p++ );
// find a dot
}
for ( int i = 0; i < 4; i++ )
{
printf( "%c", *p++ );
}