将部分非数字字符串转换为双精度
Convert part non-numeric string to double
我正在尝试将字符串转换为双精度字符串,它也包含非数字字符。我想知道是否有一个通用的解决方案,而不是找到字符串中每个非数字字符的索引并将它们一一删除。 (类似于 atof())
例如,这是我的字符串行(2 个向量坐标):
[12,75082301 28,53644171 119,392771] [108,4213282 30,04183776 77,14237388]”
(由 \t 分隔,双引号包含在字符串中)
我拆分了 tindo 一个字符串数组
array<String^> ^columns;
columns = line->Split('\t');
在我的第一篇专栏中有:"[12,75082301
在我的第三列中有:119,392771]
有没有一种简单的方法可以用相同的方法将 thoose string 转换为 double?
(还有后续问题:如果有 2 个 '\t' directli 彼此相邻,使用 StringSplitOption::RemoveEmptyEntries 我应该可以跳过空条目,但它似乎不适合我.. .有什么想法吗?)
如果您的 "non-numeric" 字符可以出现在字符串中的任何位置(即在您的数字“1,123[456”的中间),那么您将无法避免对字符串进行预处理并删除它们。幸运的是,您可以使用 std::remove_if
的 std::copy_if
算法一次完成此操作。
但是,如果您的 "non-numeric" 字符仅出现在字符串的开头或结尾,您实际上可以将它们视为空格并 "split" 您的字符串正确使用 stringstream
使用自定义语言环境。定义一个将 [
、]
和 \t
视为空格的构面,您就可以开始了。这样做还可以解决您的第二个问题 - 几个相邻的 \t
个字符。
除此之外,您还可以定义另一个将 ,
视为小数点的方面。将它与前一个结合起来,您可以直接从原始字符串中读取 double
s。
这是执行所有这些操作的代码。一、切面:
struct custom_space_facet: std::ctype<char> {
custom_space_facet(const std::string& s): std::ctype<char>(get_table(s)) {}
static const std::ctype_base::mask* get_table(std::string const &s) {
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
for (auto ch : s) rc[ch] = std::ctype_base::space;
return &rc[0];
}
};
struct decimal_coma_facet : std::numpunct<char> {
char do_decimal_point() const { return ','; }
};
接下来,代码本身:
auto l1 = std::locale(std::locale(), new custom_space_facet(" \t[]"));
auto l2 = std::locale(std::locale(), new decimal_coma_facet);
auto locale = l1.combine<std::numpunct<char>>(l2);
std::stringstream input("[12,75082301 28,53644171 119,392771] [108,4213282 30,04183776 77,14237388]");
input.imbue(locale);
std::cout << std::setprecision(10);
double value;
while (input >> value)
std::cout << value << "\n";
运行 这将为您提供所需的双打:
12.75082301
28.53644171
119.392771
108.4213282
30.04183776
77.14237388
我正在尝试将字符串转换为双精度字符串,它也包含非数字字符。我想知道是否有一个通用的解决方案,而不是找到字符串中每个非数字字符的索引并将它们一一删除。 (类似于 atof())
例如,这是我的字符串行(2 个向量坐标):
[12,75082301 28,53644171 119,392771] [108,4213282 30,04183776 77,14237388]” (由 \t 分隔,双引号包含在字符串中)
我拆分了 tindo 一个字符串数组
array<String^> ^columns;
columns = line->Split('\t');
在我的第一篇专栏中有:"[12,75082301
在我的第三列中有:119,392771]
有没有一种简单的方法可以用相同的方法将 thoose string 转换为 double?
(还有后续问题:如果有 2 个 '\t' directli 彼此相邻,使用 StringSplitOption::RemoveEmptyEntries 我应该可以跳过空条目,但它似乎不适合我.. .有什么想法吗?)
如果您的 "non-numeric" 字符可以出现在字符串中的任何位置(即在您的数字“1,123[456”的中间),那么您将无法避免对字符串进行预处理并删除它们。幸运的是,您可以使用 std::remove_if
的 std::copy_if
算法一次完成此操作。
但是,如果您的 "non-numeric" 字符仅出现在字符串的开头或结尾,您实际上可以将它们视为空格并 "split" 您的字符串正确使用 stringstream
使用自定义语言环境。定义一个将 [
、]
和 \t
视为空格的构面,您就可以开始了。这样做还可以解决您的第二个问题 - 几个相邻的 \t
个字符。
除此之外,您还可以定义另一个将 ,
视为小数点的方面。将它与前一个结合起来,您可以直接从原始字符串中读取 double
s。
这是执行所有这些操作的代码。一、切面:
struct custom_space_facet: std::ctype<char> {
custom_space_facet(const std::string& s): std::ctype<char>(get_table(s)) {}
static const std::ctype_base::mask* get_table(std::string const &s) {
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
for (auto ch : s) rc[ch] = std::ctype_base::space;
return &rc[0];
}
};
struct decimal_coma_facet : std::numpunct<char> {
char do_decimal_point() const { return ','; }
};
接下来,代码本身:
auto l1 = std::locale(std::locale(), new custom_space_facet(" \t[]"));
auto l2 = std::locale(std::locale(), new decimal_coma_facet);
auto locale = l1.combine<std::numpunct<char>>(l2);
std::stringstream input("[12,75082301 28,53644171 119,392771] [108,4213282 30,04183776 77,14237388]");
input.imbue(locale);
std::cout << std::setprecision(10);
double value;
while (input >> value)
std::cout << value << "\n";
运行 这将为您提供所需的双打:
12.75082301
28.53644171
119.392771
108.4213282
30.04183776
77.14237388