修正浮点数转字符串算法
This commit is contained in:
parent
293b440fb7
commit
4f36e20f7a
|
@ -75,7 +75,7 @@ bool Array::Release()
|
|||
|
||||
if(fr && p)
|
||||
{
|
||||
delete (byte*)p;
|
||||
delete[] (byte*)p;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ IList::IList(IList&& list)
|
|||
|
||||
IList::~IList()
|
||||
{
|
||||
if(_Arr && _Arr != Arr) delete _Arr;
|
||||
if(_Arr && _Arr != Arr) delete[] _Arr;
|
||||
}
|
||||
|
||||
void IList::Init()
|
||||
|
@ -73,7 +73,7 @@ void IList::move(IList& list)
|
|||
else
|
||||
{
|
||||
// 如果已有数据区,则释放
|
||||
if(_Arr && _Arr != Arr) delete _Arr;
|
||||
if(_Arr && _Arr != Arr) delete[] _Arr;
|
||||
|
||||
_Arr = list._Arr;
|
||||
list.Init();
|
||||
|
@ -188,7 +188,7 @@ bool IList::CheckCapacity(int count)
|
|||
// 为了安全,按照字节拷贝
|
||||
Buffer(p, sz << 2).Copy(0, _Arr, _Count << 2);
|
||||
|
||||
if(_Arr && _Arr != Arr) delete _Arr;
|
||||
if(_Arr && _Arr != Arr) delete[] _Arr;
|
||||
|
||||
_Arr = (void**)p;
|
||||
_Capacity = sz;
|
||||
|
|
|
@ -479,37 +479,62 @@ bool String::Concat(UInt64 num, int radix)
|
|||
return Concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
/*static char* ftoa(char* str, int len, double num)
|
||||
static char* ftoa(char* str, int len, double num, int prec)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
len = sprintf_s(str, len, "%.8f", num);
|
||||
#else
|
||||
len = sprintf(str, "%.8f", num);
|
||||
#endif
|
||||
// 干掉后面多余的0
|
||||
for (int i = len; i >= 0; i--)
|
||||
// 先计算整数部分,连符号一起计算了
|
||||
// 在逐级计算小数点后
|
||||
int n = (int)num;
|
||||
num -= n;
|
||||
if (num < 0)num = -num;
|
||||
|
||||
// 整数部分
|
||||
ltoa((Int64)n, str, 10);
|
||||
|
||||
if (prec > 0 && num > 0.0)
|
||||
{
|
||||
if (str[i] == '0') str[i] = '\0';
|
||||
// 小数部分
|
||||
int slen = strlen(str);
|
||||
int m = 10;
|
||||
while (--prec > 0) m *= 10;
|
||||
|
||||
str[slen++] = '.';
|
||||
ltoa((Int64)(m*num), str + slen, 10);
|
||||
slen = strlen(str);
|
||||
/*for (int i = 0; i < prec; i++)
|
||||
{
|
||||
num *= 10;
|
||||
n = (int)num;
|
||||
num -= n;
|
||||
str[slen++] = '0' + n;
|
||||
}
|
||||
str[slen] = 0;*/
|
||||
|
||||
// 干掉后面多余的0
|
||||
for (int i = slen - 1; i >= 0 && str[i] == '0'; i--, slen--)
|
||||
{
|
||||
str[i] = '\0';
|
||||
}
|
||||
if (str[slen - 1] == '.') str[slen - 1] = '\0';
|
||||
}
|
||||
|
||||
return str;
|
||||
}*/
|
||||
}
|
||||
|
||||
bool String::Concat(float num, int decimalPlaces)
|
||||
{
|
||||
char buf[20];
|
||||
dtostrf(num, decimalPlaces, buf, sizeof(buf));
|
||||
//dtostrf(num, decimalPlaces, buf, sizeof(buf));
|
||||
//sprintf(buf, "%f", num);
|
||||
//ftoa(buf, num);
|
||||
ftoa(buf, sizeof(buf), num, decimalPlaces);
|
||||
return Concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
bool String::Concat(double num, int decimalPlaces)
|
||||
{
|
||||
char buf[20];
|
||||
dtostrf(num, decimalPlaces, buf, sizeof(buf));
|
||||
//dtostrf(num, decimalPlaces, buf, sizeof(buf));
|
||||
//sprintf(buf, "%f", num);
|
||||
//ftoa(buf, num);
|
||||
ftoa(buf, sizeof(buf), num, decimalPlaces);
|
||||
return Concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
|
|
|
@ -64,29 +64,29 @@ extern "C" {
|
|||
|
||||
INROOT void* operator new(uint size)
|
||||
{
|
||||
mem_printf(" new size: %d ", size);
|
||||
mem_printf(" new(%d,", size);
|
||||
auto p = malloc(size);
|
||||
mem_printf("0x%p ", p);
|
||||
mem_printf("0x%p) ", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
INROOT void* operator new[](uint size)
|
||||
{
|
||||
mem_printf(" new size[]: %d ", size);
|
||||
mem_printf(" new[](%d,", size);
|
||||
auto p = malloc(size);
|
||||
mem_printf("0x%p ", p);
|
||||
mem_printf("0x%p) ", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
INROOT void operator delete(void* p) noexcept
|
||||
{
|
||||
mem_printf(" delete 0x%p ", p);
|
||||
mem_printf(" delete(0x%p) ", p);
|
||||
if (p) free(p);
|
||||
}
|
||||
|
||||
INROOT void operator delete[](void* p) noexcept
|
||||
{
|
||||
mem_printf(" delete[] 0x%p ", p);
|
||||
mem_printf(" delete[](0x%p) ", p);
|
||||
if (p) free(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ static void TestCtor()
|
|||
|
||||
debug_printf("字符串构造函数测试\r\n");
|
||||
|
||||
auto err = "String(cstring cstr)";
|
||||
auto err = "String(cstring cstr)";
|
||||
|
||||
// 默认空字符串,使用内部数据区
|
||||
String str;
|
||||
|
@ -29,7 +29,7 @@ static void TestCtor()
|
|||
assert(str1 == "456", err);
|
||||
assert(str1.GetBuffer() == (void*)"456", err);
|
||||
|
||||
err = "String(const String& str)";
|
||||
err = "String(const String& str)";
|
||||
String str2(str1);
|
||||
assert(str2 == str1, err);
|
||||
assert(str2.GetBuffer() != str1.GetBuffer(), err);
|
||||
|
@ -66,16 +66,18 @@ void TestNum10()
|
|||
String str6((UInt64)331144, 10);
|
||||
assert(str6 == "331144", "String(UInt64 value, int radix = 10)");
|
||||
|
||||
// 默认2位小数,所以字符串要补零
|
||||
// 浮点数格式化
|
||||
String str7((float)123.0);
|
||||
assert(str7 == "123.00", "String(float value, int decimalPlaces = 2)");
|
||||
str7.Show(true);
|
||||
assert(str7 == "123", "String(float value, int decimalPlaces = 2)");
|
||||
|
||||
// 浮点数格式化的时候,如果超过要求小数位数,则会四舍五入
|
||||
String str8((double)456.784);
|
||||
assert(str8 == "456.78", "String(double value, int decimalPlaces = 2)");
|
||||
String str8((double)456.784, 2);
|
||||
str8.Show(true);
|
||||
assert(str8 == "456.78", "String(double value, int decimalPlaces = 4)");
|
||||
|
||||
String str9((double)456.789);
|
||||
assert(str9 == "456.79", "String(double value, int decimalPlaces = 2)");
|
||||
str9.Show(true);
|
||||
assert(str9.StartsWith("456.78"), "String(double value, int decimalPlaces = 2)");
|
||||
}
|
||||
|
||||
void TestNum16()
|
||||
|
@ -111,11 +113,11 @@ static void TestAssign()
|
|||
|
||||
String str = "万家灯火,无声物联!";
|
||||
debug_printf("TestAssign: %s\r\n", str.GetBuffer());
|
||||
str = "无声物联";
|
||||
str = "无声物联";
|
||||
assert(str == "无声物联", "String& operator = (cstring cstr)");
|
||||
|
||||
String str2 = "xxx";
|
||||
str2 = str;
|
||||
String str2 = "xxx";
|
||||
str2 = str;
|
||||
assert(str == "无声物联", "String& operator = (cstring cstr)");
|
||||
assert(str2.GetBuffer() != str.GetBuffer(), "String& operator = (const String& rhs)");
|
||||
}
|
||||
|
@ -126,40 +128,40 @@ static void TestConcat()
|
|||
|
||||
debug_printf("字符串连接测试\r\n");
|
||||
|
||||
auto now = DateTime::Now();
|
||||
auto now = DateTime::Now();
|
||||
//char cs[32];
|
||||
//debug_printf("now: %d %s\r\n", now.Second, now.GetString('F', cs));
|
||||
|
||||
String str;
|
||||
|
||||
// 连接时间,继承自Object
|
||||
str += now;
|
||||
str += now;
|
||||
str.Show(true);
|
||||
// yyyy-MM-dd HH:mm:ss
|
||||
assert(str.Length() == 19, "String& operator += (const Object& rhs)");
|
||||
|
||||
// 连接其它字符串
|
||||
int len = str.Length();
|
||||
int len = str.Length();
|
||||
String str2(" 中国时间");
|
||||
str += str2;
|
||||
assert(str.Length() == len + str2.Length(), "String& operator += (const String& rhs)");
|
||||
|
||||
// 连接C格式字符串
|
||||
str += " ";
|
||||
str += " ";
|
||||
|
||||
// 连接整数
|
||||
len = str.Length();
|
||||
len = str.Length();
|
||||
str += 1234;
|
||||
assert(str.Length() == len + 4, "String& operator += (int num)");
|
||||
|
||||
// 连接C格式字符串
|
||||
str += " ";
|
||||
str += " ";
|
||||
|
||||
// 连接浮点数
|
||||
len = str.Length();
|
||||
str += -1234.8856; // 特别注意,默认2位小数,所以字符串是-1234.89
|
||||
len = str.Length();
|
||||
str += -1234.8856;
|
||||
str.Show(true);
|
||||
assert(str.Length() == len + 8, "String& operator += (double num)");
|
||||
assert(str.Length() == len + 10, "String& operator += (double num)");
|
||||
}
|
||||
|
||||
static void TestConcat16()
|
||||
|
@ -172,7 +174,7 @@ static void TestConcat16()
|
|||
str.Concat((byte)0x20, 16);
|
||||
|
||||
// 连接整数的十六进制,前面补零
|
||||
str += " @ ";
|
||||
str += " @ ";
|
||||
str.Concat((ushort)0xE3F, 16);
|
||||
|
||||
// 连接整数的十六进制(大写字母),前面补零
|
||||
|
@ -192,7 +194,7 @@ static void TestAdd()
|
|||
str = str + 1234 + "#" + R("99xx") + '$' + -33.883 + "@" + DateTime::Now();
|
||||
str.Show(true);
|
||||
// 字符串连加 1234@0000-00-00 00:00:00#99xx
|
||||
assert(str.Contains("字符串连加 1234#99xx$-33.88@"), "friend StringHelper& operator + (const StringHelper& lhs, cstring cstr)");
|
||||
assert(str.Contains("字符串连加 1234#99xx$-33.883@"), "friend StringHelper& operator + (const StringHelper& lhs, cstring cstr)");
|
||||
}
|
||||
|
||||
static void TestEquals()
|
||||
|
@ -216,20 +218,20 @@ static void TestSet()
|
|||
String str = "ABCDEFG";
|
||||
assert(str[3] == 'D', "char operator [] (int index)");
|
||||
|
||||
str[5] = 'W';
|
||||
str[5] = 'W';
|
||||
assert(str[5] == 'W', "char& operator [] (int index)");
|
||||
//debug_printf("%s 的第 %d 个字符是 %c \r\n", str.GetBuffer(), 5, str[5]);
|
||||
|
||||
str = "我是ABC";
|
||||
int len = str.Length();
|
||||
auto bs = str.GetBytes();
|
||||
str = "我是ABC";
|
||||
int len = str.Length();
|
||||
auto bs = str.GetBytes();
|
||||
assert(bs.Length() == str.Length(), "ByteArray GetBytes() const");
|
||||
assert(bs[len - 1] == (byte)'C', "ByteArray GetBytes() const");
|
||||
//assert(bs.GetBuffer() == (byte*)str.GetBuffer(), "ByteArray GetBytes() const");
|
||||
|
||||
// 十六进制字符串转为二进制数组
|
||||
str = "36-1f-36-35-34-3F-31-31-32-30-32-34";
|
||||
auto bs2 = str.ToHex();
|
||||
str = "36-1f-36-35-34-3F-31-31-32-30-32-34";
|
||||
auto bs2 = str.ToHex();
|
||||
bs2.Show(true);
|
||||
assert(bs2.Length() == 12, "ByteArray ToHex()");
|
||||
assert(bs2[1] == 0x1F, "ByteArray ToHex()");
|
||||
|
@ -245,12 +247,12 @@ static void TestSet()
|
|||
assert(str.EndsWith("-32-34"), "bool EndsWith(cstring str)");
|
||||
|
||||
// 字符串截取
|
||||
str = " 36-1f-36-35-34\n";
|
||||
len = str.Length();
|
||||
str = str.Trim();
|
||||
str = " 36-1f-36-35-34\n";
|
||||
len = str.Length();
|
||||
str = str.Trim();
|
||||
assert(str.Length() == len - 2, "String& Trim()");
|
||||
|
||||
str = str.Substring(3, 5).ToUpper();
|
||||
str = str.Substring(3, 5).ToUpper();
|
||||
str.Show(true);
|
||||
assert(str == "1F-36", "String Substring(int start, int _Length)");
|
||||
}
|
||||
|
@ -261,17 +263,17 @@ static void TestMemory()
|
|||
|
||||
debug_printf("字符串内存泄漏测试\r\n");
|
||||
|
||||
int p = 0;
|
||||
int p = 0;
|
||||
{
|
||||
auto arr = new int[4];
|
||||
p = (int)arr;
|
||||
p = (int)arr;
|
||||
|
||||
delete[] arr;
|
||||
}
|
||||
|
||||
{
|
||||
String str = "ABCDEFG";
|
||||
for(int i=0; i<4; i++) str += str;
|
||||
for (int i = 0; i < 4; i++) str += str;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -289,30 +291,30 @@ static void TestCompare()
|
|||
|
||||
debug_printf("字符串比较测试\r\n");
|
||||
|
||||
String str = "abcd";
|
||||
cstring cs = "abcdef";
|
||||
String str = "abcd";
|
||||
cstring cs = "abcdef";
|
||||
|
||||
auto err = "int CompareTo(cstring cstr) const";
|
||||
auto err = "int CompareTo(cstring cstr) const";
|
||||
|
||||
// 因为按照左边长度来比较,所以返回0
|
||||
assert(str.CompareTo(cs) == 0, err);
|
||||
|
||||
err = "bool operator != (cstring cstr) const";
|
||||
err = "bool operator != (cstring cstr) const";
|
||||
assert(str != cs, err);
|
||||
|
||||
// 倒过来试试
|
||||
String str2 = "abcdef";
|
||||
cstring cs2 = "abcd";
|
||||
String str2 = "abcdef";
|
||||
cstring cs2 = "abcd";
|
||||
|
||||
assert(str2.CompareTo(cs2) > 0, err);
|
||||
|
||||
err = "bool operator != (cstring cstr) const";
|
||||
err = "bool operator != (cstring cstr) const";
|
||||
assert(str2 != cs2, err);
|
||||
|
||||
// 不区分大小写
|
||||
String str3 = "ABCD";
|
||||
String str3 = "ABCD";
|
||||
|
||||
err = "bool EqualsIgnoreCase(cstring cstr) const";
|
||||
err = "bool EqualsIgnoreCase(cstring cstr) const";
|
||||
assert(!str3.Equals(cs2), err);
|
||||
assert(str3.EqualsIgnoreCase(cs2), err);
|
||||
assert(str3.EqualsIgnoreCase(String(cs2)), err);
|
||||
|
@ -324,66 +326,66 @@ static void TestSplit(cstring cstr)
|
|||
|
||||
debug_printf("字符串分割测试\r\n");
|
||||
|
||||
String str = cstr;
|
||||
String str = cstr;
|
||||
|
||||
auto err = "StringSplit Split(cstring sep) const";
|
||||
auto err = "StringSplit Split(cstring sep) const";
|
||||
|
||||
int p = -1;
|
||||
auto sp = str.Split(",");
|
||||
int p = -1;
|
||||
auto sp = str.Split(",");
|
||||
assert(sp.Position == p && sp.Length == 0, err);
|
||||
assert(sp, err);
|
||||
|
||||
auto rs = sp.Next();
|
||||
auto rs = sp.Next();
|
||||
|
||||
p = 0;
|
||||
p = 0;
|
||||
|
||||
// 如果分隔符开头,则跳过它
|
||||
if(cstr[0] == ',')
|
||||
if (cstr[0] == ',')
|
||||
{
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
p++;
|
||||
}
|
||||
|
||||
assert(sp.Position == p && sp.Length == 4, err);
|
||||
assert(rs == "+IPD", err);
|
||||
p += 4 + 1;
|
||||
p += 4 + 1;
|
||||
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
assert(sp.Position == p && sp.Length == 1, err);
|
||||
assert(rs.ToInt() == 3, err);
|
||||
p += 1 + 1;
|
||||
p += 1 + 1;
|
||||
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
assert(sp.Position == p && sp.Length == 2, err);
|
||||
assert(rs.ToInt() == 96, err);
|
||||
p += 2 + 1;
|
||||
p += 2 + 1;
|
||||
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
assert(sp.Position == p && sp.Length == rs.Length(), err);
|
||||
assert(rs == "10.0.0.21", err);
|
||||
p += rs.Length() + 1;
|
||||
p += rs.Length() + 1;
|
||||
|
||||
// 更换分隔符
|
||||
sp.Sep = ":";
|
||||
rs = sp.Next();
|
||||
sp.Sep = ":";
|
||||
rs = sp.Next();
|
||||
assert(sp.Position == p && sp.Length == 4, err);
|
||||
assert(rs.ToInt() == 3377, err);
|
||||
p += 4 + 1;
|
||||
p += 4 + 1;
|
||||
|
||||
// 最后一组
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
assert(sp.Position == p && sp.Length == rs.Length(), err);
|
||||
assert(rs == "abcdef", err);
|
||||
//assert(sp.Position + sp.Length == str.Length(), err);
|
||||
|
||||
// 再来一组
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
assert(!sp, err);
|
||||
assert(sp.Position == -2 && sp.Length == 0, err);
|
||||
assert(!rs, err);
|
||||
|
||||
// 到了默认不再查找
|
||||
rs = sp.Next();
|
||||
rs = sp.Next();
|
||||
assert(!sp, err);
|
||||
assert(sp.Position == -2 && sp.Length == 0, err);
|
||||
assert(!rs, err);
|
||||
|
@ -409,10 +411,10 @@ void String::Test()
|
|||
TestCompare();
|
||||
|
||||
// 分隔符
|
||||
cstring cstr = "+IPD,3,96,10.0.0.21,3377:abcdef";
|
||||
cstring cstr = "+IPD,3,96,10.0.0.21,3377:abcdef";
|
||||
TestSplit(cstr);
|
||||
// 以分隔符开头和结尾的情况
|
||||
cstr = ",+IPD,3,96,10.0.0.21,3377:abcdef:";
|
||||
cstr = ",+IPD,3,96,10.0.0.21,3377:abcdef:";
|
||||
TestSplit(cstr);
|
||||
|
||||
debug_printf("字符串单元测试全部通过!");
|
||||
|
|
Loading…
Reference in New Issue