如何将 std::string 转换为 int?
Posted
技术标签:
【中文标题】如何将 std::string 转换为 int?【英文标题】:How can I convert a std::string to int? 【发布时间】:2011-12-01 14:22:04 【问题描述】:我想将字符串转换为 int,我指的不是 ASCII 码。
为了快速了解一下,我们以字符串的形式传入一个方程。我们要将其分解,正确格式化并求解线性方程。现在,这么说,我无法将字符串转换为 int。
我知道该字符串将采用 (-5) 或 (25) 等格式,所以它绝对是一个 int。但是我们如何从字符串中提取它呢?
我想的一种方法是在字符串中运行一个 for/while 循环,检查一个数字,然后提取所有数字,然后查看是否有前导“-”,如果有,乘以整数 -1。
不过,对于这样一个小问题,它似乎有点过于复杂。有什么想法吗?
【问题讨论】:
你试过atoi()
吗?
cplusplus.com/reference/clibrary/cstdlib/atoi
***.com/search?q=convert+string+int++c%2B%2B
@Chad 所以你建议他使用整个库来做一些语言可以用标准库做的事情?
@Brandon,如果你有std::string
myString
,并且想使用atoi
,那么你想说atoi(myString.c_str())
。
【参考方案1】:
你可以使用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;
【讨论】:
【参考方案2】:可能的选项如下所述:
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 也显示),因为“在某些版本的 libc 上,没有字段宽度限制的 scanf 可能会因大量输入数据而崩溃”(请参阅 here 和 here) .
2. 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
此解决方案简短而优雅,但仅适用于兼容 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 ??
但是,使用此解决方案很难区分错误输入(请参阅here)。
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
的包装,文档建议使用sstream
来更好地管理错误(请参阅here)。
5. strto()*
由于错误管理,这个解决方案很长,这里有描述。由于没有函数返回纯 int,因此在整数的情况下需要进行转换(请参阅 here 了解如何实现此转换)。
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 库。不鼓励使用所有其他解决方案或存在错误。
【讨论】:
已修复。感谢您的报告。 漂亮的总结,非常感谢。我是否可以建议添加一个初步评论,建议最终解决方案,以便只有对细节感兴趣的人才能继续阅读? 这应该是公认的答案,你也忘记了(或者更确切地说应该添加因为它是旧答案)from_chars 不要使用sscanf
。这是一个 C API 函数,问题是关于 C++ 的。如果您打算使用sscanf
,那么至少使用std::
。【参考方案3】:
我认为从int
转换为std::string
或反之亦然需要一些特殊功能,例如std::stoi()
但是如果您需要将double
转换为string
,请使用to_string()
(不是 C#。C# 是 .ToString() 而不是 to_string())
【讨论】:
std::stoi
已经在多个其他答案中提到,问题不是关于将双精度转换为字符串。
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。【参考方案4】:
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;
;
【讨论】:
【参考方案5】:为了更加详尽(正如 cmets 中所要求的那样),我使用 std::from_chars
添加了 C++17 给出的解决方案。
std::string str = "10";
int number;
std::from_chars(str.data(), str.data()+str.size(), number);
如果要检查是否转换成功:
std::string str = "10";
int number;
auto [ptr, ec] = std::from_chars(str.data(), str.data()+str.size(), number);
assert(ec == std::errc);
// ptr points to chars after read number
此外,要比较所有这些解决方案的性能,请参阅以下快速基准链接:https://quick-bench.com/q/GBzK53Gc-YSWpEA9XskSZLU963Y
(std::from_chars
最快,std::istringstream
最慢)
【讨论】:
【参考方案6】:如果你没有硬编码:)
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;
【讨论】:
这不处理溢出或负数。第二个函数和atoi
很像,不知道为什么要手写。此外,还有一些地方可以改进:不要按值传递字符串,更多地使用标准函数(第一个函数可以使用 std::all_of
+ std::isdigit
之类的东西重写)。【参考方案7】:
我知道这个问题已经很老了,但我认为有更好的方法来解决这个问题
#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);
【讨论】:
【参考方案8】:1。标准::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";
【讨论】:
【参考方案9】:要将字符串表示形式转换为整数值,我们可以使用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
根据上面的输出,我们可以看到它从字符串数字转换为整数。
来源和更多信息string to int c++
【讨论】:
【参考方案10】: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"));
【讨论】:
【参考方案11】:我的代码:
#include <iostream>
using namespace std;
int main()
string s="32"; //String
int n=stoi(s); //Convert to int
cout << n + 1 << endl;
return 0;
【讨论】:
【参考方案12】:来自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 和 [,太空漫游]
40c3: 16579
-10010110001:-1201
0x7f: 127
【讨论】:
【参考方案13】:单行版本:long n = strtol(s.c_str(), NULL, base);
。
(s
是字符串,base
是 int
,例如 2、8、10、16。)
strtol
的更多详情可以参考this link。
核心思想是使用strtol
函数,包含在cstdlib
中。
由于strtol
只处理char
数组,我们需要将string
转换为char
数组。可以参考this link。
一个例子:
#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
【讨论】:
【参考方案14】:嗯,很多答案,很多可能性。我在这里缺少的是一些通用方法,可以将字符串转换为不同的 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 上,最大 int 为 2147483647。 让我们为字符串分配一个值 max int + 1:string str = "2147483648"。 现在,将字符串转换为 int 时:
stringstream ss(str);
int x;
ss >> x;
x 变成 2147483647,这绝对是一个错误:字符串“2147483648”不应该转换为 int 2147483647。提供的函数 toIntegralType 发现此类错误并引发异常。
【讨论】:
【参考方案15】: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);
...
【讨论】:
链接已损坏。你能解决它吗?【参考方案16】:这可能有点矫枉过正,但是
boost::lexical_cast<int>( theString )
应该去工作
很好。
【讨论】:
一个错字。它应该只是boost::lexical_cast<int>( theString )
(其中theString
是包含要转换为int
的字符串的变量的名称)。【参考方案17】:
在 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
如果需要解释十六进制,需要指定基数。
【讨论】:
【参考方案18】:在 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
【讨论】:
有关 std::stoi 的问题,请参阅 ***.com/a/6154614/195527 :它将"11x"
转换为整数 11
。
#include from_chars
更新这个答案吗?它应该比stoi
快几个数量级。
stoi
应该是首选。见Why shouldn't I use atoi()?【参考方案19】:
还有另一种简单的方法:假设您有一个像 c='4'
这样的角色,因此您可以执行以下步骤之一:
第一个: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
【讨论】:
问题是关于从string
转换为int
而不是从char
转换为string
。
有问题且与问题不匹配【参考方案20】:
使用atoi函数将字符串转换为整数:
string a = "25";
int b = atoi(a.c_str());
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
【讨论】:
永远不要使用atoi
。 strtol
做所有atoi
做的事情,但更好,并且安全失败。
扩展@BenVoigt 的评论:避免atoi
的一个重要原因是它仅通过返回0
来报告转换失败! atoi
与其说是不安全地失败,不如说是默默地失败。
@VainsteinK:返回0
会报告一些故障。其他人使用atoi
导致未定义的行为。这使得它对于验证不受信任的输入毫无用处。 wiki.sei.cmu.edu/confluence/display/c/…【参考方案21】:
诚然,我的解决方案不适用于负整数,但它会从包含整数的输入文本中提取所有正整数。它使用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
【讨论】:
【参考方案22】:atoi
是一个将字符串转换为整数的内置函数,假设字符串以整数表示形式开头。
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
【讨论】:
任何时候想到atoi
,请改用strtol
。【参考方案23】:
std::istringstream ss(thestring);
ss >> thevalue;
为了完全正确,您需要检查错误标志。
【讨论】:
这不会从(-5)
中提取-5
。
@Nawaz,括号是否真的存在,或者这就是 OP 展示他的字符串的方式?
我不知道。我只是指出这种方法的局限性。
@Nawaz,它也不能对输入“WERWER”进行操作。我不认为括号实际上是他实际字符串的一部分,而且我不认为我不解析它们的事实是相关的。
@Nawaz,好吧...我不这么认为,但我知道你怎么能这样做。以上是关于如何将 std::string 转换为 int?的主要内容,如果未能解决你的问题,请参考以下文章