C++ 将csv文件的一行拆分为std::vector?

C++ 将csv文件的一行拆分为std::vector?,c++,csv,vector,std,C++,Csv,Vector,Std,我有一个函数,可以逐行读取CSV文件。对于每一行,它都会将该行拆分为一个向量。执行此操作的代码是 std::stringstream ss(sText); std::string item; while(std::getline(ss, item, ',')) { m_vecFields.push_back(item); } 除了读取最后一个值为空的行外,该选项工作正常。比如说, text1,tex2, 我希望它返回一个大小为3的向量

我有一个函数,可以逐行读取CSV文件。对于每一行,它都会将该行拆分为一个向量。执行此操作的代码是

    std::stringstream ss(sText);
    std::string item;

    while(std::getline(ss, item, ','))
    {
        m_vecFields.push_back(item);
    }
除了读取最后一个值为空的行外,该选项工作正常。比如说,

text1,tex2,
我希望它返回一个大小为3的向量,其中第三个值是空的。但是,它只返回大小为2的向量。我怎样才能纠正这个问题

bool addEmptyLine = sText.back() == ',';

/* your code here */

if (addEmptyLine) m_vecFields.push_back("");


您可以使用类似的函数:

template <class InIt, class OutIt>
void Split(InIt begin, InIt end, OutIt splits)
{
    InIt current = begin;
    while (begin != end)
    {
        if (*begin == ',')
        {
            *splits++ = std::string(current,begin);
            current = ++begin;
        }
        else
            ++begin;
    }
    *splits++ = std::string(current,begin);
}
模板
无效拆分(初始开始、初始结束、输出拆分)
{
初始电流=开始;
while(开始!=结束)
{
如果(*开始==',')
{
*splits++=std::string(当前,开始);
电流=++开始;
}
其他的
++开始;
}
*splits++=std::string(当前,开始);
}
它将遍历字符串,每当遇到分隔符时,它将提取字符串并将其存储在拆分迭代器中。
有趣的是

  • 当current==begin时,它将插入一个空字符串(测试用例:“text1,tex2”)
  • 最后一次插入保证始终有正确数量的元素。
    如果后面有逗号,则会触发上一个项目符号并添加空字符串,否则会将最后一个元素添加到向量中
您可以这样使用它:

std::stringstream ss(sText);
std::string item;
std::vector<std::string> m_vecFields;
while(std::getline(ss, item))
{
    Split(item.begin(), item.end(), std::back_inserter(m_vecFields));
}

std::for_each(m_vecFields.begin(), m_vecFields.end(), [](std::string& value)
{
    std::cout << value << std::endl;
});
std::stringstream-ss(sText);
std::字符串项;
std::向量m_向量场;
while(std::getline(ss,item))
{
拆分(item.begin()、item.end()、std::back_插入器(m_向量字段));
}
std::for_each(m_vecFields.begin()、m_vecFields.end()、[](std::string&value)
{

std::cout您可以使用
boost::split
为您完成所有这些。

它在一行中具有所需的行为

示例boost::拆分代码
C++11使处理转义逗号变得非常容易,使用:

顺便提一下,如果您只是想从CSV
字符串
构建
向量
,例如
,您可以执行以下操作:

const regex re{"((?:[^\\\\,]|\\\\.)*?)(?:,|$)"};
vector<string> m_vecFields{sregex_token_iterator(item.begin(), item.end(), re, 1), sregex_token_iterator()};

请注意,
“+”
现在已替换了
“*”
,表示需要一个或多个匹配字符。这将阻止它匹配以“
”结尾的
字符串。

解析csv文件的灵活解决方案: 其中:

来源-CSV文件的内容

delimeter-CSV delimeter,例如“,”;

std::vector<std::string> csv_split(std::string source, char delimeter) {
    std::vector<std::string> ret;
    std::string word = "";
    int start = 0;

    bool inQuote = false;
    for(int i=0; i<source.size(); ++i){
        if(inQuote == false && source[i] == '"'){
            inQuote = true;
            continue;
        }
        if(inQuote == true && source[i] == '"'){
            if(source.size() > i && source[i+1] == '"'){
                ++i;
            } else {
                inQuote = false;
                continue;
            }
        }

        if(inQuote == false && source[i] == delimeter){
            ret.push_back(word);
            word = "";
        } else {
            word += source[i];
        }
    }
    ret.push_back(word);

    return ret;
}
std::vector csv\u split(std::string source,char delimeter){
std::载体ret;
std::string word=“”;
int start=0;
bool inQuote=false;
对于(int i=0;i i&&source[i+1]=='”){
++一,;
}否则{
inQuote=false;
继续;
}
}
if(inQuote==false&&source[i]==delimeter){
向后推(字);
单词=”;
}否则{
字+=源[i];
}
}
向后推(字);
返回ret;
}

可能与否重复。如果行以逗号结尾,则该代码会做完全相同的事情。分隔符不是问题吗?
std::getline
提取,直到找到分隔符。但是对于最后一项,没有下一个分隔符
,因此不会提取任何内容,因此while循环结束。@Jonnster:仅仅因为目前被接受的答案有缺陷并不意味着其他问题不能充分解决同一个问题空间-还有其他答案应该有效并且可以投票,你可以用具体的答案对问题进行评论。是的,我只是像第一个例子一样添加了代码,回来后发现有人提出了建议。这不是c最精简的代码,但它可以。为什么?
使用名称空间std
是一件非常正常的事情,不是吗?我不认为删除它会在@Seanny123实现任何效果,但可以在您自己的代码中实现。
"please split"
"this"
"csv"
""
"line"
""
std::stringstream ss(sText);
std::string item;
const regex re{"((?:[^\\\\,]|\\\\.)*?)(?:,|$)"};

std::getline(ss, item)

m_vecFields.insert(m_vecFields.end(), sregex_token_iterator(item.begin(), item.end(), re, 1), sregex_token_iterator());
const regex re{"((?:[^\\\\,]|\\\\.)*?)(?:,|$)"};
vector<string> m_vecFields{sregex_token_iterator(item.begin(), item.end(), re, 1), sregex_token_iterator()};
const regex re{"((?:[^\\\\,]|\\\\.)+?)(?:,|$)"};
std::vector<std::string> csv_split(std::string source, char delimeter) {
    std::vector<std::string> ret;
    std::string word = "";
    int start = 0;

    bool inQuote = false;
    for(int i=0; i<source.size(); ++i){
        if(inQuote == false && source[i] == '"'){
            inQuote = true;
            continue;
        }
        if(inQuote == true && source[i] == '"'){
            if(source.size() > i && source[i+1] == '"'){
                ++i;
            } else {
                inQuote = false;
                continue;
            }
        }

        if(inQuote == false && source[i] == delimeter){
            ret.push_back(word);
            word = "";
        } else {
            word += source[i];
        }
    }
    ret.push_back(word);

    return ret;
}