逗号

时间:2018-02-15 23:53:27

标签: c++ c++11

我知道几个相关的问题,例如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) )。这种方法是否正确?

2 个答案:

答案 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 转换为 doublepush_back 到列表中。

line_list.push_back(atof(clean_words.c_str()));