tags:

views:

212

answers:

8

I need to convert a char* to an integer. For example:

data.SetBytFldPos(*attribute->value());

The value in the attribute class is a char*. 'SetBytFldPos" takes an int.

+5  A: 

Lots of ways. Simplest is to use the strtol() function.

anon
I avoid this function since it can't represent error conditions very well. Zero is ambiguous.
David Gladfelter
@David It expresses them very well - better than the alternatives. If a conversion fails, it sets its second parameter to point to the character that caused the failure. If a range error occurs, special values (not zero) are returned. This is all described in the page I provided alink to.
anon
If it can't convert the number you know because the pointer still points to the start of the string.
Martin Beckett
@David: If no conversion is performed, zero is returned, and the value of `nptr` is stored in the object pointed to by `endptr`, provided that `endptr` is not a null pointer. So it's not ambiguous.
Alok
+4  A: 

You don't convert char* to an int. You may wish to parse a decimal string. This is done by atoi(). atoi("1") == 1.

Pavel Radzivilovsky
Notice that `atoi("0")` and `atoi("foobar")` both return 0. To quote from the man page: The atoi() function converts the initial portion of the string pointed to by nptr to int. The behavior is the same as strtol(nptr, (char **) NULL, 10); except that atoi() does not detect errors.
hlovdal
A: 

You can use atoi() function

data.SetByteFldPos(atoi(attribute->value()));
sergiom
A: 

There is a simple C function called atoi which is not so good because the error handling is in best case unintuitively and easy to forget. The (C) function strtol is much better, make it a habit to prefer that one to atoi. Here is example code from the man page:

   #include <stdlib.h>
   #include <limits.h>
   #include <stdio.h>
   #include <errno.h>

   int
   main(int argc, char *argv[])
   {
       int base;
       char *endptr, *str;
       long val;

       if (argc < 2) {
           fprintf(stderr, "Usage: %s str [base]\n", argv[0]);
           exit(EXIT_FAILURE);
       }

       str = argv[1];
       base = (argc > 2) ? atoi(argv[2]) : 10;

       errno = 0;    /* To distinguish success/failure after call */
       val = strtol(str, &endptr, base);

       /* Check for various possible errors */

       if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
               || (errno != 0 && val == 0)) {
           perror("strtol");
           exit(EXIT_FAILURE);
       }

       if (endptr == str) {
           fprintf(stderr, "No digits were found\n");
           exit(EXIT_FAILURE);
       }

       /* If we got here, strtol() successfully parsed a number */

       printf("strtol() returned %ld\n", val);

       if (*endptr != '\0')        /* Not necessarily an error... */
           printf("Further characters after number: %s\n", endptr);

       exit(EXIT_SUCCESS);
   }

Notice the total lack of any kind of error check for the atoi(argv[2]) conversion. Not that strtol is super simple and intuitive to check for errors either, but it is at least better.

hlovdal
+3  A: 

If you need to make sure that your char* represents a valid int, you can use Boost Lexical Cast

#include <boost/lexical_cast.hpp>

try {
    data.SetBytFldPos(boost::lexical_cast<int>(*attribute->value()));
} catch (bad_lexical_cast) {
    // something is wrong
}
Ferruccio
You should use global #include style, that is <boost/lexical_cast.h>. Not that it *really* matters....
larsm
Are the boost libraries not all suffixed with hpp?
Martin York
This solution is horribly inefficient compared with using strtol(), if efficiency is of any concern.
anon
Ferruccio
+1  A: 

You can also write a generic "convert string-to-X template".

template <class T>
T parse(const std::string& s)
{
  T out;
  std::stringstream ss(s);
  ss >> out;
  return out;
}

Usage:

int x = parse<int>("123");
float y = parse<float>("3.14159");
Peter Alexander
1) Already been done: Boost::lexical_cast<>() 2) That wont work as the compiler can not choose which template function to use based on the return type (it can only choose based on the types of the parameters and they are always std::string so no help there).
Martin York
Yes, you are absolutely correct. I have fixed the code.
Peter Alexander
A: 

There are four ways I can think of:

  • atoi. Be warned that this function returns 0 if it can't parse your string.
  • strtol, a more robust version of atoi. This might cause a compiler warning because you need an int and its return value is long.
  • Boost library's lexical_cast. I like this one if you can use Boost.
  • Use a stringstream, as shown below.

Code sample:

std::string str(*attribute->value());
std::istringstream myStrm(str);
int val;

myStrm >> val;
Kristo
A: 

You can

// needed
#include <sstream>

// source, target
char const * p = "123";
int ival;

// conversion
std::stringstream ss(p);
ss >> ival;

Note though that we usually talk about "strings", not char*, as long as we don't mean pointers.

phresnel