Basics of strtol?
Asked Answered
C

4

9

I am really confused. I have to be missing something rather simple but nothing I am reading about strtol() is making sense. Can someone spell it out for me in a really basic way, as well as give an example for how I might get something like the following to work?

string input = getUserInput;
int numberinput = strtol(input,?,?);
Crepuscular answered 10/2, 2013 at 2:30 Comment(7)
Have you tried stackoverflow.com/search?q=strtol ?Daunt
Or cplusplus.com/reference/cstdlib/strtol ?Daunt
Any particular reason for using strtol instead of a stringstream to read a number?Foldboat
Have you tried int number = strtol(input.**c_str()**, ...);?Alewife
@Foldboat no need for a stringstream when we have std::stol.Prostate
@SethCarnegie Awesome, more C++11 shininess I didn't know about. Thanks!Foldboat
Trust the one of the masters and forget about rest, read -> https://mcmap.net/q/49634/-correct-usage-of-strtolRies
F
33

The first argument is the string. It has to be passed in as a C string, so if you have a std::string use .c_str() first.

The second argument is optional, and specifies a char * to store a pointer to the character after the end of the number. This is useful when converting a string containing several integers, but if you don't need it, just set this argument to NULL.

The third argument is the radix (base) to convert. strtol can do anything from binary (base 2) to base 36. If you want strtol to pick the base automatically based on prefix, pass in 0.

So, the simplest usage would be

long l = strtol(input.c_str(), NULL, 0);

If you know you are getting decimal numbers:

long l = strtol(input.c_str(), NULL, 10);

strtol returns 0 if there are no convertible characters at the start of the string. If you want to check if strtol succeeded, use the middle argument:

const char *s = input.c_str();
char *t;
long l = strtol(s, &t, 10);
if(s == t) {
    /* strtol failed */
}

If you're using C++11, use stol instead:

long l = stol(input);

Alternately, you can just use a stringstream, which has the advantage of being able to read many items with ease just like cin:

stringstream ss(input);
long l;
ss >> l;
Foldboat answered 10/2, 2013 at 2:41 Comment(8)
Ok so this got my code to work. Just to check passing a string with no number in it would yield what exactly? Also what is the difference between a string and a C string?Crepuscular
If you don't have a number in the string, strtol returns 0. Since that's a legal return value, you have to use the middle parameter to disambiguate.Foldboat
@JamesThompson: A string (std::string) is a C++ object that represents a string. It is the preferred way to handle strings in C++. A C string is a sequence of characters which ends in a null terminator (\0) and is represented by a pointer to the first character in the sequence (a char *). C functions (like strtol) don't take string objects, so you have to pass a C string instead.Foldboat
oh no that's a problem then. I need to be able to catch when a number is not entered, however for my project 0 is a valid number so I can't just do a if(int = 0)Crepuscular
Ok so it works, and I thank you. But I don't actually get it. Probably because Im not use to pointers. What is actually being compared in the statement (s==t)Crepuscular
strtol saves a pointer to the first non-numeric character in t. If s==t, then it means the first character in the string is non-numeric, i.e. the string doesn't start with a number.Foldboat
Ok that make sense. One last question. I actually have to do the same thing with doubles I know there is a strtod by using the same code isn't working does strtod use diff params? or what am i missingCrepuscular
Google for the function. Does it have different parameters?Foldboat
C
4

Suppose you're given a string char const * str. Now convert it like this:

#include <cstdlib>
#include <cerrno>

char * e;
errno = 0;

long n = std::strtol(str, &e, 0);

The last argument 0 determines the number base you want to apply; 0 means "auto-detect". Other sensible values are 8, 10 or 16.

Next you need to inspect the end pointer e. This points to the character after the consumed input. Thus if all input was consumed, it points to the null-terminator.

if (*e != '\0') { /* error, die */ }

It's also possible to allow for partial input consumption using e, but that's the sort of stuff that you'll understand when you actually need it.

Lastly, you should check for errors, which can essentially only be overflow errors if the input doesn't fit into the destination type:

if (errno != 0) { /* error, die */ }

In C++, it might be preferable to use std::stol, though you don't get to pick the number base in this case:

#include <string>

try { long n = std::stol(str); }
catch (std::invalid_argument const & e) { /* error */ }
catch (std::out_of_range const & e)     { /* error */ }
Chad answered 10/2, 2013 at 2:41 Comment(0)
A
0

Quote from C++ reference:

long int strtol ( const char * str, char ** endptr, int base );

Convert string to long integer

Parses the C string str interpreting its content as an integral number of the specified base, which is returned as a long int value. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number.

So try something like

long l = strtol(pointerToStartOfString, NULL, 0)
Amoeba answered 10/2, 2013 at 2:34 Comment(2)
Im new to C++ so im not use to pointers although i aware of the concept. How to i find pointerToStartOfString for my string and what should it look likeCrepuscular
How it works in C is like this: char is a variable containing a character. char* is a variable containing a pointer. The pointer, when dereferenced, points to a character (usually the start of many characters in memory, called a 'string'). So if you have char* MyPointer, then you can do strtol(MyPointer, NULL, 0).Amoeba
C
0

I always use simply strol(str,0,0) - it returns long value. 0 for radix (last parameter) means to auto-detect it from input string, so both 0x10 as hex and 10 as decimal could be used in input string.

Comportment answered 10/2, 2013 at 2:38 Comment(4)
Trying to use strol(input,0,0) gave me the error of "cannot convert std::string' to const char*' for argument 1' to long int strtol(const char*, char**, int)'"Crepuscular
Yes, C++ has std::string which is not char*. Even though they're used for the same thing (holding strings) functions that work on one do not work on the other.Amoeba
for std::string use strtol(str.c_str(),0,0)Comportment
True about 0 leads to auto-detect the base. With "0109" the result is 8 as 8 is the auto-detected base.Photochromy

© 2022 - 2024 — McMap. All rights reserved.