-1

Possible Duplicate:
How to convert a number to string and vice versa in C++

How do I convert a char array to integer/double/long type -atol() functions?

Community
  • 1
  • 1
Joe Joeansjen
  • 75
  • 1
  • 2
  • 6
  • 1
    Do you mean *minus* `atol` functions? Like, without using them? – Wyatt Anderson Dec 04 '11 at 15:42
  • What do you mean as "convert"? Do you want to parse the string number representation stored in the string? Do you want to represent character numeric codes in your integer? – Vlad Dec 04 '11 at 15:43

5 Answers5

10

Either Boost.LexicalCast:

boost::lexical_cast<int>("42");

Or (C++11):

std::stoi("42");

Also, don't use char arrays unless it's interop. Use std::string instead. Also don't ever use ato* functions, even in C, they're broken as designed, as they can't signal errors properly.

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
5

Writing such a function yourself is a great exercise:

unsigned parse_int(const char * p)
{
    unsigned result = 0;
    unsigned digit;
    while ((digit = *p++ - '0') < 10)
    {
        result = result * 10 + digit;
    }    
    return result;
}

Of course, you should prefer existent library facilities in real world code.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • There are many security flaws in this function. – AlexTheo Dec 04 '11 at 16:07
  • @Alex: I'd be glad to hear about them. – fredoverflow Dec 04 '11 at 16:12
  • 1) NULL as argument 2) array which contains characters < '0' in ascii table 3) this method is based on ascii table so it is not portable for a first time. – AlexTheo Dec 04 '11 at 16:18
  • 1
    @AlexTheodoridis: "not portable" isn't the same as "many security flaws". If the function is called with NULL as its argument, it will crash immediately. Is that a security flaw? – jalf Dec 04 '11 at 16:21
  • @jalf In general you are right. – AlexTheo Dec 04 '11 at 16:22
  • @AlexTheodoridis: but specifically, I'm wrong? I'm sorry, I don't understand what you mean. – jalf Dec 04 '11 at 16:23
  • 1
    @Alex: 1) So? There are many C library functions that invoke undefined behavior when being passed a NULL pointer, for example `strlen`. I wouldn't call that a security flaw. 2) I am doing unsigned comparison. `(digit = *p++ - '0')` will produce values bigger than 10 for characters below `'0'`. 3) Every real world character encoding has consecutive digits, even EBCDIC. – fredoverflow Dec 04 '11 at 16:23
  • I mean the case 3. If your program go to crash in case of invalid argument I think that this is an problem. – AlexTheo Dec 04 '11 at 16:25
  • @FredOverflow sorry I can't help you if don't see security flaws in this code. in case of characters <0 it will produce a wrong output in any case this is a problem. – AlexTheo Dec 04 '11 at 16:28
  • @AlexTheodoridis: wait, you can see (multiple) security flaws in this code, but are unable to help others see what they are? – jalf Dec 04 '11 at 16:29
  • @Alex: Let's take the string `"123!"` as an example. My function will parse the `123` and then stop, because `'!' - '0' = 33 - 48 = 4294967281u` which is obviously not smaller than 10. Your claims can be refuted with a simple test: `std::cout << parse_int("123!") << '\n';` does indeed print `123`. – fredoverflow Dec 04 '11 at 16:31
  • @Alex: How is that a problem? An input with characters < `0` is wrong anyway. – Xeo Dec 04 '11 at 16:32
  • @jalf ok lets except the case 1 for a NULL ptr but in case if your function generate unexpected output which can produce unexpected behavior in your code I think is a security flaw. I wrote 3 problems in this case but no problem let's upvote this post :D – AlexTheo Dec 04 '11 at 16:33
  • 1
    @Alex: When exactly does my function generate "unexpected output"? Please provide an example input string, the expected output, and the actual (erroneous) output. – fredoverflow Dec 04 '11 at 16:36
  • 1
    @AlexTheodoridis Hmm it crashes when passing in NULL. Maybe...? we could...? not pass NULL? We shouldn't really expect the user of this function to be dumber than he is. If he treats a NULL pointer as a C string, this function really is his least problem. – Christian Rau Dec 04 '11 at 16:37
  • @FredOverflow finally in case if your system doesn't use ascii table. But for invalid input like ( "123a") it will generate 123 in this case I think that function must inform user about incorrect input. But with more though I see that is not so big problem but it is depends on the system.... – AlexTheo Dec 04 '11 at 16:45
  • This code depends on the system's encoding not assigning values 0 to one of the numerals, although such an encoding wouldn't play well with null-terminated strings. – Kerrek SB Dec 04 '11 at 16:47
  • @Alex: Again, to the best of my knowledge, my function works with every real world character encoding in existence. If you know of a character encoding where the digits are non-consecutive, please let me know what character encoding that is. About the invalid input part, fair enough. That's a design decision. If the specification states that invalid input must be reported, not silently swallowed, my function is useless. – fredoverflow Dec 04 '11 at 16:53
  • 2
    And here i am, unable to downvote comments... :P @Alex: if you can provide an example of this code doing anything other than it was designed to do, feel free to share. Otherwise, quit going on about "security flaws". The most that's going on here is he's assuming that the user of this function is not a moron, and has passed a non-null pointer to a nul-terminated string. Like, you know, pretty much every function in `` assumes. – cHao Dec 04 '11 at 16:54
  • @AlexTheo: there is a huge difference between "yields unpredictable output when given garbage input", and "a security flaw". The function behaves correctly for valid inputs, and if your input isn't valid, it's up to the caller to sanitize it before calling the function. And even if you don't, there's no way this can lead to more than a denial of service attack (by crashing the process). And both stringstreams and `lexical_cast` are vulnerable to the exact same problem. Pass them a pointer to an unmapped address, and they'll crash. Just like this function. – jalf Dec 04 '11 at 18:22
  • @jalf ok thank you. I was a little bit confused with a code in general (because it uses ascii and in actually it is an c function, and I didn't saw the unsigned keyword at the first time - it was my mistake). Anyway it doesn't matter now. – AlexTheo Dec 04 '11 at 18:33
  • 2
    @Alex The C++ standard guarantees that digits are consecutive. So no, `x - '0'` **does not** depend on the ASCII table, it only depends on the C++ standard, which I think is acceptable. (reference: §2.3p4 "In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.") – R. Martinho Fernandes Dec 04 '11 at 18:37
  • Ok I got it, you are right thanks :) – AlexTheo Dec 04 '11 at 18:55
  • Xmm I really feel when the code is buggy :). Lets say that I will give as argument something like "99999999999999999999999999999999999999999999999999999999999". Will it generate the unexpected behavior??? What about signed numbers??? – AlexTheo Dec 05 '11 at 18:58
  • @Alex: It will generate 99999999999999999999999999999999999999999999999999999999999 mod 2^32 which is exactly what the C++ standard prescribes. And if you look at the result type, the function only parses unsigned numbers. – fredoverflow Dec 05 '11 at 21:40
  • In first overflow it will give you 9999999999999999999999999999999999 mod 2^32 + 9 which is different than number mod 2^32. In second step you will multiply this result with 10 "which may cause a new overflow too" and add the next number. So I don't think that the final result will be 99999999999999999999999999999999999999999999 mod 2^32. Also c++ does not prescribes how to convert string to number. – AlexTheo Dec 06 '11 at 09:20
  • Sorry for the first overflow 9999999999999999999999999999999999 mod 2^32*10 + 9. And it is doesn't matter because in this case I think that user will wait for something else. I believe that this may generate a lot of security issues :). – AlexTheo Dec 06 '11 at 09:28
  • Xmm it will mod 2^32 you are right I just calculated it but doesn't matter. Thanks. – AlexTheo Dec 06 '11 at 09:41
2

Using C++ Streams

std::string hello("123"); 
std::stringstream str(hello); 
int x;  
str >> x;  
if (!str) 
{      
   // The conversion failed.      
} 
Alok Save
  • 202,538
  • 53
  • 430
  • 533
1
template<class In, class Out>
static Out lexical_cast(const In& inputValue)
        {
    Out result;

    std::stringstream stream(std::stringstream::in | std::stringstream::out);
    stream << inputValue;
    stream >> result;
    if (stream.fail() || !stream.eof()) {
        throw bad_cast("Cast failed");
    }

    return result;
}

using it:

int val = lexical_cast< std::string, int >( "123" );
AlexTheo
  • 4,004
  • 1
  • 21
  • 35
  • I can craft an invalid input that'll make this function crash. So I guess your version has a security flaw, just like @FredOverflow's? – jalf Dec 04 '11 at 16:31
  • @jalf Xmm let's tell me and I will fix it :). – AlexTheo Dec 04 '11 at 16:35
  • Apparently, there is no `bad_cast` constructor taking a C string. – fredoverflow Dec 04 '11 at 16:46
  • sorry bad_cast is an exception from my lib you can't use this code as is. This is an example only. You can throw your exception if you wish. – AlexTheo Dec 04 '11 at 16:47
  • For example, passing `std::string(" 123")` to this function will work, but passing `std::string("123 ")` or `std::string(" 123 ")` will make it throw. Not really robust, IMHO. – jrok Dec 04 '11 at 16:50
  • and this is a right behavior because " 123 " is not an integer string. – AlexTheo Dec 04 '11 at 16:51
  • " 123" works though, " 123 " or "123 " doesn't. I'd call all three somehow valid integer strings. – jrok Dec 04 '11 at 16:52
  • ok thank you I will fix it :) – AlexTheo Dec 04 '11 at 16:53
  • I would refrain from reusing names from the standard library. That might confuse other programmers. – fredoverflow Dec 04 '11 at 17:00
  • If spaces inside the string are valid, how about tabs and line breaks? – fredoverflow Dec 04 '11 at 17:01
  • @FredOverflow actually I use namespace in this case so bad_cast and this function are in the same namespace. No spaces are not valid in my opinion. – AlexTheo Dec 04 '11 at 17:04
  • `boost::lexical_cast` allows leading and trailing spaces. Just saying. – fredoverflow Dec 04 '11 at 17:06
  • You can't fix it. I could pass in a user-defined type whose `operator<<` crashes (for example by dereferencing a null pointer). Or I could pass in a `const char*` which points to some garbage address. It is as fragile as @FredOverflow's answer, because, quite simply, it's impossible to avoid in C++. – jalf Dec 04 '11 at 18:18
  • Hmm it could be a reason why boost developers doesn't use 2 class template in their code, "but use explicitly declared type as argument instead", like this one :). – AlexTheo Dec 04 '11 at 18:38
0

Do you mean how to convert them to integers? You cannot convert an array of characters into a function on the language level - perhaps you can with some compiler specific inline assembler syntax. For doing a conversion into an integer you can use atoi

int i = atoi("123");`

Or strtol

long l = strtol("123", NULL, 10);
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212