我想将一个字符串转换为整数,而不是ASCII码。
简单来说,我们会得到一个字符串方程。我们需要将其分解,正确格式化并解决线性方程。但是,我无法将字符串转换为整数。
我知道这个字符串的格式将是(-5)或(25)等,因此它一定是整数。但是如何从一个字符串中提取出它呢?
我考虑的一个方法是通过字符串运行for / while循环,检查数字,提取其后的所有数字,然后查看是否有前导'-',如果有,则将整数乘以-1。
但对于这样一个小问题来说,似乎有点过于复杂了。你们有什么好主意吗?
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
from_chars
更新这个答案?它应该比stoi
快几个数量级。 - NathanOliverstd::stoi("not-a-num")
,会导致程序崩溃,你该怎么办? - Yongqi Z以下是可能的选项:
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(str);
// string -> float
float f = std::stof(str);
// string -> double
double d = std::stod(str);
} catch (...) {
// error management
}
这个解决方案简短而优雅,但只适用于符合C++11标准的编译器。
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
的包装器,文档建议使用sstream
以获得更好的错误管理(请参见此处)。
5. strto()*
由于需要进行错误管理,因此该解决方案非常冗长,可在此处找到其描述。由于没有任何函数返回普通整数,所以在需要整数的情况下需要进行转换(请参见此处了解如何进行转换)。
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 库。其他所有解决方案都不被鼓励,或者存在漏洞。
sscanf
。这是一个 C API 函数,而问题涉及到 C++。如果您打算使用 sscanf
,请至少使用 std::
。 - Marc Dirvenstd::istringstream ss(thestring);
ss >> thevalue;
为了完全正确,您需要检查错误标志。
(-5)
中提取-5
。 - Nawazstd::from_chars
解决方案。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
std::from_chars
是最快的,而std::istringstream
则最慢。atoi
所没有提供的一个特性。 - Wolfatoi
。strtol
能够完成 atoi
的所有功能,而且更加安全可靠。 - Ben Voigtatoi
的一个重要原因是它仅通过返回0
来报告转换失败! atoi
不会不安全地失败,而是_默默失败_。 - Vainstein K0
来报告。其他一些会导致atoi
出现未定义的行为。这使得它对于验证不受信任的输入毫无用处。https://wiki.sei.cmu.edu/confluence/display/c/ERR07-C.+Prefer+functions+that+support+error+checking+over+equivalent+functions+that+don%27t - Ben Voigtstd::stoi()
std::string str = "10";
int number = std::stoi(str);
std::string str = "10";
int number;
std::istringstream(str) >> number;
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;
}
std::atoi()
std::string str = "10";
int number = std::atoi(str.c_str());
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];
}
};
#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;
}
这可能有点过度设计,但 boost::lexical_cast<int>( theString )
应该能够很好地完成工作。
boost::lexical_cast<int>(theString)
(其中 theString
是包含要转换为 int
的字符串的变量名称)。 - James Kanze
atoi()
函数吗? - i_am_jorfint atoi (const char* str);
功能:将参数str
所指向的字符串转换为一个整数(类型为int
)。返回值:如果转换成功,则返回该整数,否则返回零。注意事项:int
类型的范围,则返回INT_MAX
或INT_MIN
,具体取决于转换结果的符号。/* atoi examples */ #include /* printf */
#include /* atoi */
int main ()
{
int i;
char buffer[256];
printf ("Enter a number: ");
fgets (buffer, 256, stdin);
i = atoi (buffer);
printf ("The value entered is %d. Its double is %d.\n",i,i*2);
return 0;
}
- i_am_jorfmyString
的std::string
,而想要使用atoi
函数,则需要输入atoi(myString.c_str())
。 - Robᵩ