Как я могу преобразовать std :: string в int?

367

Просто задай быстрый вопрос. Я немного поглядел в интернете, и я нашел несколько решений, но никто из них еще не работал. Глядя на преобразование строки в int, и я не имею в виду коды ASCII.

Для быстрого прогона мы передаем уравнение в виде строки. Мы должны сломать его, правильно отформатировать и решить линейные уравнения. Теперь, говоря это, я не могу преобразовать строку в int.

Я знаю, что строка будет в формате (-5) или (25) и т.д., так что это определенно int. Но как мы извлекаем это из строки?

Один из способов, которым я думал, - запустить цикл for/while через строку, проверить цифру, извлечь все цифры после этого, а затем посмотреть, есть ли ведущий "-", если есть, умножить int на -1.

Похоже, что для такой маленькой проблемы это немного сложнее. Любые идеи?

  • 7
    Вы пробовали atoi() ?
  • 3
    cplusplus.com/reference/clibrary/cstdlib/atoi
Показать ещё 12 комментариев
Теги:
string
int

13 ответов

590
Лучший ответ

В С++ 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

  • 3
    Для проблем с std :: stoi см. Stackoverflow.com/a/6154614/195527 : он преобразует "11x" в целое число 11 .
  • 4
    #include <stdlib.h> / * atoi * /
Показать ещё 1 комментарий
53
std::istringstream ss(thestring);
ss >> thevalue;

Чтобы быть полностью корректным, вы захотите проверить флаги ошибок.

  • 2
    Это не будет извлекать -5 из (-5) .
  • 0
    @ Наваз, действительно ли присутствуют парены, или это просто то, как ОП представляет свои строки?
Показать ещё 6 комментариев
35

используйте функцию atoi для преобразования строки в целое число:

string a = "25";

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

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

  • 10
    Никогда не используйте atoi . strtol делает все, что делает atoi , но лучше, и терпит неудачу безопасно.
28

Возможные варианты описаны ниже:

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

Это ошибка (также показанная cppcheck), потому что "scanf без ограничений ширины поля может сбой с огромными входными данными в некоторых версиях libc" (см. здесь, и здесь).

2. Второй вариант: 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
        }   

Это решение является коротким и элегантным, но доступно только на компиляторах С++ 11 compliants.

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 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, и в документации предлагается использовать sstrem для лучшего управления ошибками (см. здесь).

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     

Выводы

Подводя итоги, лучшим решением является С++ 11 std:: stoi() или, как второй вариант, использование библиотек Qt. Все другие решения обескуражены или ошибочны.

  • 0
    Ссылка не работает ...
  • 0
    Исправлена. Спасибо за сообщение.
Показать ещё 1 комментарий
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);
        }
    }
    ...
}
  • 0
    Ссылка не работает. Не могли бы вы это исправить?
5

По общему признанию, мое решение не будет работать для отрицательных целых чисел, но оно будет извлекать все положительные целые числа из входного текста, содержащего целые числа. Он использует 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;
}

Текст ввода:

 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 ) должен работать довольно хорошо.

  • 0
    theString& ? Что такое & ?
  • 0
    Опечатка. Это должно быть просто boost::lexical_cast<int>( theString ) (где theString - имя переменной, содержащей строку, которую вы хотите преобразовать в int ).
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 необходимо указать базу, если вам нужно интерпретировать hexdecimal.

1

atoi - встроенная функция, которая преобразует строку в целое число, предполагая, что строка начинается с целочисленного представления.

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

  • 0
    Каждый раз, когда вы думаете об atoi , используйте вместо этого strtol .
0

long n = strtol(s.c_str(), NULL, base); версия: long n = strtol(s.c_str(), NULL, base); ,

(s это строка, а base это int такой как 2, 8, 10, 16.)

Вы можете обратиться к этой ссылке для более подробной информации о strtol.


Основная идея заключается в том, чтобы использовать функцию strtol, которая включена в cstdlib.

Поскольку strtol только с массивом char, нам нужно преобразовать string в массив char. Вы можете обратиться к этой ссылке.

Пример:

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

Ну, много ответов, много возможностей. Здесь мне не хватает универсального метода, который преобразует строку в различные целочисленные типы 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

Почему бы просто не использовать оператор вывода stringstream для преобразования строки в целочисленный тип? Вот ответ: допустим, строка содержит значение, которое превышает предел для целочисленного типа. Например, в Wndows 64 max int равно 2147483647. Давайте присвоим строке значение max int + 1: string str = "2147483648". Теперь при преобразовании строки в int:

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

x становится 2147483647, что определенно является ошибкой: строка "2147483648" не должна была быть преобразована в int 2147483647. Предоставленная функция toIntegralType обнаруживает такие ошибки и выдает исключение.

-1

существует еще один простой способ: предположим, что у вас есть символ типа c='4', поэтому вы можете сделать один из следующих шагов:

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 .

второй способ:

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

  • 1
    Речь идет о преобразовании из string в int а не из char в string .
  • 0
    глючит и не соответствует вопросу
-3

Это нормально работает, когда я его использую:

int myint = int::Parse(mystring);
  • 0
    Почему внизу, мне любопытно?
  • 12
    Вероятно, потому что это C #, а не C ++.
Показать ещё 3 комментария
Сообщество Overcoder
Наверх
Меню