只是有一个简短的问题.我已经在互联网上看了很多,我找到了一些解决方案,但没有一个已经有效.看一下将字符串转换为int,我不是指ASCII码.
为了快速减少,我们将方程作为字符串传递.我们要将其分解,正确格式化并求解线性方程.现在,在说,我无法将字符串转换为int.
我知道字符串将采用格式(-5)或(25)等,所以它肯定是一个int.但是我们如何从字符串中提取它?
我想的一种方法是通过字符串运行for/while循环,检查一个数字,然后提取所有数字,然后查看是否有一个前导' - ',如果存在,则将int乘以 - 1.
虽然这个小问题看起来有点过于复杂.有任何想法吗?
tgm*_*ath 658
在C++ 11中,有一些很好的新转换函数从std::string
数字类型.
而不是
atoi( str.c_str() )
Run Code Online (Sandbox Code Playgroud)
您可以使用
std::stoi( str )
Run Code Online (Sandbox Code Playgroud)
str
你的号码在哪里std::string
.
有版本号的所有口味:
long stol(string)
,float stof(string)
,double stod(string)
,...查看http://en.cppreference.com/w/cpp/string/basic_string/stol
Win*_*ert 58
std::istringstream ss(thestring);
ss >> thevalue;
Run Code Online (Sandbox Code Playgroud)
要完全正确,您需要检查错误标志.
bre*_*njt 37
使用atoi函数将字符串转换为整数:
string a = "25";
int b = atoi(a.c_str());
Run Code Online (Sandbox Code Playgroud)
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
Cla*_*dio 35
可能的选项如下所述:
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
Run Code Online (Sandbox Code Playgroud)
这是一个错误(也由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
}
Run Code Online (Sandbox Code Playgroud)
此解决方案简短而优雅,但仅适用于C++ 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 ??
Run Code Online (Sandbox Code Playgroud)
但是,使用此解决方案很难区分不良输入(请参阅此处).
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
}
Run Code Online (Sandbox Code Playgroud)
但是,这只是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
Run Code Online (Sandbox Code Playgroud)
结论
总而言之,最好的解决方案是C++ 11 std :: stoi(),或者作为第二种选择,使用Qt库.所有其他解决方案都不鼓励或错误.
use*_*747 14
std::stoi()
std::string str = "10";
int number = std::stoi(str);
Run Code Online (Sandbox Code Playgroud)
std::string str = "10";
int number;
std::istringstream(str) >> number;
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
std::atoi()
std::string str = "10";
int number = std::atoi(str.c_str());
Run Code Online (Sandbox Code Playgroud)
sscanf()
std::string str = "10";
int number;
if (sscanf(str .c_str(), "%d", &number) == 1)
{
std::cout << number << '\n';
}
else
{
std::cout << "Bad Input";
}
Run Code Online (Sandbox Code Playgroud)
Pas*_* H. 11
为了更加详尽(正如评论中所要求的那样),我使用std::from_chars
.
std::string str = "10";
int number;
std::from_chars(str.data(), str.data()+str.size(), number);
Run Code Online (Sandbox Code Playgroud)
如果要检查转换是否成功:
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
Run Code Online (Sandbox Code Playgroud)
此外,要比较所有这些解决方案的性能,请参阅以下快速基准链接:https : //quick-bench.com/q/GBzK53Gc-YSWpEA9XskSZLU963Y
(std::from_chars
是最快的,std::istringstream
也是最慢的)
这是他们的例子:
以下示例将命令行参数视为一系列数字数据:
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);
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
小智 6
在C++11中,我们可以使用“stoi”函数将字符串转换为int
#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;
}
Run Code Online (Sandbox Code Playgroud)
不可否认,我的解决方案不适用于负整数,但它将从包含整数的输入文本中提取所有正整数.它使用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;
}
Run Code Online (Sandbox Code Playgroud)
输入文本:
the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878
Run Code Online (Sandbox Code Playgroud)
输出整数:
5
25
7987
78
9878
Run Code Online (Sandbox Code Playgroud)
该类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];
}
};
Run Code Online (Sandbox Code Playgroud)
完整的在线演示:http://ideone.com/dRWSj
C++ 随着时间的推移而发展,解析方法也随之发展int
。\n我将在此答案中提供摘要。
注意:答案同样适用于long
、float
、 和其他算术类型。
下表按最新到最新的顺序比较了所有选项(仅 C++ 标准选项,无第三方库)。
\n方法 | 错误处理 | 优点缺点 |
---|---|---|
std::from_chars c++17 | std::from_chars_result (手动错误处理) | \xe2\x9c\x94\xef\xb8\x8f 快速且零开销 \xe2\x9c\x94\xef\xb8\x8f 支持任何基数作为运行时参数 \xe2\x9c\x94\xef\xb8\x8f 也可以对于浮点数,选择的格式 \xe2\x9d\x8c 界面不符合人体工程学 \xe2\x9d\x8c 没有区域设置支持 |
std::sto*系列 c++11 | std::invalid_argument std::out_of_range (例外) | \xe2\x9c\x94\xef\xb8\x8f 简单接口 \xe2\x9c\x94\xef\xb8\x8f 支持任何基数作为运行时参数 \xe2\x9c\x94\xef\xb8\x8f 也适用于浮点数 \xe2\x9c\x94\xef\xb8\x8f 快乐路径中没有开销 \xe2\x9d\x8c 如果错误常见则效率低下 \xe2\x9d\x8c 晦涩的名称 \xe2\x9d\x8c 没有语言环境支持 |
std::istringstream c++98 | bool 旗帜,或stream.exceptions() | \xe2\x9c\x94\xef\xb8\x8f 通用方法(对于带有>> 运算符的类型)\xe2\x9c\x94\xef\xb8\x8f 考虑区域设置(例如可以更改基数) \xe2\x9c\x94\xef\xb8 \x8f 可以检测不同的格式(例如 0x... )\xe2\x9d\x8c 流的速度慢且开销高 \xe2\x9d\x8c 对不同基数的支持有限 |
std::strto*系列 c++98 | std::errno (全局标志、手册) | \xe2\x9c\x94\xef\xb8\x8f 小程序集输出 \xe2\x9c\x94\xef\xb8\x8f 快乐/悲伤路径中的小开销 \xe2\x9c\x94\xef\xb8\x8f 支持任何基数运行时参数 \xe2\x9c\x94\xef\xb8\x8f 与 C 兼容 \xe2\x9c\x94\xef\xb8\x8f 也适用于浮点数 \xe2\x9c\x94\xef\xb8\x8f 支持语言环境 \如果基数为零, xe2\x9c\x94\xef\xb8\x8f 可以检测不同的格式 \xe2\x9d\x8c 模糊名称 \xe2\x9d\x8c 界面不符合人体工程学 |
std::ato*家族 c++98 | 零表示失败 (手动错误处理) | \xe2\x9c\x94\xef\xb8\x8f 小汇编输出 \xe2\x9c\x94\xef\xb8\x8f 简单接口 \xe2\x9c\x94\xef\xb8\x8f 快乐/悲伤路径中的小开销 \xe2 \x9c\x94\xef\xb8\x8f 与 C 兼容 \xe2\x9c\x94\xef\xb8\x8f 也适用于浮点数 \xe2\x9d\x8c 模糊名称 \xe2\x9d\x8c int ,不支持基数,格式等 |
std::sscanf c++98 | int 解析的参数数量 (手动错误处理) | \xe2\x9c\x94\xef\xb8\x8f 小汇编输出 \xe2\x9c\x94\xef\xb8\x8f 也适用于浮点数 \xe2\x9c\x94\xef\xb8\x8f 可以检测不同的格式(例如 0x... )\ xe2\x9c\x94\xef\xb8\x8f 与 C 兼容 \xe2\x9d\x8c 接口不符合人体工程学 \xe2\x9d\x8c 无类型安全性,非常容易出现错误 \xe2\x9d\x8c 对不同基数的支持有限 |
std::from_chars
, 或(如果不可用)。\n或std::strto*
中的异常开销是不可接受的。std::sto*
std::istringstream
std::strto*
.std::istringstream
.std::sto*
,或创建一个围绕 的包装器std::from_chars
。大多数特殊情况不太可能出现,因此大多数时候,使用std::stoi
orstd::from_chars
包装器:
// could be generalized with a template\nbool parse_int(std::string_view str, int& out, int base = 10) {\n auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out, base);\n return err == std::errc{};\n}\n\nstd::string s = ...;\nif (int x; parse_int(s, x)) {\n // x has been parsed :)\n}\n
Run Code Online (Sandbox Code Playgroud)\n这种包装器的优点是您始终可以回退到 C++17 之前的其他函数,同时始终具有相同的接口:
\n// alternative pre-C++17 version\nbool parse_int(const std::string& str, int& out, int base = 10) {\n errno = 0;\n char* end = nullptr;\n out = std::strtol(str.data(), str.data() + str.size(), &end, base);\n return str.data() != end && errno == 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n如果你不关心这一点,你也可以返回parse_int
而std::optional<int>
不是分配引用。
归档时间: |
|
查看次数: |
1253094 次 |
最近记录: |