我知道几个相关的问题,例如Parsing a comma-delimited std::string。但是,我已经创建了一个符合我特定需求的代码 - 用逗号剥离任何空格来分割字符串(从文件中读取)。稍后我想将这些子字符串转换为double
并存储在std::vector
中。并非所有操作都显示出来。这是我给出的代码。
include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
int main()
{
std::string str1 = " 0.2345, 7.9 \n", str2;
str1.erase(remove_if(str1.begin(), str1.end(), isspace), str1.end()); //remove whitespaces
std::string::size_type pos_begin = { 0 }, pos_end = { 0 };
while (str1.find_first_of(",", pos_end) != std::string::npos)
{
pos_end = str1.find_first_of(",", pos_begin);
str2 = str1.substr(pos_begin, pos_end- pos_begin);
std::cout << str2 << std::endl;
pos_begin = pos_end+1;
}
}
输出:
0.2345
7.9
所以程序是这样的。虽然循环搜索,
pos_end
的出现将首次出现,
,str2
将成为子字符串,pos_begin
将转到pos_end
旁边的pos_end
1}}。第一次迭代运行正常。
在下一次迭代中,pos_end- pos_begin
的值非常大,我不确定pos_begin
是什么。与if (pos_end == std::string::npos)
pos_end = str1.length();
相同(尽管它将不被使用)。正在进行一些检查,例如
g++ -Wall -Wextra prog.cpp -o prog -std=c++11
一种方法?
该程序可以工作(Public Shared orders As Dictionary(Of Integer, Order)
)。这种方法是否正确?
答案 0 :(得分:1)
您的擦除习惯可能无法在更现代的编译器上编译,因为isspace已经过载。在某些时候,使用range-for删除空格可能更有效。 有问题的Algorythm取决于您是否需要存储令牌和正确&#34;语法&#34;行和存储中的错误或不是空令牌。
#include<iostream>
#include<string>
#include<list>
#include<algorithm>
typedef std::list<std::string> StrList;
void tokenize(const std::string& in, const std::string& delims, StrList& tokens)
{
tokens.clear();
std::string::size_type pos_begin , pos_end = 0;
std::string input = in;
input.erase(std::remove_if(input.begin(),
input.end(),
[](auto x){return std::isspace(x);}),input.end());
while ((pos_begin = input.find_first_not_of(delims,pos_end)) != std::string::npos)
{
pos_end = input.find_first_of(delims,pos_begin);
if (pos_end == std::string::npos) pos_end = input.length();
tokens.push_back( input.substr(pos_begin,pos_end-pos_begin) );
}
}
int main()
{
std::string str = ",\t, 0.2345,, , , 7.9 \n";
StrList vtrToken;
tokenize( str, "," , vtrToken);
int i = 1;
for (auto &s : vtrToken)
std::cout << i++ << ".) " << s << std::endl;
return 0;
}
输出:
1.) 0.2345
2.) 7.9
此变体删除所有空令牌。在您的上下文中是否正确是未知的,因此没有正确的答案。如果您必须检查字符串是否正确,或者您是否使用默认值替换空标记,则必须添加其他检查
答案 1 :(得分:0)
我在 c++20 中使用 ranges
库并实现如下:
#include <iostream>
#include <ranges>
#include <algorithm>
#include <vector>
auto join_character_in_each_subranges = [](auto &&rng) {
return std::string(&*rng.begin(), std::ranges::distance(rng)); };
auto trimming = std::ranges::views::filter([](auto character){
return !std::isspace(character);});
int main()
{
std::string myline = " 0.2345, 7.9 ";
std::vector<double> line_list;
for (std::string&& words : myline
| std::ranges::views::split(',')
| std::ranges::views::transform(join_character_in_each_subranges))
{
auto words_trimming = words | trimming;
std::string clean_number;
std::ranges::for_each(words_trimming,
[&](auto character){ clean_number += character;});
line_list.push_back(atof(clean_number.c_str()));
}
}
首先,迭代 myline
个句子并将视图拆分为分隔符上的子范围
myline | std::ranges::views::split(',')
获取每个子范围并将每个字符相互附加并使用std::string
函数查看transform
std::transform 将给定的函数应用于一个范围并将结果存储在另一个范围中。
std::ranges::views::transform(join_character_in_each_subranges)
此外,从视图范围中删除任何前缀和后缀
auto words_trimming = words | trimming;
并使用
将视图范围转换为std::string
std::ranges::for_each(words_trimming, [&](auto character){ clean_number += character;});
最后,将每个 clean_number
转换为 double
和 push_back
到列表中。
line_list.push_back(atof(clean_words.c_str()));