Как я могу преобразовать std::string в int?
Просто быстрый вопрос. Я немного осмотрел интернет и нашел несколько решений, но ни одно из них еще не сработало. Глядя на преобразование строки в int, я не имею в виду коды ASCII.
Для быстрого разбега мы передаем в уравнении в виде строки. Мы должны разбить его, правильно отформатировать и решить линейные уравнения. Теперь, говоря это, я не могу преобразовать строку в int.
Я знаю, что строка будет в формате (-5) или (25) и т. Д., Так что это определенно int. Но как нам извлечь это из строки?
Один из способов, которым я думал, это запустить цикл for/while через строку, проверить на наличие цифры, извлечь после нее все цифры и посмотреть, есть ли начальный '-', если есть, умножить int на -1.
Это кажется слишком сложным для такой маленькой проблемы. Есть идеи?
27 ответов
В C++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
Возможные варианты описаны ниже:
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
}
Это решение короткое и элегантное, но оно доступно только на компиляторах C++11.
3. Третий вариант: потоки
#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
#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
Выводы
Подводя итог, можно сказать, что лучшим решением является C++11 std::stoi() или, как второй вариант, использование библиотек Qt. Все остальные решения не приветствуются или содержат ошибки.
std::istringstream ss(thestring);
ss >> thevalue;
Чтобы быть полностью правильным, вы захотите проверить флаги ошибок.
Чтобы быть более исчерпывающим (и как было запрошено в комментариях), я добавляю решение, данное C++17, используя std::from_chars
.
std::string str = "10";
int number;
std::from_chars(str.data(), str.data()+str.size(), result);
Если вы хотите проверить, было ли преобразование успешным:
std::string str = "10";
int number;
auto [ptr, ec] = std::from_chars(str.data(), str.data()+str.size(), result);
assert(ec == std::errc{});
// ptr points to chars after read number
Более того, чтобы сравнить производительность всех этих решений, перейдите по следующей ссылке быстрого тестирования: https://quick-bench.com/q/GBzK53Gc-YSWpEA9XskSZLU963Y
(std::from_chars
самый быстрый и
std::istringstream
самый медленный)
Используйте функцию atoi для преобразования строки в целое число:
string a = "25";
int b = atoi(a.c_str());
1. std::stoi
std::string str = "10";
int number = std::stoi(str);
2. струнные потоки
std::string str = "10";
int number;
std::istringstream(str) >> number
3. boost::lexical_cast
#include <boost/lexical_cast.hpp>
std::string str = "10";
int number;
try
{
number = boost::lexical_cast<int>(str);
std::cout << number << std::endl;
}
catch (boost::bad_lexical_cast const &e) // bad input
{
std::cout << "error" << std::endl;
}
4. std::atoi
std::string str = "10";
int number = std::atoi(str.c_str());
5. sscanf()
std::string str = "10";
int number;
if (sscanf(str .c_str(), "%d", &number) == 1)
{
std::cout << number << '\n';
}
else
{
std::cout << "Bad Input";
}
А как насчет 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);
}
}
...
}
По общему признанию, мое решение не будет работать для отрицательных целых чисел, но оно извлечет все положительные целые числа из входного текста, содержащего целые числа. Это использует numeric_only
локали:
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
В С++11 мы можем использовать функцию "stoi" для преобразования строки в целое число.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "16";
string s2 = "9.49";
string s3 = "1226";
int num1 = stoi(s1);
int num2 = stoi(s2);
int num3 = stoi(s3);
cout << "stoi(\"" << s1 << "\") is " << num1 << '\n';
cout << "stoi(\"" << s2 << "\") is " << num2 << '\n';
cout << "stoi(\"" << s3 << "\") is " << num3 << '\n';
return 0;
}
C++ со временем развивался, а вместе с ним и методы синтаксического анализа.int
с. В этом ответе я приведу краткое изложение.
Примечание: ответ в равной степени применим и к
long
,
float
и другие арифметические типы.
Сравнение
В следующей таблице сравниваются все параметры (только стандартные параметры C++, без сторонних библиотек) от самых последних до самых последних.
Рекомендуемая практика
- Если у вас высокопроизводительное приложение, используйте , или если оно недоступно. Накладные расходы на исключения в или были бы неприемлемы.
- В противном случае, если вам нужна совместимость с C, используйте
std::strto*
. - В противном случае, если в вашем проекте запрещены исключения, используйте
std::istringstream
. - В противном случае используйте
std::sto*
или создайте оболочку вокруг .
Большинство особых случаев маловероятны, поэтому в большинстве случаев используйте
std::stoi
или
std::from_chars
обертка :
// could be generalized with a template
bool parse_int(std::string_view str, int& out, int base = 10) {
auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out, base);
return err == std::errc{};
}
std::string s = ...;
if (int x; parse_int(s, x)) {
// x has been parsed :)
}
Преимущество такой оболочки в том, что вы всегда можете вернуться к другим функциям до C++17, всегда имея тот же интерфейс:
// alternative pre-C++17 version
bool parse_int(const std::string& str, int& out, int base = 10) {
errno = 0;
char* end = nullptr;
out = std::strtol(str.data(), str.data() + str.size(), &end, base);
return str.data() != end && errno == 0;
}
Если вас это не волнует, вы также можете сделатьparse_int
возвращатьсяstd::optional<int>
вместо назначения ссылки.
Это, вероятно, немного излишне, но boost::lexical_cast<int>( theString )
должен на работу довольно хорошо.
Ну, много ответов, много возможностей. Здесь мне не хватает универсального метода, который преобразует строку в различные целочисленные типы 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 обнаруживает такие ошибки и выдает исключение.
atoi
является встроенной функцией, которая преобразует строку в целое число, предполагая, что строка начинается с целочисленного представления.
В 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
нужно указать базу, если вам нужно интерпретировать шестнадцатеричное.
Я знаю, что этот вопрос действительно старый, но я думаю, что есть способ лучше.
#include <string>
#include <sstream>
bool string_to_int(std::string value, int * result) {
std::stringstream stream1, stream2;
std::string stringednumber;
int tempnumber;
stream1 << value;
stream1 >> tempnumber;
stream2 << tempnumber;
stream2 >> stringednumber;
if (!value.compare(stringednumber)) {
*result = tempnumber;
return true;
}
else return false;
}
Если я написал код правильно, это вернет логическое значение, которое сообщает вам, была ли строка допустимым числом, если ложь, то это не было числом, если правда, то это было число, и это число теперь результат, вы бы позвонили вот так:
std::string input;
std::cin >> input;
bool worked = string_to_int(input, &result);
Вы можете использовать
std::stringstream
, вот пример:
#include <iostream>
#include <sstream>
using namespace std;
string r;
int main() {
cin >> r;
stringstream tmp(r);
int s;
tmp >> s;
cout << s;
return 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"));
}
int stringToInt(std::string value) {
if(value.length() == 0 ) return 0; //tu zmiana..
if (value.find( std::string("NULL") ) != std::string::npos) {
return 0;
}
if (value.find( std::string("null") ) != std::string::npos) {
return 0;
}
int i;
std::stringstream stream1;
stream1.clear();
stream1.str(value);
stream1 >> i;
return i;
};
Чтобы преобразовать из строкового представления в целочисленное значение, мы можем использовать std::stringstream.
если преобразованное значение выходит за пределы диапазона для целочисленного типа данных, возвращается INT_MIN или INT_MAX.
Также, если строковое значение не может быть представлено как допустимый тип данных int, возвращается 0.
#include
#include
#include
int main() {
std::string x = "50";
int y;
std::istringstream(x) >> y;
std::cout << y << '\n';
return 0;
}
Выход: 50
Согласно приведенному выше выводу, мы видим, что он преобразован из строковых чисел в целое число.
Источник и многое другое в строке в int C++
С 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;
}
Выход:
2001, Космическая Одиссея: 2001 и [, Космическая Одиссея]
40с3: 16579
-10010110001: -1201
0x7f: 127
обработка ошибок не выполнена
int myatoti(string ip)
{
int ret = 0;
int sign = 1;
if (ip[0] == '-')
{
ip.erase(0, 1);
sign = -1;
}
int p = 0;
for (auto it = ip.rbegin(); it != ip.rend(); it++)
{
int val = *it - 48;
int hun = 1;
for (int k = 0; k < p; k++)
{
hun *= 10;
}
ret += val * hun;
p++;
}
return ret * sign;
}
Мой код:
#include <iostream>
using namespace std;
int main()
{
string s="32"; //String
int n=stoi(s); //Convert to int
cout << n + 1 << endl;
return 0;
}
Если у вас есть жесткий код :)
bool strCanBeInt(std::string string){
for (char n : string) {
if (n != '0' && n != '1' && n != '2' && n != '3' && n != '4' && n != '5'
&& n != '6' && n != '7' && n != '8' && n != '9') {
return false;
}
}
return true;
}
int strToInt(std::string string) {
int integer = 0;
int numInt;
for (char n : string) {
if(n == '0') numInt = 0;
if(n == '1') numInt = 1;
if(n == '2') numInt = 2;
if(n == '3') numInt = 3;
if(n == '4') numInt = 4;
if(n == '5') numInt = 5;
if(n == '6') numInt = 6;
if(n == '7') numInt = 7;
if(n == '8') numInt = 8;
if(n == '9') numInt = 9;
if (integer){
integer *= 10;
}
integer += numInt;
}
return integer;
}
Это обычно работает, когда я использую это:
int myint = int::Parse(mystring);
Есть еще один простой способ: предположим, у вас есть такой персонаж, как c='4'
поэтому вы можете сделать один из этих шагов:
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 .
второй способ:
q=c-'0'; the same , character '0' means 48
Однострочная версия: 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
Я думаю, что преобразование из
int
к
std::string
или наоборот нужны некоторые специальные функции, такие как
std::stoi()
но если вам нужно преобразовать
double
в
string
использовать
to_string()
(НЕ С#. С# — это .ToString(), а не to_string())