Làm thế nào tôi có thể chuyển đổi một chuỗi std :: sang int?


484

Chỉ cần có một câu hỏi nhanh. Tôi đã tìm kiếm trên mạng khá nhiều và tôi đã tìm thấy một vài giải pháp nhưng chưa có giải pháp nào hoạt động. Nhìn vào việc chuyển đổi một chuỗi thành một int và tôi không có nghĩa là mã ASCII.

Để chạy nhanh xuống, chúng ta được truyền vào một phương trình dưới dạng một chuỗi. Chúng tôi phải phá vỡ nó, định dạng chính xác và giải các phương trình tuyến tính. Bây giờ, khi nói rằng, tôi không thể chuyển đổi một chuỗi thành một int.

Tôi biết rằng chuỗi sẽ ở định dạng (-5) hoặc (25), v.v. vì vậy nó chắc chắn là một số nguyên. Nhưng làm thế nào để chúng tôi trích xuất nó từ một chuỗi?

Một cách tôi đã nghĩ là chạy một vòng lặp for / while qua chuỗi, kiểm tra một chữ số, trích xuất tất cả các chữ số sau đó và sau đó xem liệu có một dấu '-', nếu có, nhân số int với - 1.

Có vẻ như một chút phức tạp cho một vấn đề nhỏ như vậy mặc dù. Có ý kiến ​​gì không?


9
Bạn đã thử atoi()chưa
i_am_jorf



7
@Chad Vì vậy, bạn đang đề nghị anh ấy sử dụng toàn bộ thư viện cho những thứ mà ngôn ngữ có thể làm với các thư viện tiêu chuẩn?
Bojangles

6
@Brandon, nếu bạn có một std::string myString, và muốn sử dụng atoi, thì bạn muốn nói atoi(myString.c_str()).
Rob

Câu trả lời:


726

Trong C ++ 11, có một số hàm chuyển đổi mới đẹp từ std::stringloại số.

Vì vậy, thay vì

atoi( str.c_str() )

bạn có thể dùng

std::stoi( str )

nơi strlà số của bạn như std::string.

Có phiên bản cho tất cả các hương vị của những con số: long stol(string), float stof(string), double stod(string), ... thấy http://en.cppreference.com/w/cpp/string/basic_string/stol


5
Đối với các vấn đề với std :: stoi, xem stackoverflow.com/a/6154614/195527 : nó sẽ chuyển đổi "11x"thành số nguyên 11.
CC.

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

4
@CC Đó cũng là hành vi của atoi: cplusplus.com/reference/cstdlib/atoi "Chuỗi có thể chứa các ký tự bổ sung sau các ký tự tạo thành số nguyên, bị bỏ qua và không ảnh hưởng đến hành vi của hàm này."
Phù thủy Tin

4
Bạn có phiền cập nhật câu trả lời này với from_charstừ C ++ 17 không? Nó được cho là đơn đặt hàng có cường độ nhanh hơn stoi.
NathanOliver


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

Để hoàn toàn chính xác, bạn sẽ muốn kiểm tra các cờ lỗi.


2
Điều này sẽ không trích xuất -5từ (-5).
Nawaz

@Nawaz, các parens có thực sự ở đó không, hay đó chỉ là cách OP trình bày các chuỗi của mình?
Winston Ewert

Tôi không biết. Tôi chỉ chỉ ra giới hạn của phương pháp này.
Nawaz

16
@Nawaz, Nó cũng không thể hoạt động trên đầu vào "WERWER". Tôi không nghĩ rằng parens thực sự là một phần trong chuỗi thực tế của anh ấy và tôi không nghĩ thực tế là tôi không phân tích chúng có liên quan.
Winston Ewert

4
@Nawaz, ok ... Tôi không hiểu từ đó nhưng tôi thấy làm thế nào bạn có thể.
Winston Ewert

44

Các tùy chọn có thể được mô tả dưới đây:

1. Tùy chọn đầu tiên: 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

Đây là một lỗi (cũng được hiển thị bởi cppcheck) vì "scanf không có giới hạn độ rộng trường có thể bị sập với dữ liệu đầu vào lớn trên một số phiên bản của libc" (xem tại đâytại đây ).

2. Tùy chọn thứ hai: 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
        }   

Giải pháp này ngắn và thanh lịch, nhưng nó chỉ có trên các trình biên dịch tuân thủ C ++ 11.

3. Tùy chọn thứ ba: dòng

    #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 ??

Tuy nhiên, với giải pháp này khó phân biệt giữa đầu vào xấu (xem tại đây ).

4. Tùy chọn thứ tư: Boost 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
        }

Tuy nhiên, đây chỉ là một trình bao bọc sstreamvà tài liệu đề nghị sử dụng sstreamđể quản lý lỗi tốt hơn (xem tại đây ).

5. Tùy chọn thứ năm: strto * ()

Giải pháp này rất dài, do quản lý lỗi và được mô tả ở đây. Vì không có hàm nào trả về một int đơn giản, nên cần phải chuyển đổi trong trường hợp số nguyên (xem tại đây để biết cách chuyển đổi này có thể đạt được).

6. Tùy chọn thứ sáu: 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     

Kết luận

Tóm lại, giải pháp tốt nhất là C ++ 11 std::stoi()hoặc, như một tùy chọn thứ hai, sử dụng các thư viện Qt. Tất cả các giải pháp khác được khuyến khích hoặc lỗi.


Đã sửa. Cảm ơn đã báo cáo.
Claudio

Tóm tắt đẹp, cảm ơn nhiều. Tôi có thể đề nghị thêm một nhận xét ban đầu đề xuất giải pháp cuối cùng để chỉ những người quan tâm đến chi tiết tiếp tục đọc không?
luca

1
đây sẽ là câu trả lời được chấp nhận, cũng có thể bạn đã quên (hay đúng hơn là nên thêm nguyên nhân đó là một câu trả lời cũ) from_chars
xception


9

Còn Boost.Lexical_cast thì sao?

Dưới đây là ví dụ của họ:

Ví dụ sau coi các đối số dòng lệnh là một chuỗi dữ liệu số:

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);
        }
    }
    ...
}

Liên kết bị hỏng. Bạn có thể sửa nó không?
Yuchen Zhong

5

Phải thừa nhận rằng, giải pháp của tôi sẽ không hoạt động đối với các số nguyên âm, nhưng nó sẽ trích xuất tất cả các số nguyên dương từ văn bản đầu vào có chứa các số nguyên. Nó sử dụng numeric_onlyngôn ngữ:

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;
}

Nhập ký tự:

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

Số nguyên đầu ra:

 5
25
7987
78
9878

Lớp numeric_onlyđược định nghĩa là:

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];
    }
};

Bản demo hoàn chỉnh trực tuyến: http://ideone.com/dRWSj


4

Nó có thể là một chút quá mức, nhưng boost::lexical_cast<int>( theString )nên làm việc khá tốt.


Một lỗi đánh máy. Nó chỉ đơn giản là boost::lexical_cast<int>( theString )( theStringtên của biến chứa chuỗi bạn muốn chuyển đổi thành int).
James Kanze


1

Trong Windows, bạn có thể sử dụng:

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, stringstreamcần chỉ định cơ sở nếu bạn cần diễn giải thập lục phân.


1

Vâng, rất nhiều câu trả lời, rất nhiều khả năng. Điều tôi thiếu ở đây là một số phương thức phổ biến chuyển đổi một chuỗi thành các loại tích phân C ++ khác nhau (ngắn, int, dài, bool, ...). Tôi đã đưa ra giải pháp sau đây:

#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;
}

Dưới đây là ví dụ về cách sử dụng:

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

Tại sao không chỉ sử dụng toán tử đầu ra chuỗi để chuyển đổi một chuỗi thành một kiểu tích phân? Đây là câu trả lời: Giả sử một chuỗi chứa một giá trị vượt quá giới hạn cho loại tích phân dự định. Đối với bài kiểm tra, trên Wndows 64 max int là 2147483647. Hãy gán cho chuỗi một giá trị max int + 1: string str = "2147483648". Bây giờ, khi chuyển đổi chuỗi thành int:

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

x trở thành 2147483647, đây chắc chắn là một lỗi: chuỗi "2147483648" không được chuyển đổi thành int 2147483647. Hàm được cung cấp choIntegralType phát hiện ra các lỗi như vậy và ném ngoại lệ.


0

Từ http://www.cplusplus.com/reference/opes/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;
}

Đầu ra:

2001, A Space Odyssey: 2001 và [, A Space Odyssey]

40c3: 16579

-10010110001: -1201

0x7f: 127


0

Mã của tôi:

#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

Để chuyển đổi từ biểu diễn chuỗi thành giá trị số nguyên, chúng ta có thể sử dụng std :: stringstream.

nếu giá trị được chuyển đổi nằm ngoài phạm vi cho kiểu dữ liệu số nguyên, nó sẽ trả về INT_MIN hoặc INT_MAX.

Ngoài ra, nếu giá trị chuỗi không thể được biểu diễn dưới dạng kiểu dữ liệu int hợp lệ, thì 0 được trả về.

#include 
#include 
#include 

int main() {

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

Đầu ra: 50

Theo đầu ra ở trên, chúng ta có thể thấy nó được chuyển đổi từ số chuỗi thành số nguyên.

Nguồn và nhiều hơn nữa tại chuỗi để int c ++


-2

Phiên bản một dòng: long n = strtol(s.c_str(), NULL, base); .

( slà chuỗi và baselà một intví dụ như 2, 8, 10, 16.)

Bạn có thể tham khảo liên kết này để biết thêm chi tiết về strtol.


Ý tưởng cốt lõi là sử dụng strtolchức năng, được bao gồm trong cstdlib.

strtolchỉ xử lý với charmảng, chúng ta cần chuyển đổi stringsang charmảng. Bạn có thể tham khảo liên kết này .

Một ví dụ:

#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;
}

cái nào sẽ xuất ra:

1111000001011010
61530
f05a
1111000001011010

-3

có một cách dễ dàng khác: giả sử bạn có một nhân vật như c='4'vậy, do đó bạn có thể thực hiện một trong các bước sau:

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 .

cách thứ hai:

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


1
Câu hỏi đặt ra là về chuyển đổi từ stringtới intchứ không phải là từ charđể string.
Yuchen Zhong

lỗi và không phù hợp với câu hỏi
caoan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.