Bagaimana saya bisa mengkonversi string std :: ke int?

484

Punya pertanyaan singkat. Saya sudah melihat-lihat internet cukup banyak dan saya sudah menemukan beberapa solusi tetapi belum ada yang bekerja. Melihat mengkonversi string ke int dan saya tidak bermaksud kode ASCII.

Untuk run-down cepat, kita dilewatkan dalam persamaan sebagai string. Kita harus memecahnya, memformatnya dengan benar dan menyelesaikan persamaan linear. Sekarang, dengan mengatakan itu, saya tidak dapat mengubah string menjadi int.

Saya tahu bahwa string akan berada dalam format (-5) atau (25) dll. Jadi itu jelas int. Tapi bagaimana kita mengekstraknya dari string?

Salah satu cara yang saya pikirkan adalah menjalankan for / while loop melalui string, memeriksa digit, mengekstrak semua digit setelah itu dan kemudian melihat apakah ada '-' terkemuka, jika ada, kalikan int dengan - 1.

Tampaknya agak terlalu rumit untuk masalah kecil. Ada ide?

Brandon
sumber
9
Sudahkah Anda mencoba atoi()?
i_am_jorf
7
@Chad Jadi Anda merekomendasikan dia menggunakan seluruh pustaka untuk sesuatu yang bisa dilakukan bahasa dengan pustaka standar?
Bojangles
6
@ Brandon, jika Anda memiliki std::string myString, dan ingin menggunakan atoi, maka Anda ingin mengatakan atoi(myString.c_str()).
Robᵩ

Jawaban:

726

Di C ++ 11 ada beberapa fungsi konversi baru yang bagus dari std::stringke tipe angka.

Jadi, bukannya

atoi( str.c_str() )

kamu bisa menggunakan

std::stoi( str )

dimana strnomor kamu sebagai std::string.

Ada versi untuk semua rasa dari nomor: long stol(string), float stof(string), double stod(string), ... lihat http://en.cppreference.com/w/cpp/string/basic_string/stol

tgmath
sumber
5
Untuk masalah dengan std :: stoi, lihat stackoverflow.com/a/6154614/195527 : ini akan dikonversi "11x"menjadi integer 11.
CC.
5
#include <stdlib.h> / * atoi * /
Ulad Kasach
4
@CC Itu juga perilaku atoi: cplusplus.com/reference/cstdlib/atoi "String dapat berisi karakter tambahan setelah mereka yang membentuk angka integral, yang diabaikan dan tidak berpengaruh pada perilaku fungsi ini."
Penyihir Timah
4
Maukah Anda memperbarui jawaban ini from_charsdari C ++ 17? Seharusnya perintah besarnya lebih cepat dari stoi.
NathanOliver
stoiharus lebih disukai. Lihat Mengapa saya tidak harus menggunakan atoi ()?
phuclv
57
std::istringstream ss(thestring);
ss >> thevalue;

Agar benar sepenuhnya, Anda ingin memeriksa bendera kesalahan.

Winston Ewert
sumber
2
Ini tidak akan diekstrak -5dari (-5).
Nawaz
@Nawaz, apakah orangtua benar-benar ada di sana, atau hanya dengan cara itulah OP menyajikan senarnya?
Winston Ewert
Saya tidak tahu Saya hanya menunjukkan keterbatasan pendekatan.
Nawaz
16
@Nawaz, Ini juga tidak dapat beroperasi pada input "WERWER". Saya tidak berpikir parens sebenarnya bagian dari string yang sebenarnya dan saya tidak berpikir fakta bahwa saya tidak menguraikannya relevan.
Winston Ewert
4
@Nawaz, ok ... Saya tidak mengambil kata itu tapi saya mengerti bagaimana Anda bisa.
Winston Ewert
44

Opsi yang mungkin dijelaskan di bawah ini:

1. Opsi pertama: 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

Ini adalah kesalahan (juga ditunjukkan oleh cppcheck) karena "scanf tanpa batas lebar bidang dapat macet dengan data input besar pada beberapa versi libc" (lihat di sini , dan di sini ).

2. Opsi kedua: 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
        }   

Solusi ini pendek dan elegan, tetapi hanya tersedia pada kompiler yang memenuhi C ++ 11.

3. Opsi ketiga: 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 ??

Namun, dengan solusi ini sulit untuk membedakan antara input yang buruk (lihat di sini ).

4. Opsi keempat: 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
        }

Namun, ini hanya pembungkus sstream, dan dokumentasi menyarankan untuk digunakan sstreamuntuk manajemen kesalahan yang lebih baik (lihat di sini ).

5. Opsi kelima: strto * ()

Solusi ini sangat panjang, karena manajemen kesalahan, dan dijelaskan di sini. Karena tidak ada fungsi yang mengembalikan int polos, konversi diperlukan jika integer (lihat di sini bagaimana konversi ini dapat dicapai).

6. Opsi keenam: 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     

Kesimpulan

Kesimpulannya, solusi terbaik adalah C ++ 11 std::stoi()atau, sebagai opsi kedua, penggunaan pustaka Qt. Semua solusi lain tidak disarankan atau bermasalah.

Claudio
sumber
Tetap. Terima kasih telah melaporkan.
Claudio
Ringkasan yang indah, terima kasih banyak. Bolehkah saya menyarankan untuk menambahkan komentar awal yang menyarankan solusi akhir sehingga hanya orang yang tertarik dengan detail yang tetap membaca?
luca
1
ini harus menjadi jawaban diterima, juga Anda lupa (atau lebih tepatnya harus menambahkan penyebab itu jawaban tua) from_chars
xception
40

gunakan fungsi atoi untuk mengonversi string menjadi integer:

string a = "25";

int b = atoi(a.c_str());

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

brenjt
sumber
14
Tidak pernah digunakan atoi. strtolmelakukan segalanya atoi, tetapi lebih baik, dan gagal dengan aman.
Ben Voigt
9

Bagaimana dengan Boost.Lexical_cast ?

Inilah contoh mereka:

Contoh berikut memperlakukan argumen baris perintah sebagai urutan data numerik:

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);
        }
    }
    ...
}
Robᵩ
sumber
Tautan rusak. Bisakah Anda memperbaikinya?
Yuchen Zhong
5

Memang, solusi saya tidak akan berfungsi untuk bilangan bulat negatif, tetapi itu akan mengekstrak semua bilangan bulat positif dari teks input yang mengandung bilangan bulat. Itu menggunakan numeric_onlylokal:

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

Masukkan teks:

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

Bilangan bulat keluaran:

 5
25
7987
78
9878

Kelas numeric_onlydidefinisikan sebagai:

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

Demo online lengkap: http://ideone.com/dRWSj

Nawaz
sumber
4

Mungkin sedikit berlebihan, tetapi boost::lexical_cast<int>( theString )harus bekerja dengan baik.

James Kanze
sumber
Salah ketik. Itu harus sederhana boost::lexical_cast<int>( theString )(di mana theStringnama variabel yang berisi string yang ingin Anda konversi int).
James Kanze
1

Di Windows, Anda dapat menggunakan:

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, stringstreamperlu menentukan basis jika Anda perlu menafsirkan hexdecimal.

Jichao
sumber
1

Yah, banyak jawaban, banyak kemungkinan. Apa yang saya lewatkan di sini adalah beberapa metode universal yang mengubah string menjadi tipe integral C ++ yang berbeda (pendek, int, panjang, bool, ...). Saya datang dengan solusi berikut:

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

Berikut adalah contoh penggunaannya:

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

Mengapa tidak menggunakan operator output stringstream untuk mengubah string menjadi tipe integral? Inilah jawabannya: Katakanlah sebuah string berisi nilai yang melebihi batas untuk tipe integral yang dimaksudkan. Sebagai contoh, pada Wndows 64 max int adalah 2147483647. Mari kita berikan nilai string int max 1 +: string str = "2147483648". Sekarang, saat mengonversi string ke int:

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

x menjadi 2147483647, yang pasti merupakan kesalahan: string "2147483648" tidak seharusnya dikonversi ke int 2147483647. Fungsi yang disediakan untukIntegralType mengenali kesalahan tersebut dan melempar pengecualian.

Andrushenko Alexander
sumber
0

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

Keluaran:

2001, A Space Odyssey: 2001 and [, A Space Odyssey]

40c3: 16579

-10010110001: -1201

0x7f: 127

pengguna7967189
sumber
0

Kode Saya:

#include <iostream>
using namespace std;

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

    return 0;
}
Gonçalo Garrido
sumber
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"));
}
Amey Kudari
sumber
0

Untuk mengkonversi dari representasi string ke nilai integer, kita dapat menggunakan std :: stringstream.

jika nilai yang dikonversi di luar kisaran untuk tipe data integer, itu mengembalikan INT_MIN atau INT_MAX.

Juga jika nilai string tidak dapat direpresentasikan sebagai tipe data int yang valid, maka 0 dikembalikan.

#include 
#include 
#include 

int main() {

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

Output: 50

Sesuai dengan output di atas, kita dapat melihatnya dikonversi dari nomor string ke angka integer.

Sumber dan lainnya di string ke int c ++

Bala Singh
sumber
-2

Versi satu baris: long n = strtol(s.c_str(), NULL, base); .

( sadalah string, dan basemerupakanint seperti 2, 8, 10, 16.)

Anda dapat merujuk ke tautan ini untuk perincian lebih lanjut tentang strtol.


Gagasan intinya adalah menggunakan strtolfungsi, yang termasuk dalamcstdlib .

Karena strtolhanya menangani dengan chararray, kita perlu mengonversi stringke chararray. Anda bisa merujuk ke tautan ini .

Sebuah contoh:

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

yang akan menghasilkan:

1111000001011010
61530
f05a
1111000001011010
Hansimov
sumber
-3

ada cara mudah lainnya: misalkan Anda memiliki karakter seperti c='4' itu maka Anda dapat melakukan salah satu dari langkah-langkah ini:

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 .

cara kedua:

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

cupu
sumber
1
Pertanyaannya adalah tentang mengubah dari stringmenjadi intdaripada dari charke string.
Yuchen Zhong
buggy dan tidak cocok dengan pertanyaan
caoanan