简体   繁体   中英

Convert hex- bin- or decimal string to long long in C++

I have this code which handles Strings like "19485" or "10011010" or "AF294EC"...

long long toDecimalFromString(string value, Format format){
    long long dec = 0;
    for (int i = value.size() - 1; i >= 0; i--) {
        char ch = value.at(i);
        int val = int(ch);
        if (ch >= '0' && ch <= '9') {
            val = val - 48;
        } else {
            val = val - 55;
        }
        dec = dec + val * (long long)(pow((int) format, (value.size() - 1) - i));
    }
    return dec;
}

this code works for all values which are not in 2's complement. If I pass a hex-string which is supposed to be a negativ number in decimal I don't get the right result.

If you don't handle the minus sign, it won't handle itself. Check for it, and memorize the fact you've seen it. Then, at the end, if you'd seen a '-' as the first character, negate the results.

Other points:

  • You don't need (nor want) to use pow : it's just results = format * results + digit each time through.
  • You do need to validate your input, making sure that the digit you obtain is legal in the base (and that you don't have any other odd characters).
  • You also need to check for overflow.
  • You should use isdigit and isalpha (or islower and isupper ) for you character checking.
  • You should use eg val -= '0' (and not 48 ) for your conversion from character code to digit value.
  • You should use [i] , and not at(i) , to read the individual characters. Compile with the usual development options, and you'll get a crash, rather than an exception, in case of error.
  • But you should probably use iterators, and not an index, to go through the string. It's far more idiomatic.
  • You should almost certainly accept both upper and lower case for the alphas, and probably skip leading white space as well.

Technically, there's also no guarantee that the alphabetic characters are in order and adjacent. In practice, I think you can count on it for characters in the range 'A'-'F' (or 'a'-'f' , but the surest way of converting character to digit is to use table lookup.

You need to know whether the specified number is to be interpreted as signed or unsigned (in other words, is "ffffffff" -1 or 4294967295?). If signed, then to detect a negative number test the most-significant bit. If ms bit is set, then after converting the number as you do (generating an unsigned value) take the 1's complement (bitwise negate it then add 1).

Note: to test the ms bit you can't just test the leading character. If the number is signed, is "ff" supposed to be -1 or 255?. You need to know the size of the expected result (if 32 bits and signed, then "ffffffff" is negative, or -1. But if 64 bits and signed, "ffffffff' is positive, or 4294967295). Thus there is more than one right answer for the example "ffffffff".

Instead of testing ms bit you could just test if unsigned result is greater than the "midway point" of the result range (for example 2^31 -1 for 32-bit numbers).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM