std :: string을 int로 변환하려면 어떻게해야합니까?


484

간단한 질문이 있습니다. 나는 인터넷을 둘러 보았고 몇 가지 해결책을 찾았지만 아직 아무것도 작동하지 않았습니다. 문자열을 int로 변환하는 것을 보면서 ASCII 코드를 의미하지는 않습니다.

빠른 요약을 위해 방정식으로 문자열로 전달됩니다. 우리는 그것을 분해하고 올바르게 포맷하고 선형 방정식을 풀어야합니다. 이제는 문자열을 정수로 변환 할 수 없습니다.

문자열이 형식 (-5) 또는 (25) 등이 될 것이므로 확실히 int입니다. 그러나 문자열에서 어떻게 추출합니까?

내가 생각한 한 가지 방법은 문자열을 통해 for / while 루프를 실행하고 숫자를 확인한 후 그 뒤에 모든 숫자를 추출한 다음 선행 '-'가 있는지 확인하고 있다면 int에-를 곱하는 것입니다. 1.

그런 작은 문제는 조금 복잡해 보입니다. 어떤 아이디어?


9
당신은 시도 했습니까 atoi()?
i_am_jorf



7
@Chad 어쨌든 표준 라이브러리로 언어가 할 수있는 일에 전체 라이브러리를 사용하도록 권장하고 있습니까?
Bojangles

6
@Brandon, 당신이 있고을 std::string myString사용하고 싶다면 atoi말하고 싶습니다 atoi(myString.c_str()).
Robᵩ

답변:


726

C ++ 11에는 멋진 새로운 변환 함수 std::string가 숫자 유형으로 있습니다.

그래서 대신

atoi( str.c_str() )

당신이 사용할 수있는

std::stoi( str )

str귀하의 번호는 어디입니까 std::string?

숫자의 모든 맛의 버전이있다 : long stol(string), float stof(string), double stod(string), ... 참조 http://en.cppreference.com/w/cpp/string/basic_string/stol


5
std :: stoi 관련 문제는 stackoverflow.com/a/6154614/195527 : "11x"integer 로 변환 됩니다 11.
CC.

5
#include <stdlib.h> / * atoi * /
Ulad Kasach

4
@CC atoi의 동작이기도합니다. cplusplus.com/reference/cstdlib/atoi "문자열은 정수 뒤에 숫자가있는 문자 뒤에 추가 문자를 포함 할 수 있습니다.이 문자는 무시 되며이 함수의 동작에 영향을주지 않습니다."
주석 마법사

4
이 답변 from_chars을 C ++ 17에서 업데이트 하시겠습니까 ? 보다 수십 배 빠릅니다 stoi.
NathanOliver


57
std::istringstream ss(thestring);
ss >> thevalue;

완전히 수정하려면 오류 플래그를 확인해야합니다.


2
-5에서 추출되지 않습니다 (-5).
Nawaz

@Nawaz, 파 렌스가 실제로 있습니까, 아니면 OP가 자신의 줄을 제시하는 방법입니까?
Winston Ewert

모르겠어요 나는 접근 방식의 한계를 지적하고 있습니다.
Nawaz

16
@Nawaz, 입력 "WERWER"에서도 작동하지 않습니다. 나는 parens가 실제로 그의 실제 문자열의 일부라고 생각하지 않으며, 내가 그들을 파싱하지 않는다는 사실이 관련이 있다고 생각하지 않습니다.
Winston Ewert

4
@Nawaz, 알았어 .. 그런 식으로 단어를 쓰지 않지만 어떻게 할 수 있는지 봅니다.
Winston Ewert

44

가능한 옵션은 다음과 같습니다.

1. 첫 번째 옵션 : sscanf ()

    #include <cstdio>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        if(sscanf(str.c_str(), "%d", &i) != 1)
            // error management

        // string -> float
        if(sscanf(str.c_str(), "%f", &f) != 1)
            // error management

        // string -> double 
        if(sscanf(str.c_str(), "%lf", &d) != 1)
            // error management

"필드 너비 제한이없는 scanf가 일부 버전의 libc에서 큰 입력 데이터로 충돌 할 수 있습니다" ( 여기여기 참조 ) 때문에 오류 (cppcheck로도 표시됨) ).

2. 두 번째 옵션 : std :: sto * ()

    #include <iostream>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        try {
            // string -> integer
            int i = std::stoi(str);

            // string -> float
            float f = std::stof(str);

            // string -> double 
            double d = std::stod(str);
        } catch (...) {
            // error management
        }   

이 솔루션은 짧고 우아하지만 C ++ 11 호환 컴파일러에서만 사용할 수 있습니다.

3. 세 번째 옵션 : sstreams

    #include <string>
    #include <sstream>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        std::istringstream ( str ) >> i;

        // string -> float
        std::istringstream ( str ) >> f;

        // string -> double 
        std::istringstream ( str ) >> d;

        // error management ??

그러나이 솔루션을 사용하면 잘못된 입력을 구별하기가 어렵습니다 ( 여기 참조 ).

4. 네번째 옵션 : Boost 's lexical_cast

    #include <boost/lexical_cast.hpp>
    #include <string>

        std::string str;

        try {
            int i = boost::lexical_cast<int>( str.c_str());
            float f = boost::lexical_cast<int>( str.c_str());
            double d = boost::lexical_cast<int>( str.c_str());
            } catch( boost::bad_lexical_cast const& ) {
                // Error management
        }

그러나 이것은의 래퍼 sstream일 뿐이며 문서는 sstream더 나은 오류 관리 를 위해 사용하도록 제안합니다 ( 여기 참조 ).

5. 다섯 번째 옵션 : strto * ()

이 솔루션은 오류 관리로 인해 매우 길며 여기에 설명되어 있습니다. 일반 int를 반환하는 함수가 없으므로 정수인 경우 변환이 필요 합니다 (이 변환을 수행하는 방법 은 여기 참조 ).

6. 여섯 번째 옵션 : Qt

    #include <QString>
    #include <string>

        bool ok;
        std::string;

        int i = QString::fromStdString(str).toInt(&ok);
        if (!ok)
            // Error management

        float f = QString::fromStdString(str).toFloat(&ok);
        if (!ok)
            // Error management 

        double d = QString::fromStdString(str).toDouble(&ok);
        if (!ok)
    // Error management     

결론

요약하면 가장 좋은 솔루션은 C ++ 11 std::stoi()또는 두 번째 옵션으로 Qt 라이브러리 사용입니다. 다른 모든 솔루션은 권장하지 않거나 버그가 있습니다.


결정된. 보고 해 주셔서 감사합니다.
Claudio

아름다운 요약, 많은 감사합니다. 세부 사항에 관심이있는 사람 만 계속 읽을 수 있도록 최종 해결 방법을 제안하는 초기 의견을 추가해도됩니까?
luca

1
이 또한 잊어 허용 대답해야한다 (또는 오히려 오래된 대답 원인 추가해야합니다) from_chars을
xception이


9

Boost.Lexical_cast어떻 습니까?

그들의 예는 다음과 같습니다.

다음 예제는 명령 행 인수를 일련의 숫자 데이터로 처리합니다.

int main(int argc, char * argv[])
{
    using boost::lexical_cast;
    using boost::bad_lexical_cast;

    std::vector<short> args;

    while(*++argv)
    {
        try
        {
            args.push_back(lexical_cast<short>(*argv));
        }
        catch(bad_lexical_cast &)
        {
            args.push_back(0);
        }
    }
    ...
}

링크가 끊어졌습니다. 고칠 수 있습니까?
Yuchen Zhong

5

분명히, 내 솔루션은 음의 정수에 대해 작동하지 않지만 정수를 포함하는 입력 텍스트에서 모든 양의 정수를 추출합니다. numeric_only로케일 을 사용합니다 .

int main() {
        int num;
        std::cin.imbue(std::locale(std::locale(), new numeric_only()));
        while ( std::cin >> num)
             std::cout << num << std::endl;
        return 0;
}

입력 텍스트 :

 the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878

출력 정수 :

 5
25
7987
78
9878

클래스 numeric_only는 다음과 같이 정의됩니다.

struct numeric_only: std::ctype<char> 
{
    numeric_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
        return &rc[0];
    }
};

완전한 온라인 데모 : http://ideone.com/dRWSj


4

아마도 약간의 과잉 일 수도 있지만 boost::lexical_cast<int>( theString )일을 잘해야합니다.


오타. 간단히 변환해야합니다 boost::lexical_cast<int>( theString )(여기서 theString변환하려는 문자열이 포함 된 변수 이름 int).
James Kanze


1

Windows에서는 다음을 사용할 수 있습니다.

const std::wstring hex = L"0x13";
const std::wstring dec = L"19";

int ret;
if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}
if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}

strtol, stringstream당신은 16 진을 해석해야하는 경우 기본을 지정해야합니다.


1

글쎄, 많은 대답과 많은 가능성. 여기서 누락 된 것은 문자열을 다른 C ++ 정수 유형 (short, int, long, bool 등)으로 변환하는 보편적 인 방법입니다. 나는 다음과 같은 해결책을 생각해 냈습니다.

#include<sstream>
#include<exception>
#include<string>
#include<type_traits>

using namespace std;

template<typename T>
T toIntegralType(const string &str) {
    static_assert(is_integral<T>::value, "Integral type required.");
    T ret;
    stringstream ss(str);
    ss >> ret;
    if ( to_string(ret) != str)
        throw invalid_argument("Can't convert " + str);
    return ret;
}

사용 예는 다음과 같습니다.

string str = "123";
int x = toIntegralType<int>(str); // x = 123

str = "123a";
x = toIntegralType<int>(str); // throws exception, because "123a" is not int

str = "1";
bool y = toIntegralType<bool>(str); // y is true
str = "0";
y = toIntegralType<bool>(str); // y is false
str = "00";
y = toIntegralType<bool>(str); // throws exception

문자열 스트림 출력 연산자를 사용하여 문자열을 정수 유형으로 변환하지 않는 이유는 무엇입니까? 대답은 다음과 같습니다. 문자열에 의도 된 정수 유형의 한계를 초과하는 값이 포함되어 있다고 가정합니다. 예를 들어, Wndows에서 64 max int는 2147483647입니다. 문자열에 max int + 1 값을 지정합니다 : string str = "2147483648". 이제 문자열을 int로 변환 할 때 :

stringstream ss(str);
int x;
ss >> x;

x는 2147483647이되고, 확실히 오류는 무엇입니까? 문자열 "2147483648"은 int 2147483647로 변환되지 않아야합니다. 제공된 IntegralType 함수는 이러한 오류를 발견하고 예외를 발생시킵니다.


0

에서 http://www.cplusplus.com/reference/string/stoi/

// stoi example
#include <iostream>   // std::cout
#include <string>     // std::string, std::stoi

int main ()
{
  std::string str_dec = "2001, A Space Odyssey";
  std::string str_hex = "40c3";
  std::string str_bin = "-10010110001";
  std::string str_auto = "0x7f";

  std::string::size_type sz;   // alias of size_t

  int i_dec = std::stoi (str_dec,&sz);
  int i_hex = std::stoi (str_hex,nullptr,16);
  int i_bin = std::stoi (str_bin,nullptr,2);
  int i_auto = std::stoi (str_auto,nullptr,0);

  std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
  std::cout << str_hex << ": " << i_hex << '\n';
  std::cout << str_bin << ": " << i_bin << '\n';
  std::cout << str_auto << ": " << i_auto << '\n';

  return 0;
}

산출:

2001, 스페이스 오디세이 : 2001 및 [, 스페이스 오디세이]

40c3 : 16579

-10010110001 : -1201

0x7f : 127


0

내 코드 :

#include <iostream>
using namespace std;

int main()
{
    string s="32";  //String
    int n=stoi(s);  //Convert to int
    cout << n + 1 << endl;

    return 0;
}

0
ll toll(string a){
    ll ret=0;
    bool minus=false;
    for(auto i:a){
        if(i=='-'){ minus=true; continue; }
        ret*=10;
        ret+=(i-'0');
    } if(minus) ret*=-1;
    return ret;
    # ll is defined as, #define ll long long int
    # usage: ll a = toll(string("-1234"));
}

0

문자열 표현에서 정수 값으로 변환하기 위해 std :: stringstream을 사용할 수 있습니다.

변환 된 값이 정수 데이터 유형의 범위를 벗어나면 INT_MIN 또는 INT_MAX를 리턴합니다.

또한 문자열 값을 유효한 int 데이터 형식으로 표현할 수 없으면 0이 반환됩니다.

#include 
#include 
#include 

int main() {

    std::string x = "50";
    int y;
    std::istringstream(x) >> y;
    std::cout << y << '\n';
    return 0;
}

출력 : 50

위의 출력에 따라 문자열 숫자에서 정수로 변환 된 것을 볼 수 있습니다.

int C ++의 문자열 에서 소스 및 기타


-2

한 줄 버전 : long n = strtol(s.c_str(), NULL, base); .

( s문자열이며, baseint등의 2, 8, 10, 16)

에 대한 자세한 내용은 이 링크 를 참조하십시오 strtol.


핵심 아이디어는에 strtol포함 된 기능 을 사용 하는 것입니다 cstdlib.

이후 strtol만 핸들 char배열, 우리는 변환 할 필요 stringchar배열입니다. 이 링크를 참조 할 수 있습니다 .

예를 들면 :

#include <iostream>
#include <string>   // string type
#include <bitset>   // bitset type used in the output

int main(){
    s = "1111000001011010";
    long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string

    cout << s << endl;
    cout << t << endl;
    cout << hex << t << endl;
    cout << bitset<16> (t) << endl;

    return 0;
}

출력됩니다 :

1111000001011010
61530
f05a
1111000001011010

-3

또 다른 쉬운 방법이 있습니다 : 캐릭터가 있다고 가정하면 c='4'다음 단계 중 하나를 수행 할 수 있습니다.

1 위 : int q

q=(int) c ; (q is now 52 in ascii table ) . q=q-48; remember that adding 48 to digits is their ascii code .

두 번째 방법 :

q=c-'0'; the same , character '0' means 48


1
문제는에서 변환하는 방법에 대한 것입니다 stringint보다는 오히려에서 charstring.
Yuchen Zhong

버그와 질문에 맞지 않음
caoanan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.