Reputation: 11
I have a simple function that takes a string of digits and turns them into a floating-point number, the function is underneath:
float convertStrToFloatNumber (std::string n) {
// Converts the number n to a float in the form of 000.000
if (6 - n.length() > 0) {
// The representation is with trailing zeros
n.append(6 - n.length(), '0');
}
// Insert . at the 3. spot
n.insert(3, ".");
return strtof((n).c_str(), 0);
}
How ever i throws the following exception when run with the input "030000"
:
"terminate called after throwing an instance of 'std::length_error' what(): basic_string_M_repalce_aux" what im really interested in is understanding what the last part of the error means.
Upvotes: 0
Views: 4397
Reputation: 66441
Since n.length()
is unsigned, 6
is promoted to the same unsigned type, and when the length is greater than six the subtraction will wrap around and produce a huge positive number.
The most robust (and shortest) solution is to avoid the subtraction completely;
if (n.length() < 6)
{
n.resize(6, '0');
}
Upvotes: 0
Reputation: 22334
The issue does not occur for "030000"
, but for any string longer than 6 characters.
std::string::length()
returns unsigned type. Due to integral promotion rules, 6
gets promoted to unsigned type and you perform subtraction on unsigned types. Underflow on unsigned types result in wraparound, so 0 - 1u
is equal to std::numeric_limits<unsigned>::max()
(if unsigned
is 32-bit, then it's equal to 2^32 - 1
= 4294967295
)
You can simply change the logic of condition:
if (n.length() < 6)
Or cast the length
to signed type:
if (6 - static_cast<int>(n.length()) > 0)
Upvotes: 3