I've found a problem with the strtod method which I've used all this time. First of all it doesn't understand non-point decimal separator, so I've forced to use this:
std::replace(sSource.begin(), sSource.end(), getDecimalSeparator(), '.');
But no I've found another problem and didn't found how to resolve it yet. If the value is negative and the thousands separator is a point ("."), strtod return 0 and _EndPtr points to the start of the string:
// PRECONDITIONS:
// * digit grouping symbol (thousands separator) = "."
// * decimal symbol = ","
// * digital grouping = "123.456.789"
// * negative sign symbol = "-"
// * negative number format = "- 1,1"
// * OS WinXP SP2
// * the rest doesn't matter
double parse(const char* cszValue, char** szStop)
{
// NOTE: error handling code has been removed to simplify the sample
return strtod(sSource.c_str(), szStop);
}
//...
char* szStop = NULL;
double dVal = 0.0;
dVal = parse("123.45", &szStop); // works!
// All the next DON'T WORK!
dVal = parse("123,45", &szStop); // dVal == 123.0 szStop == ",45"
dVal = parse("- 123.45", &szStop); // dVal == 0.0 szStop == "- 123.45"
// the same for "- 123,45"
dVal = parse("1.123.45", &szStop); // dVal == 1.123 szStop == ".45"
// the same for "1.123,45"
dVal = parse("1 123.45", &szStop); // dVal == 1 szStop == " 123.45"
// the same for "1 123,45"
dVal = parse("- 1 123,45", &szStop); // dVal == 0 szStop == start of the string
// the same for "- 1 123.45", "- 1.123,45", "- 1.123.45"
There are the questions:
What I doing wrong? (answered)
Why strtod fails if the decimal separator formatted according to local settings? (answered)
Even if I'll replace current decimal separator with a point (".") and remove all thousand separators, how to parse a negative value? Detect a negative sing, remove it, parse the value as a positive number and reverse the negative sign after that?