解析C++中的完整(从头到尾)字符串,包括所有空格

Parse a whole (beginning to end) string in C++, including all whitespace

本文关键字:字符串 包括所 空格 从头到尾 C++ 解析      更新时间:2023-10-16

我正在寻找一种在C++中通用解析整个字符串的方法。我的意思是整个字符串在解析中使用,否则就是错误。这意味着为大多数类型划定空格的朴素operator >>行为不是我想要的(尽管如果解决方案涉及它,我会非常高兴(。一些例子:

// Parse a whole value, throwing an exception if there's a parse error
void parse_into<typename T>(const char* input, T& result);
double value = 0;
parse_into("12.5", value);  // #1: Success
parse_into("ABC", value);  // #2: Fail
parse_into("12.5 abc", value);  //#3: Fail
std::string str_value;
parse_into("ABC", str_value);  // #4: Success
parse_into("ABC ABC", str_value);  // #5: Success; str_value == "ABC ABC"
parse_into("ABC  ABC", str_value);  // #6: Success; str_value == "ABC  ABC'

我相信我想要的是围绕stringstreamoperator >>.我可以看到如何通过检查stringstream是否为空来检测是否未解析整个字符串(案例 #3(。但是,我无法弄清楚的是一种通用方法,允许可以从任何字符串构造的类型,例如std::string.也许是涉及可以从const char*构造类型的 SIFNAE 重载?

我对最终界面没有特别的正式要求;我想要的是让它做任何给定类型的"正确事情"。对于上下文,这适用于命令行参数分析库。该库处理检测单词边界,因此我知道parse_into输入是我尝试阅读的整个单词。

对于double来说,这可以通过std::stod在首次读取您的输入作为std::string后实现。

std::optional<double> parse(std::string const& str) {
std::size_t num = 0;
try {
auto const res = std::stod(str,&num);
if (num < str.size()) return std::nullopt;
return res;
} catch (...) {
return std::nullopt;
}
}

您可以为不同类型的类型创建重载(例如,使用传入的值(。我在这里使用std::optional,但您也可以throw或使用任何其他方式来传达错误。

例如:

bool parse(std::string const& str, double& out);
bool parse(std::string const& str, std::uint32_t& out);
bool parse(std::string const& str, std::string& out); // always succeeds
// ...

编辑:一个更通用的接口,允许传递任何类型的stoXYZ函数:

template <typename T>
static void parse(std::string const& s, T (*fun)(std::string const&,std::size_t*,int), std::optional<T>& out) { /**/ }   
template <typename T>
static void parse(std::string const& s, T (*fun)(std::string const&,std::size_t*), std::optional<T>& out) { /**/ }

这需要一个指向函数的指针,但它也可能需要一个std::function对象。存在这两个重载是因为std::stoistd::stod具有不同的参数列表(整数需要基数(。