Nasıl std :: string int dönüştürmek?


484

Hemen bir soru sor. İnternete biraz baktım ve birkaç çözüm buldum ama hiçbiri işe yaramadı. Bir dize int dönüştürmek seyir ve ASCII kodları demek değil.

Hızlı bir düşüş için, bir denklemde dize olarak geçiriliriz. Onu parçalayacağız, doğru biçimlendireceğiz ve lineer denklemleri çözeceğiz. Şimdi, bunu söyleyerek, bir dizeyi int'ye dönüştüremiyorum.

Dize (-5) veya (25) vb. Biçiminde olacağını biliyorum, bu yüzden kesinlikle bir int. Ama bunu bir dizeden nasıl çıkarabiliriz?

Düşündüğüm bir yol, dize boyunca bir for / while döngüsü çalıştırıyor, bir rakamı kontrol ediyor, bundan sonra tüm rakamları çıkarıyor ve sonra önde gelen bir '-' olup olmadığını görmek için bakıyoruz, int ile çarpın - 1.

Böyle küçük bir sorun için biraz fazla karmaşık gibi görünüyor. Herhangi bir fikir?


9
Denedin atoi()mi
i_am_jorf



7
@Chad Yani dilin standart kütüphanelerle yapabileceği bir şey için bütün bir kütüphaneyi kullanmasını mı tavsiye ediyorsunuz?
Bojangles

6
@Brandon, eğer bir tane varsa std::string myStringve kullanmak istiyorsanız atoi, o zaman söylemek istersiniz atoi(myString.c_str()).
Robᵩ

Yanıtlar:


726

C ++ 11'de std::stringbir sayı türüne kadar bazı güzel yeni dönüştürme işlevleri vardır .

Yani yerine

atoi( str.c_str() )

kullanabilirsiniz

std::stoi( str )

strolarak numaran nerede std::string.

Sayıların tüm lezzetleri için sürüm vardır: long stol(string), float stof(string), double stod(string), ... bkz http://en.cppreference.com/w/cpp/string/basic_string/stol


5
Std :: stoi ile ilgili sorunlar için bkz. Stackoverflow.com/a/6154614/195527 : "11x"tamsayıya dönüştürülecektir 11.
CC.

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

4
@CC Bu da atoi'nin davranışıdır: cplusplus.com/reference/cstdlib/atoi "Dize, ayrılmaz sayıyı oluşturan, yok sayılan ve bu işlevin davranışı üzerinde hiçbir etkisi olmayan karakterlerden sonra ek karakterler içerebilir."
Kalay Büyücüsü

4
Bu cevabı from_charsC ++ 17'den güncellemek ister misiniz ? Büyüklük sıralamasından daha hızlı olması gerekiyordu stoi.
NathanOliver

stoitercih edilmelidir. Bkz. Neden atoi () kullanmamalıyım?
phuclv

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

Tam olarak doğru olmak için hata bayraklarını kontrol etmek isteyeceksiniz.


2
Bu ayıklamak olmayacak -5dan (-5).
Nawaz

@Nawaz, parens aslında orada mı, yoksa OP dizelerini nasıl sunuyor?
Winston Ewert

Bilmiyorum. Sadece yaklaşımın sınırlılığına işaret ediyorum.
Nawaz

16
@Nawaz, "WERWER" girişinde de çalışamaz. Ben parens aslında onun gerçek dize bir parçası olduğunu sanmıyorum ve onları ayrıştırmak değil aslında alakalı olduğunu sanmıyorum.
Winston Ewert

4
@Nawaz, tamam ... Kelimeyi bu şekilde anlamadım ama nasıl yapabileceğini görüyorum.
Winston Ewert

44

Olası seçenekler aşağıda açıklanmıştır:

1. İlk seçenek: 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

Bu bir hatadır (cppcheck tarafından da gösterilir) çünkü "alan genişliği sınırları olmayan scanf bazı libc sürümlerinde büyük giriş verileriyle çökebilir" ( buraya ve buraya bakın ).

2. İkinci seçenek: 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
        }   

Bu çözüm kısa ve zariftir, ancak yalnızca C ++ 11 uyumlu derleyicilerde mevcuttur.

3. Üçüncü seçenek: 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 ??

Bununla birlikte, bu çözüm ile kötü girdi arasında ayrım yapmak zordur ( buraya bakın ).

4. Dördüncü seçenek: 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
        }

Ancak, bu sadece bir sarıcıdır sstreamve belgeler sstreamdaha iyi hata yönetimi için kullanılmasını önermektedir ( buraya bakın ).

5. Beşinci seçenek: strto * ()

Bu çözüm hata yönetimi nedeniyle çok uzundur ve burada açıklanmaktadır. Hiçbir işlev bir düz int döndürmediği için, tamsayı olması durumunda bir dönüştürmeye ihtiyaç duyulur ( bu dönüştürmenin nasıl gerçekleştirilebileceği için buraya bakın ).

6. Altıncı seçenek: 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     

Sonuçlar

Özetle, en iyi çözüm C ++ 11 std::stoi()veya ikinci bir seçenek olarak Qt kütüphanelerinin kullanımıdır. Diğer tüm çözümler cesareti kırılmış veya buggy.


Sabit. Raporladığınız için teşekkürler.
Claudio

Güzel özet, çok teşekkürler. Yalnızca ayrıntılarla ilgilenen kişilerin okumaya devam etmesi için nihai çözümü öneren bir ilk yorum eklemeyi önerebilir miyim?
luca

1
bu kabul edilen cevap olmalı, ayrıca unuttun (ya da eski bir cevaba neden olduğunu eklemelisin) from_chars
xception 8


9

Boost.Lexical_cast ne olacak ?

İşte onların örneği:

Aşağıdaki örnek, komut satırı bağımsız değişkenlerini bir sayısal veri dizisi olarak ele alır:

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

Bağlantı koptu. Tamir edebilir misin?
Yuchen Zhong

5

Kuşkusuz, çözümüm negatif tamsayılar için işe yaramaz, ancak tamsayı içeren giriş metninden tüm pozitif tamsayıları ayıklar. numeric_onlyYerel ayarı kullanır :

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

Giriş metni:

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

Çıkış tamsayıları:

 5
25
7987
78
9878

Sınıf numeric_onlyşu şekilde tanımlanır:

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

Komple çevrimiçi demo: http://ideone.com/dRWSj


4

Muhtemelen biraz abartılı, ama boost::lexical_cast<int>( theString )iş için oldukça iyi olmalı.


Bir yazım hatası. Basit olmalıdır boost::lexical_cast<int>( theString )( theStringdönüştürmek istediğiniz dizeyi içeren değişkenin adı int).
James Kanze


1

Windows'da şunları kullanabilirsiniz:

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, stringstreamonaltılık yorum yapmanız gerekiyorsa, tabanı belirtmeniz gerekir.


1

Pek çok cevap, çok fazla olasılık. Ne eksik burada farklı bir C ++ integral türleri (kısa, int, uzun, bool, ...) bir dize dönüştüren bazı evrensel yöntemdir. Aşağıdaki çözümü buldum:

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

Kullanım örnekleri:

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

Neden bir stringi integral tipine dönüştürmek için stringstream çıktı operatörünü kullanmıyorsunuz? İşte cevap: Diyelim ki bir dize, amaçlanan integral türü için sınırı aşan bir değer içeriyor. Örneğin Wndows 64 max int için 2147483647'dir. Bir dizeye max int + 1 değeri atayalım: string str = "2147483648". Şimdi, dizeyi int'e dönüştürürken:

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

x 2147483647 olur, kesinlikle bir hata nedir: "2147483648" dizesinin int 2147483647'ye dönüştürülmemesi gerekiyordu. IntegralType'a sağlanan işlev bu tür hataları bulur ve istisna atar.


0

Gönderen 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;
}

Çıktı:

2001, Bir Uzay Odyssey: 2001 ve [, Bir Uzay Odyssey]

40c3: 16579

-10010110001: -1201

0x7f: 127


0

Kodum:

#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

Dize gösteriminden tamsayı değerine dönüştürmek için std :: stringstream öğesini kullanabiliriz.

dönüştürülen değer tamsayı veri türü için aralık dışındaysa, INT_MIN veya INT_MAX döndürür.

Ayrıca, dize değeri geçerli bir int veri türü olarak gösterilemiyorsa, 0 döndürülür.

#include 
#include 
#include 

int main() {

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

Çıktı: 50

Yukarıdaki çıktıya göre, dize numaralarından tamsayı sayısına dönüştürüldüğünü görebiliriz.

Int c ++ dizesinde kaynak ve daha fazlası


-2

Bir satır sürümü: long n = strtol(s.c_str(), NULL, base);.

( sDize ve basebir intörneğin 2, 8, 10, 16)

İle ilgili daha fazla bilgi için bu bağlantıya bakabilirsiniz strtol.


Ana fikir, strtoliçinde yer alan işlevi kullanmaktır cstdlib.

Yana strtololan tek kulplu chardizisi, biz dönüştürmek gerekir stringiçin chardiziden. Bu bağlantıya başvurabilirsiniz .

Bir örnek:

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

hangi çıktı:

1111000001011010
61530
f05a
1111000001011010

-3

başka bir kolay yol daha var: varsayalım ki c='4' şu adımlardan birini yapabilirsin:

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 .

ikinci yol:

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


1
Sorusu dönüştürme hakkındadır stringiçin intyerine gelen charetmek string.
Yuchen Zhong

adamcağız ve soru
eşleşmiyor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.