示例输入字符串:
char *str = "12345.567675";
如果我需要小数点后3位的精度,那么所需的输出:
str = "12345.568";
有没有办法在不将字符串转换为double
并返回字符串?
答案 0 :(得分:2)
答案 1 :(得分:1)
您可以使用递归来完成此操作。
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 *
,但在删除添加值时应该更加小心。
答案 2 :(得分:0)
在字符串中找到点。然后,找到该位置后的第四个字符。将子字符串从0返回到点+3的位置,然后调整最后一个字符 - 如果原始字符串中的点后第四个字符大于或等于5,则增加最后一个字符(或设置为'0',如果'9 '并增加prievous等等)。如果它小于5 - 什么都不做,只返回原始字符串的子串。
虽然,我认为如果你只是将它转换为浮点数就不会达到性能,请使用(例如)boost::format
将其四舍五入。
答案 3 :(得分:0)
首先将它转换为浮动。
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
答案 4 :(得分:-2)
假设你总是有一个点,后面至少有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++ );
}