C++ How to convert string, which has string and numeric, into int or long

334 views Asked by At

I'm trying to convert a string variable, which contains alphabetic and numeric values, into an int variable.

string argument = "100km";
int i = atoi(argument.c_str());
cout<<i<<endl;

I've confirmed that i has an int of 100 and km is omitted. However, if I enter 2147483648km, which is over that range of int, i will have -2147483648.

According to this page, int is supposed to be able to have

–2,147,483,648 to 2,147,483,647

So, I thought that this error came from the range of int, but the same error happens even when atoi is replaced by atol and int is replaced by unsigned long, which can have a much larger value. In other words, replacing int with long doesn't fix this error.

Chances are that I need to come up with an alternative way to convert this kind of string (i.e. string of "______km" into an int variable).

5

There are 5 answers

0
Andreas DM On BEST ANSWER

The data type ranges from Microsoft's site can show you what Visual C++ compilers use.
This may vary, see 6502's answer covering that.

Moreover, atol returns a long, so if you give it a unsigned long you're going to get a long in return.

Since C++11, you are able to use atoll which returns a long long, otherwise see the other answers using stoi, stol, stoll.

1
6502 On

In some compilers int is not "much less" than long, and indeed they're equal.

The only guarantee the standard gives you is that a long is never smaller than an int.

A simple solution would be to use atof instead that uses doubles that on most platforms is a 64-bit IEE754 double-precision number that is able to represent all integers exactly up to a magnitude of 253 that is 9,007,199,254,740,992.

0
Some programmer dude On

The size and range of the basic integer types depends on the compiler. On 32-bit platforms just about all compilers only have 32-bit int and long types. On 64-bit platforms the Visual Studio compiler still have 32-bit int and long while e.g. GCC have 32-bit int and 64-bit long.

If you want a larger type then you need long long which currently is 64 bits on all platforms and compilers (though it don't have to be).

Also, you should switch to stoi, stol and stoll (or their unsigned variants) instead of atoi.


If you want to know the actual limits, sizes and ranges of a type, you should use std::numeric_limits.

0
Steephen On

By using strtol you can achieve what you are looking for:

    string argument = "2147483648km";
    char *end;
    std::cout<<strtol(static_cast<const char *> (argument.c_str()),&end,10);

Depends on the size , you can prefer stol,stoll or stoi. More details are available here : http://en.cppreference.com/w/cpp/string/byte/strtol

0
edmz On

Use std::stringstream.

#include <sstream>
#include <iostream>
#include <string>
using namespace std;

int main()
{
        std::stringstream ss { "2147483648km" };
        int n;
        string s;

        if (!(ss >> n ))
        {
                std::cout << "cannot convert \n";
        }
        else
        {
                ss >> s ;
                std::cout << n << " " << s << "\n";
        }
}

And you can even abstract the whole thing

struct Distance
{
    string unit; 
    int distance;

    friend istream& operator>>(istream& in, Distance &d)
    {
         return in >> distance >> unit;
    }

};

std::stringstream ss { "331104km" };
Distance dst;
ss >> dst;