将csv数据从第x列提取到第y列,从第1行提取到第2行c ++

时间:2018-03-08 20:33:15

标签: c++ split export-to-csv save-as

我有一个.csv文件,比方说,1000行和1200列。

如何从所需的列中提取数据,让67 提取到另一列,让我们说890 。 同时从一行让9 到另一行,让我们说789 ,然后用C ++将数据导出为新的csv文件?

我还是初学者,但熟悉for或while循环,我可以读取文件。

#include <iostream>
#include <fstream>
#include <string>

using namespace std;


int main() {

    ifstream csvFile;

    csvFile.open("../example.csv"); 

    if (csvFile.is_open())
        {

    string line;

    while(getline(csvFile, line))
    {

    //what to do here

    }
        }

    else {

    cout << "Sorry, the file could not be openend." <<endl;

    return -1;

    }

    csvFile.close();

    return 0;

    }

修改 例如source csv file:

a,1,11,111
b,2,22,222
c,3,33,333
d,4,44,444

假设我们只想从第2列到第3列以及从第2行到第3行,那么结果是一个新的csv文件,如下所示:

2,22
3,33

2 个答案:

答案 0 :(得分:0)

我想主要的问题是从给定的列/ raw中捕获数据/变量: 1.需要定义“范围”和它

2使用“value2()”

获取数据

关于外观,它不能“同时”:你必须决定程序目标。谢谢!

很抱歉,但是这个代码插入并不常用,所以我放了一个图片:

enter image description here

答案 1 :(得分:0)

有多种方法可以做到这一点。首先想到的是将.csv文件读入vector<string>的向量,以便每个行/列值存储在2D数组中,如向量的向量容器。 (例如std::vector<std::vector<string>> array;)。这样,您就可以使用.csvgetline轻松解析您的stringstream文件,并在','上分隔。

然后,您可以编写一个提取函数,该函数接受对存储的csv值的引用,并使用基于范围的迭代器对各个向量和字符串迭代向量。此时,只需保留行索引和列索引,并在所需范围内输出所需范围和列之间的行的所有值。一个简单的函数看起来类似于:

 void extract (vector<vector<string>>const & array, size_t r1, size_t c1,
                size_t r2, size_t c2)
{
    size_t ridx = 0;                    /* row index */
    for (auto& row : array) {           /* range based row iterator */
        size_t cidx = 0;                /* column index */
        if (r1 <= ridx && ridx <= r2) { /* if in row range */
            for (auto& col : row) {     /* range based col iterator */
                if (c1 <= cidx && cidx <= c2) { /* if in col range */
                    if (cidx > c1)      /* if greater than 1st */
                        cout << ",";    /* output separator */
                    cout << col;        /* output value */
                }
                cidx++;                 /* increment col index */
            }
            cout << "\n";               /* output newline */
        }
        ridx++;                         /* increment row index */
        if (ridx > r2)                  /* break if row > r2 */
            break;
    }
}

您可以让它创建一个字符串的辅助向量,以便进行进一步处理,或者您可以简单地输出值(或写入另一个文件),如上所述。

在一个简短的示例中将各个部分组合在一起,在您的问题中显示的行1,第1列和第2行以及第2列之间读取csv文件的输出,您可以执行以下操作:

#include <iostream>
#include <fstream>
#include <sstream>

#include <string>
#include <vector>

using std::ifstream;
using std::cout;
using std::cerr;
using std::string;
using std::stringstream;
using std::vector;

void extract (vector<vector<string>>const & array, size_t r1, size_t c1,
                size_t r2, size_t c2)
{
    size_t ridx = 0;                    /* row index */
    for (auto& row : array) {           /* range based row iterator */
        size_t cidx = 0;                /* column index */
        if (r1 <= ridx && ridx <= r2) { /* if in row range */
            for (auto& col : row) {     /* range based col iterator */
                if (c1 <= cidx && cidx <= c2) { /* if in col range */
                    if (cidx > c1)      /* if greater than 1st */
                        cout << ",";    /* output separator */
                    cout << col;        /* output value */
                }
                cidx++;                 /* increment col index */
            }
            cout << "\n";               /* output newline */
        }
        ridx++;                         /* increment row index */
        if (ridx > r2)                  /* break if row > r2 */
            break;
    }
}

int main (int argc, char **argv) {

    string line;
    vector<vector<string>> array;

    if (argc < 2) {
        cerr << "error: insufficient input.\n"
                "usage: " << argv[0] << " filename\n";
        return 1;
    }

    ifstream f (argv[1]);   /* open file */
    if (!f.is_open()) {
        perror (("error while opening file " + string(argv[1])).c_str());
        return 1;
    }

    while (getline (f, line)) {         /* read each line */
        string val;                     /* string to hold value */
        vector<string> row;             /* vector for row of values */
        stringstream s (line);          /* stringstream to parse csv */
        while (getline (s, val, ','))   /* for each value */
            row.push_back (val);        /* add to row */
        array.push_back (row);          /* add row to array */
    }
    f.close();

    cout << "complete array\n\n";           
    for (auto& row : array) {           /* iterate over rows */
        for (auto& val : row)           /* iterate over vals */
            cout << val << "  ";        /* output value      */
        cout << "\n";                   /* tidy up with '\n' */
    }

    cout << "\nextracted array\n\n";
    extract (array, 1, 1, 2, 2);        /* extract from 1,1 to 2,2 */

    return 0;
}

注意:基于范围的循环是C ++ 11的一项功能,因此将-std=c++11添加到编译字符串中)

您不必将整个文件读入存储空间。您可以在初始读取行期间轻松保持行数和列数,并使用stringstream解析列,并仅使用您希望输出的值填充array,或者只输出值那时,但是通过在函数中封装extract例程,您可以根据需要对csv文件的多个不同范围进行操作。这完全取决于你。完整读取只是让您可以根据需要输出文件的多个不同部分,而无需在原始文件上多次执行I / O.

示例使用/输出

$ ./bin/iostream_sstream_csv dat/extract.csv
complete array

a  1  11  111
b  2  22  222
c  3  33  333
d  4  44  444

extracted array

2,22
3,33

可能有更多的C ++方法可以包含所需的行和列索引,而不是保留简单的行索引和列索引,但每次都有效。您可以查看distance()或从向量.begin()中减去当前迭代器,但是适用于迭代器的限制。好老指数不在乎。

仔细看看,如果您有其他问题,请告诉我。