从csv文件中提取特定行

时间:2019-12-28 15:22:59

标签: c++

我有一个csv excel文件,例如学生姓名,身份证,分数,班主任姓名等。

如果我提供了学生的姓名,我想提取学生的数据,因为我需要将其与仅在第一栏中提供的数据进行比较。

所以我已经将数据存储到2d数组中。当我尝试提取第一列时。我不行

这是我的代码。

https://i.stack.imgur.com/3p7YA.png

1 个答案:

答案 0 :(得分:0)

解决方案是将数据放入结构中,然后覆盖此结构的提取器和插入器运算符。这使您可以轻松使用std::algorithm

在C ++中,您的文件结构称为CSV(逗号分隔值)。并且,阅读此内容是一项标准任务。首先,阅读整行,然后使用给定的定界符提取该字符串的标记。 “拆分”也称为“令牌化”,C ++为此目的提供了专用功能: std::sregex_token_iterator。此构造是一个迭代器。用于遍历字符串,因此称为“ sregex”。开始部分定义了我们将在什么输入范围上进行操作,然后在输入字符串中有一个std :: regex表示应该匹配的内容或不应该匹配的内容。匹配策略的类型由最后一个参数给出。

  • 1->给我我在正则表达式中定义的内容,并且
  • -1->给我基于正则表达式不匹配的内容。

我们将结合使用std::copystd::back_inserter来将数据复制到目标向量。

可以使用std:istream_iterator来读取while文件。

这样一来,只需一行即可完成整个文件的读取和处理:

std::vector roster(std::istream_iterator<Student>(ifs), {});

这将变量“名册”定义为std :: vector,并使用std :: vector的所谓范围构造函数。请注意:我使用的是C ++ 17,可以不使用模板参数定义std :: vector。编译器可以从给定的函数参数中推导出自变量。此功能称为CTAD(“类模板参数推导”)。

此外,您可以看到我没有明确使用“ end()”迭代器。

此迭代器将使用正确的类型从空括号括起来的初始化程序列表构造,因为由于std :: vector构造函数要求与第一个参数的类型相同,因此会推断出它。 >

那么显示第一列就是一个简单的循环迭代。

请参见以下简单示例:

#include <iostream>
#include <fstream>
#include <regex>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

std::regex delimiter{ "," };

struct Student {
    // Any kind of student data. Can be converted later
    std::vector<std::string> data{};

    // Overwrite extractor operator
    friend std::istream& operator >> (std::istream& is, Student& s) {
        if (std::string line{}; std::getline(is, line)) {
            s.data.clear();
            std::copy(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}, std::back_inserter(s.data));
        }
        return is;
    }

    // Overwrite inserter
    friend std::ostream& operator << (std::ostream& os, const Student& s) {
        std::copy(s.data.begin(), s.data.end(), std::ostream_iterator<std::string>(os, "\n"));
        return os;
    }

};

int main() {

    // Open file and check if OK
    if (std::ifstream ifs("r:\\unit_db.csv"); ifs) {

        // Read all lines from file, split them and put them in this vector
        std::vector roster(std::istream_iterator<Student>(ifs), {});

        // Show all data on screen
        std::copy(roster.begin(), roster.end(), std::ostream_iterator<Student>(std::cout, "\n"));

        // Show first column
        for (const Student& s : roster)
            std::cout << "\n" << s.data[0];
    }
    return 0;
}

您还可以使用以下替代方法main

直接在文件中搜索
int main() {

    // Open file and check if OK
    if (std::ifstream ifs("r:\\unit_db.csv"); ifs) {

        const std::string name("John");

        if (auto search = std::find_if(std::istream_iterator<Student>(ifs), std::istream_iterator<Student>(),
            [&name](const Student& s) { return s.data[0] == name; }); search != std::istream_iterator<Student>()) {

            std::cout << "Searched for '" << name << "'  and found: " << *search << "\n";
        }
        else
            std::cout << "*** Error: '" << name << "' not found.\n";
    }
    return 0;
}

但是也许最好先阅读所有内容然后搜索。

当然还有许多其他可能的解决方案。