Форум программистов, компьютерный форум CyberForum.ru

Чтение CSV-файла в двумерный массив - C++

Восстановить пароль Регистрация
 
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
30.07.2015, 01:52     Чтение CSV-файла в двумерный массив #1
Есть файл вида:
"TEXT,1,20140729,150700,73.3500000,73.5800000,73.3500000,73.4800000,2301260"
Нужно собрать числа в двумерный массив. Количество строк в файле неизвестно.
Попробовал использовать регулярные выражения. Но это очень долго. Есть способ побыстрее?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "stdafx.h"
#include <iostream>
#include <regex>
 
using namespace std;
 
int main(int argc, char** argv) {
  const char *filename = "R:\\data.csv";
  FILE* file;
  fopen_s (&file, filename, "rt");
  if (!file) cout << "File not found";  // Как сюда добавить имя файла?
  else {
    char line[100];
    cmatch res;
    while (!feof(file)) {
      fgets(line, 99, file);
      if (regex_search(line, res, regex("^[^,]+,\\d+,(\\d{8}),(\\d{6}),(\\d+\\.?\\d*),(\\d+\\.?\\d*),(\\d+\\.?\\d*),(\\d+\\.?\\d*),(\\d+)$"))) {
        // Преобразовать в числовой тип и добавить числа в двумерный массив
      }
    }
    fclose(file);
  }
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
zss
Модератор
Эксперт С++
 Аватар для zss
6048 / 5651 / 1826
Регистрация: 18.12.2011
Сообщений: 14,437
Завершенные тесты: 1
30.07.2015, 07:12     Чтение CSV-файла в двумерный массив #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//TEXT,1,20140729,150700,73.3500000,73.5800000,73.3500000,73.4800000,2301260
char txt[16]={0};
int k[4];
double a[4];
ifstream fin(filename);
do
{
  if( !fin.get(txt,15,',') )
       break;
  fin>>k[0]>>k[1]>>k[2];
  fin>>a[0]>>a[1]>>a[2]>>a[3];
  fin>>k[3];
  fin.get(); // пропуск \n
...
}while( true);
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
30.07.2015, 13:56  [ТС]     Чтение CSV-файла в двумерный массив #3
Что-то не получается. В результате выполнения скрипта
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "stdafx.h"
#include <iostream>
#include <fstream>
 
using namespace std;
 
int main(int argc, char** argv) {
  char txt[16]={0};
  int k[4];
  double a[4];
  ifstream fin("R:\\data.csv");
  int i = 0;
  do {
    if ( !fin.get(txt, 15, ',') ) break;
    fin>>k[0]>>k[1]>>k[2];
    fin>>a[0]>>a[1]>>a[2]>>a[3];
    fin>>k[3];
    fin.get(); // пропуск \n
    cout<<++i<<": "<<k[0]<<"; "<<k[1]<<"; "<<k[2]<<"; "<<a[0]<<"; "<<a[1]<<"; "<<a[2]<<"; "<<a[3]<<"; "<<k[3]<<endl;
  } while(true);
  system("pause");
}
я получаю только одну строку:
Код
1: -858993460; -858993460; -858993460; -9.25596e+061; -9.25596e+061; -9.25596e+061; -9.25596e+061; -858993460
Добавлено через 3 часа 42 минуты
Надо было разделители (запятые) ещё куда-то запихать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "stdafx.h"
#include <iostream>
#include <fstream>
 
using namespace std;
 
int main(int argc, char** argv) {
  char txt[100], s;
  int k[4];
  double a[4];
  ifstream fin("R:\\data.csv");
  fin >> txt;  // Пропускаем первую строку
  do {
    if ( !fin.get(txt, 15, ',') ) break;
    fin>>s>>k[0]>>s>>k[1]>>s>>k[2];
    fin>>s>>a[0]>>s>>a[1]>>s>>a[2]>>s>>a[3];
    fin>>s>>k[3];
    fin.get(); // пропуск \n
  } while(!fin.eof());
  system("pause");
}
А как в двумерный массив записать (построчно), если не известно количество строк в файле?
Eraston
 Аватар для Eraston
53 / 10 / 2
Регистрация: 09.09.2014
Сообщений: 123
30.07.2015, 14:15     Чтение CSV-файла в двумерный массив #4
Цитата Сообщение от CyberTrader Посмотреть сообщение
Есть файл вида:
Начнем с того, что файл такого вида вообще не подразумевает табличные данные, и восстановить таблицу из него ты не сможешь ( 2 х 4 равно 4 х 2, если предполагать это для 8и элементов в файле, разделенных "," ).
Как минимум файл должен содержать 2 управляющих символа (признак поля и признак конца строки).
Соответственно, пока не встретишь признак конца строки, читаешь данные в одну строку.

Добавлено через 2 минуты
У меня CSV файлы вообще, так выглядят:
CSVgigant,"0,5900"
earth,"0,3000"
dwarf,"0,1050"
asteroid,"0,0050"
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7933 / 4715 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
30.07.2015, 14:23     Чтение CSV-файла в двумерный массив #5
CyberTrader, Т.е. regex вы использовали, а вот vector не?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
 
int main()
{
   const std::string fname = "data.csv";
   std::ifstream ifs(fname.c_str());
   if (!ifs)
   {
      std::cerr << "No file with name: " << fname << std::endl;
      return 1;
   }
   std::vector<std::vector<double> > values;
   std::string line;
   while (ifs.good())
   {
      std::getline(ifs, line);
      std::replace(line.begin(), line.end(), ',',  ' ');
      std::stringstream ss(line);
      std::string current;
      std::vector<double> temp;
      while (ss >> current)
      {
         try
         {
            const double d = std::stod(current);
            temp.push_back(d);
         }
         catch (const std::exception& e)
         {
         }
      }
      values.push_back(temp);
   }
   ifs.close();
   for (const auto& vec : values)
   {
      for (const auto& v : vec)
      {
         std::cout << v << " ";
      }
      std::cout << std::endl;
   }
}
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
30.07.2015, 22:47  [ТС]     Чтение CSV-файла в двумерный массив #6
Цитата Сообщение от ForEveR Посмотреть сообщение
CyberTrader, Т.е. regex вы использовали, а вот vector не?
Ну, как-то так, да.

Вот так-то побыстрее будет:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int main() {
  const char *sFileName = "R:\\data.csv";
  vector<vector<double> > aData;
  vector<double> v;
  ifstream hFile (sFileName);
  if (!hFile) cout << "Не удалось открыть файл";
  else {
    char sLine[100], s;
    double d;
    hFile >> sLine;  // Пропускаем первую строку
    while (!hFile.eof()) {
      if ( !hFile.get(sLine, 15, ',') ) break;
      for ( size_t i=0; i<=7; i++ ) {
        hFile >> s >> d;
        v.push_back(d);
      }
      hFile.get();  // пропуск \n
      aData.push_back(v);
      v.clear();
    }
    hFile.close();
  }
  for ( size_t i=0; i<aData.size(); i++ ) {
    v = aData[i];
    for ( size_t j=0; j<v.size(); j++ ) {
      cout << v[j] << "; ";
    }
    cout << endl;
  }
}
А можно с помощью fgets сделать? Он быстрее файлы читает.
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7933 / 4715 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
31.07.2015, 10:44     Чтение CSV-файла в двумерный массив #7
CyberTrader, Да как хотите можете делать.)
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
03.08.2015, 12:58  [ТС]     Чтение CSV-файла в двумерный массив #8
Если необходимо проверить, чтобы формат считываемых строк соответствовал требуемому, то это только с помощью regex можно сделать?

Добавлено через 1 час 8 минут
Пардон, не обратил внимания, что тут есть проверка:

C++
1
2
3
4
5
6
7
8
try
   {
     const double d = std::stod(current);
     temp.push_back(d);
   }
      catch (const std::exception& e)
   {
   }
Добавлено через 2 часа 35 минут
Не могли бы вы пояснить, что означает вот эта строка?
C++
1
while (ss >> current)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2015, 14:28     Чтение CSV-файла в двумерный массив
Еще ссылки по теме:

C++ Чтение из файла в массив
Чтение одномерного массива в двумерный массив C++
Чтение из файла в массив C++
Запись и чтение массива указателей в двумерный массив C++
C++ Двумерный массив из файла

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7933 / 4715 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
03.08.2015, 14:28     Чтение CSV-файла в двумерный массив #9
CyberTrader, Оператор >> возвращает поток, который приводится к bool (void*) в контексте проверки.
http://en.cppreference.com/w/cpp/io/.../operator_bool
Yandex
Объявления
03.08.2015, 14:28     Чтение CSV-файла в двумерный массив
Ответ Создать тему
Опции темы

Текущее время: 23:17. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru