std::字符串到整数/双倍在一次传递中
std::string to int / double in one pass
我正在解析一个可能包含实值或整数值的字符串。我想解析该字符串并在单个解析中获取整数或实数值。
我可以使用 std::stoi 和 std::stod,但是如果我先调用 stoi 并且它是一个真实的,那么它就会失败,我将不得不调用 stof,导致第二次解析。如果我首先调用 stof 并且字符串包含一个积分,它会将其视为一个有效的实值,从而丢失它是积分的信息。
有没有某种函数可以在一次传递中解析两种类型?还是我首先必须手动查找点并调用正确的函数?
谢谢。:)
您不会找到一个标准调用来实现这一点,原因很简单,没有点的数字字符串既是有效的整数又是有效的双精度。
如果您的标准是"双当且仅当点",请手动查找点。或者,读作双精度并检查小数部分是否为空。
既然你说(在上面的评论中)简单的点符号就是你想要的实数,并且你想要一个单次传递(即没有对已经解析的输入进行后退),并且(再次来自你的评论)更多的是编程经验而不是效率/可维护性/可扩展性,怎么样:
char const * input = /*...*/;
char const * parse_end;
size_t pos;
size_t pos2 = 0;
// parse integer (or pre-digit part of real)
int integer = strtol( input, &parse_end, 10 );
if ( *parse_end == '.' )
{
// you have a real number -- parse the post-digit part
input = parse_end;
double real = strtod( input, &parse_end );
// real + integer is your result
}
else
{
// integer is your result
}
// in either case, parse_end is your position
为什么我使用 C 函数... stoi
返回一个索引,但stod
期望一个string
。所以我必须做一个substr()
或类似的操作,而 C 函数使用指针,使事情变得更容易。
我在评论中所说的是正确的:作为一个大脑实验,这有一定的价值,但任何真正的解析工作都应该利用现有的解决方案,如Boost.Spirit。恕我直言,熟悉这些构建块比学习如何滚动自己的构建块更有价值。
你应该自己解析它,使用std::string::substr
、std::string::find_first_of
、std::string::find_first_not_of
等。
如您所知,std::stoi
和 std::stof
中的每一个都解释与所需类型的正确表示模式匹配的第一个最长子字符串。您可能认为积分解析的结果总是不同的实解析结果(如果两者都可能),但事实并非如此。
示例 1:考虑"123."
。 std::stoi
将解析子字符串"123"
,std::stof
将解析整个"123."
。 "123."
是有效的浮点文本,但它表示一个精确的整数。
示例 2:考虑"123.0"
。这是一个微不足道的实值表示。 std::stoi
将解析子字符串"123"
,std::stof
将解析整个"123.0"
。两个结果在算术上计算相同。
这是您应该决定要解析的内容和不解析的内容的地方。有关可能的模式 cppreference.com 请参阅文章整数文本和浮点文本。
由于遇到这种困难,许多词法分析器只是标记输入(用空格分隔),并检查完整标记是否与任何有效表示匹配。我认为,如果您不知道输入是积分还是近似实数,只需通过 std::stof 解析它。
此外,某些将float
转换为int
的解决方案会导致错误的行为。不能保证具有整型值的float
类型变量的计算等于具有相同整值的int
类型变量。这是因为float
,通常编译为使用float32_t
(IEEE 754-1985单/IEEE 754-2008二进制32)具有24位有效宽度。因此,适合 32 位有符号的整数的有效字符串表示形式可能不适合浮点数。你失去了精度。 double
,通常为IEEE 754-2008二进制64,与int32_t相比不会失去显着宽度,但int64_t等问题相同。
- 我的字符串数组一次打印出前两个字符串
- 为什么完整的字符串没有一次打印,但是当我尝试逐个字符打印时
- 比较字符串的 GetLine 工作一次,然后比较之后不起作用
- need else 参数只出现一次,无论在循环中输入多少字符串
- 为什么调用 cout.operator<<(const char*) 打印地址而不是字符串? 如何创建一个函数本地静态"HashSet<char>"并初始化它一次?
- 一次连接多个C++字符串?
- 在 c++ 中,在 for 循环中,你如何打印出一次字符串
- 搜索字符串是否至少包含一次从 0 到 9 的所有数字的最有效方法
- 至少包含一次字符 X 的 S 的不同子字符串的数量
- C++:如何一次输出两个字母的字符串
- 打印出现一次的字符串数组的第一个元素
- C 在子字符串内找到字符串的最后一次出现
- C++一次打印一个单词的字符串,计算字符数和字符数
- 一次读取一个字符的字符串,直到行或文件末尾
- 如何从字符串中每隔16个字节复制一次数据
- 如何遍历整个字符串并一次播放一个字符C++
- 如何从字符串中一次选择两个字符?到达字符串的第 i 个位置
- C++ 一次读入一个字符的 C 样式字符串
- 如何将字符串一次推送到一个元素的堆栈中
- 如何使"strtok function"一次使用多个令牌字符串? 函数指针会解决这个问题吗?