У меня есть файл .csv, скажем, 1000 строк и 1200 столбцов.
Как извлечь данные из нужного столбца, скажем 67, в другой столбец, скажем 890.
И в то же время из ряда, скажем 9, в другой ряд, скажем 789, затем экспортировать данные как новый CSV-файл с C ++?
Я все еще новичок, но знаком с циклом 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;
}
редактировать
например исходный CSV-файл:
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
Есть несколько способов сделать это. Первое, что приходит на ум, это читать ваши .csv
файл в вектор vector<string>
так что каждое значение строки / столбца сохраняется в двумерном массиве, подобном векторному контейнеру векторов. (например. std::vector<std::vector<string>> array;
). Это позволяет вам легко разбирать ваши .csv
использование файла getline
и 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;
}
}
Вы можете создать вторичный вектор строк для возврата для дальнейшей обработки или просто вывести значения (или записать в другой файл), как это было сделано выше.
Собрав воедино кусочки в коротком примере, который читает ваш CSV-файл, выводя строки между строкой 1, столбцом 1 и строкой 2 и столбцом 2, как показано в вашем вопросе, вы можете сделать что-то вроде следующего:
#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-файла, как вам нравится. Это полностью зависит от вас. Полное чтение дает вам возможность вывести столько разных частей вашего файла, сколько вам нужно, без необходимости выполнять ввод-вывод более одного раза в исходном файле.
Пример использования / Вывод
$ ./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()
, но есть ограничения, к которым применяются итераторы. Старые добрые индексы не волнуют.
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.
Я предполагаю, что главный вопрос в том, чтобы поймать данные / переменную из данного столбца / строки:
1. нужно определить «диапазон» и его
2 взять данные с помощью «value2 ()»
Что касается внешнего вида, он просто не может быть «одновременно»: вы должны решить цель программы. Спасибо!
Мне очень жаль, но я не совсем использовал эту вставку кода, поэтому я поставил изображение: