⾯试题之string转化成double
⼀、⾯试中写的代码
主要思路: 把字符串分为整数、⼩数、符号三个部分
整数部分的规律是: 整数部值 = 整数部值 * 乘值 +当前值 // 整数部分的乘值为10不变
⼩数部分的规律是:⼩数部分值 = ⼩数部分 + 当前值 * (⼩数部分乘值)// ⼩数部分的值不断缩⼩10倍符号部分:判断有⽆'-' 存在
// ConsoleApplication1.cpp : 定义控制台应⽤程序的⼊⼝点。
//
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
double string_to_double(const std::string &str)
{
double dInteger = 0; // 整数部分
double dDecimal = 0; // ⼩数部分
int sign = 1; // 符号
bool bFindPoint = false;
double dCount = 1; // ⼩数部分的值
for (int i = 0 ; i < str.length(); ++i)
{
if (str.at(i) == '-')
{
if (i == 0)
{
sign = -1;
}
else
{
return 0; // error
}
}
else if (str.at(i) == '+')
{
if (i == 0)
{
sign = 1;
}
else
{
return 0; // error
}
}
else if(str.at(i) == '.')
{
if (!bFindPoint)
{
bFindPoint = true;
}
else
{
return 0; // error
}
}
else if (str.at(i) >= '0' && str.at(i) <= '9')
{
if (bFindPoint)
bootstrapped{
dCount *= 0.1;
dDecimal += (dCount * ((int)str.at(i) - '0'));
}
else
{
dInteger *= 10;
dInteger += (int)str.at(i) - '0';
}
}
else
{
return 0; // error
}
}
return sign * (dInteger + dDecimal);
}
int main()
{
std::string str = "-1.23456";
double dValue = string_to_double(str);
std::cout << "string:" << str << std::endl;
std::cout << "double:" << dValue << std::endl;
system("pause");
return 0;
}
⼆、标准库代码
经过⽹上查阅资料才知道,字符串存放double值有很多写法类似:科学计数法、不同进制、三位间隔符(不同的地区 不同的国家 不⼀样)等等,譬如"123 000 157 100" "123,000,157,100" "1.03E+08" "0x15"
第⼀步:把收到的字符串格式化为本地C语⾔表达形式
第⼆步:把格式化后的字符串转化为double
Qt 源码
double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
TrailingJunkMode trailingJunkMode)
{
// 字符不能为空
if (*num == '\0')
{
ok = false;
processed = 0;
return 0.0;
}
ok = true;
// 优先处理未定义或不可表⽰的值--类似 -1开根号
if (qstrcmp(num, "nan") == 0)
{
processed = 3;
return qt_snan();
}
else if ((num[0] == '-' || num[0] == '+') && qstrcmp(num + 1, "nan") == 0)
{
processed = 0;
ok = false;
return 0.0;
}
// 超出浮点数的表⽰范围
if (qstrcmp(num, "+inf") == 0)
{
processed = 4;
return qt_inf();
}
else if (qstrcmp(num, "inf") == 0)
{
processed = 3;
return qt_inf();
}
else if (qstrcmp(num, "-inf") == 0)
{
processed = 4;
return -qt_inf();
}
double d = 0.0;
#if !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
int conv_flags = (trailingJunkMode == TrailingJunkAllowed) ?
double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK :
double_conversion::StringToDoubleConverter::NO_FLAGS;
double_conversion::StringToDoubleConverter conv(conv_flags, 0.0, qt_snan(), 0, 0);
d = conv.StringToDouble(num, numLen, &processed);
if (!qIsFinite(d))
{
ok = false;
if (qIsNaN(d))
{
// Garbage found. We don't accept it and return 0.
processed = 0;
return 0.0;
} else {
// Overflow. That's not OK, but we still return infinity.
return d;
}
}
#else
if (qDoubleSscanf(num, QT_CLOCALE, "%lf%n", &d, &processed) < 1)
processed = 0;
if ((trailingJunkMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d))
{
// Implementation defined nan symbol or garbage found. We don't accept it.
processed = 0;
ok = false;
return 0.0;
}
if (!qIsFinite(d))
{
// Overflow. Check for implementation-defined infinity symbols and reject them.
// We assume that any infinity symbol has to contain a character that cannot be part of a
// "normal" number (that is 0-9, ., -, +, e).
ok = false;
for (int i = 0; i < processed; ++i)
{
char c = num[i];
if ((c < '0' || c > '9') && c != '.' && c != '-' && c != '+' && c != 'e')
{
// Garbage found
processed = 0;
return 0.0;
}
}
return d;
}
#endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
// Otherwise we would have gotten NaN or sorted it out above.
Q_ASSERT(trailingJunkMode == TrailingJunkAllowed || processed == numLen);
// Check if underflow has occurred.
if (isZero(d))
{
for (int i = 0; i < processed; ++i)
{
if (num[i] >= '1' && num[i] <= '9')
{
// if a digit before any 'e' is not 0, then a non-zero number was intended.
ok = false;
return 0.0;
}
else if (num[i] == 'e' || num[i] == 'E')
{
break;
}
}
}
return d;
}
/
/ 格式化字符串---转化为本地C语⾔表达形式
bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOptions number_options, CharBuff *result) const
{
const QChar *uc = str;
int l = len;
int idx = 0;
// 跳过空格键
while (idx < l && uc[idx].isSpace())
{
++idx;
}
if (idx == l) // 字符串为空或者全部为空格
{
return false;
}
// 此时的idx 为第⼀个不为空格的位置
// 检查尾部的空格数
for (; idx < l; --l)
{
if (!uc[l - 1].isSpace())
{
break;
}
}
// 此时的l为从后向前第⼀个不为空格的位置
// idx---------l 为起始不为空和结尾不为空的标志位
int group_cnt = 0; // 分组符号的个数
int decpt_idx = -1; // ⼩数点的位置
int last_separator_idx = -1; // 上⼀个分组符号的位置
int start_of_digits_idx = -1; // 数字起始位
int exponent_idx = -1; // e的位置
while (idx < l)
{
const QChar in = uc[idx];
char out = digitToCLocale(in); // 把单个字符转化为本地c语⾔表达形式
if (out == 0) // 字符0标识空字符--当前表⽰为digitToCLocale未识别到的字符
{
if (in == m_list)
{
out = ';';
}
else if (in == m_percent)
{
out = '%';
}
// for handling base-x numbers
else if (in.unicode() >= 'A' && in.unicode() <= 'Z') // 不同进制
{
out = in.toLower().toLatin1();
}
else if (in.unicode() >= 'a' && in.unicode() <= 'z')
{
out = in.toLatin1();
}
else // 错误字符
{
break;
}
}
else if (out == '.') // ⼩数点
{
// 如果多于⼀个⼩数点或e后的点则转化失败
if (decpt_idx != -1 || exponent_idx != -1)
{
return false;
}
decpt_idx = idx;
}
else if (out == 'e' || out == 'E') // e的位置
{
exponent_idx = idx;
}
if (number_options & QLocale::RejectLeadingZeroInExponent)
{
// 如果存在指数位、且当前的字符不被digitToCLocale识别、且当前不是最后⼀个字符 if (exponent_idx != -1 && out == '0' && idx < l - 1)
{
// 指数后⾯只能为 '+' '-' '0'~'9' 否则就是错误
if (result->last() < '0' || result->last() > '9')
{
return false;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论