Jak mogę przekonwertować std:: string na int?

Mam szybkie pytanie. Rozglądałem się trochę po Internecie i znalazłem kilka rozwiązań, ale żadne z nich jeszcze nie zadziałało. Patrząc na konwersję łańcucha do int i nie mam na myśli kodów ASCII.

W przypadku szybkiego rozruchu, jesteśmy przekazywani w równaniu jako ciąg znaków. Mamy je rozbić, sformatować poprawnie i rozwiązać równania liniowe. Mówiąc to, nie jestem w stanie przekonwertować ciągu znaków na int.

Wiem, że ciąg będzie w formacie (-5) lub (25) itd. więc to na pewno int. Ale jak to wydobyć ze Sznurka?

Jednym ze sposobów, o którym myślałem, jest uruchomienie pętli for / while przez ciąg znaków, sprawdzenie cyfry, wyodrębnienie wszystkich cyfr po tym, a następnie sprawdzenie, czy nie ma wiodącego' -', jeśli istnieje, pomnóż int przez -1.

Wydaje się to trochę zbyt skomplikowane dla tak małego problemu. Jakieś pomysły?

 320
Author: Claudio, 2011-10-05

11 answers

W C++11 jest kilka nowych funkcji konwertujących z std::string na typ liczby.

Więc zamiast

atoi( str.c_str() )

Możesz użyć

std::stoi( str )

Gdzie str jest twoją liczbą jako std::string.

Istnieją wersje dla wszystkich smaków liczb: long stol(string), float stof(string), double stod(string),... zobacz http://en.cppreference.com/w/cpp/string/basic_string/stol

 513
Author: tgmath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-20 08:53:55
std::istringstream ss(thestring);
ss >> thevalue;

Aby być w pełni poprawnym, należy sprawdzić flagi błędów.

 54
Author: Winston Ewert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-05 15:26:21

Użyj funkcji atoi do konwersji ciągu znaków na liczbę całkowitą:

string a = "25";

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

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

 32
Author: brenjt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-30 21:52:57

Możliwe opcje są opisane poniżej:

1. Pierwsza opcja: 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

Jest to błąd (pokazany również przez cppcheck), ponieważ "scanf bez ograniczeń szerokości pola może zawiesić się z ogromnymi danymi wejściowymi w niektórych wersjach libc" (zobacz tutaj i tutaj ).

2. Druga opcja: std:: sto*()

    #include <iostream>
    #include <string>

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

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

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

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

To rozwiązanie jest krótkie i eleganckie, ale jest dostępne tylko na kompilatorach zgodnych z C++11.

3. Trzecia opcja: 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 ??

Jednak przy takim rozwiązaniu trudno jest odróżnić złe dane wejściowe (patrz tutaj ).

4. Czwarta opcja: 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
        }

Jest to jednak tylko wrapper sstream, a dokumentacja sugeruje użycie sstrem dla lepszego zarządzania błędami (zobacz tutaj ).

5. Piąta opcja: strto*()

To rozwiązanie jest bardzo długie, ze względu na zarządzanie błędami, i jest opisane tutaj. Ponieważ żadna funkcja nie zwraca zwykłej liczby całkowitej, konwersja jest potrzebna w przypadku liczby całkowitej (zobacz tutaj , aby dowiedzieć się, jak tę konwersję można osiągnąć).

6. Szósta opcja: 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     

Wnioski

Podsumowując, najlepszym rozwiązaniem jest C++11 std::stoi() lub, jako druga opcja, użycie bibliotek Qt. Wszystkie inne rozwiązania są zniechęcane lub wadliwe.

 19
Author: Claudio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-20 15:35:13

A co z wzmocnieniem.Lexical_cast ?

Oto ich przykład:

Poniższy przykład traktuje argumenty linii poleceń jako ciąg danych liczbowych:

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);
        }
    }
    ...
}
 9
Author: Robᵩ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 11:53:09

Wprawdzie moje rozwiązanie nie zadziała dla liczb ujemnych, ale wyodrębni wszystkie liczby dodatnie z tekstu wejściowego zawierającego liczby całkowite. Używa numeric_only locale:

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

Tekst wejściowy:

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

Wyjściowe liczby całkowite:

 5
25
7987
78
9878

Klasa numeric_only jest zdefiniowana jako:

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

Pełne demo online: http://ideone.com/dRWSj

 5
Author: Nawaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-05 15:36:19

To pewnie trochę przesada, ale boost::lexical_cast<int>( theString ) powinien do pracy całkiem dobrze.

 4
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-09 21:10:41

atoi jest wbudowaną funkcją, która konwertuje łańcuch znaków na liczbę całkowitą, zakładając, że łańcuch zaczyna się od reprezentacji liczb całkowitych.

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

 1
Author: Eric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-05 15:27:57

W Windows możesz użyć:

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 musisz określić bazę, jeśli chcesz zinterpretować hexdecimal.

 1
Author: Jichao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-25 12:44:28

To normalnie działa, gdy go używam:

int myint = int::Parse(mystring);
 -2
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-01 09:44:49

Jest inny prosty sposób : Załóżmy, że masz postać podobną do c='4', dlatego możesz wykonać jeden z następujących kroków:

1st: 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 .

Druga droga:

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

 -2
Author: nooB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-02 08:49:08