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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
#1

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

30.07.2015, 01:52. Просмотров 1131. Ответов 8
Метки нет (Все метки)

Есть файл вида:
"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);
  }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.07.2015, 01:52
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Чтение CSV-файла в двумерный массив (C++):

Чтение из csv файла в двумерный массив географических координат с нестандартными символами - C++
Добрый вечер! После Hello Word это моя первая прога на с++, поэтому очень прошу помочь. Задача состоит в следующем Есть csv файл,...

Чтение в двумерный массив из файла - C++
Есть некоторая последовательность целых чисел, которая хранится в файле. Её нужно считать и записать в двумерный массив.

Чтение одномерного массива в двумерный массив - C++
Всем здравия. Рассказывать суть программы не буду (смысла в этом не вижу), сама беда не в коде, а в Visual Studio (наверное). Проверял...

Запись и чтение массива указателей в двумерный массив - C++
Подскажите пожалуйста, вот у меня генерируется двумерный массив в массиве указателей (int**), как мне записать массив указателей в другой...

Переписать массив строк из файла в двумерный массив - C++
Переписать массив строк из файла в двумерный массив типа CHAR &quot; char Map&quot; вот что получается, как сделать чтоб копировал строку в...

Двумерный массив из файла - C++
Доброго времени суток! Подскажите как считать из файла в двумерный массив векторов vector&lt;vector&lt;string&gt;&gt; В инете и на форуме есть...

8
zss
Модератор
Эксперт С++
6401 / 5967 / 1944
Регистрация: 18.12.2011
Сообщений: 15,369
Завершенные тесты: 1
30.07.2015, 07:12 #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);
1
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
30.07.2015, 13:56  [ТС] #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");
}
А как в двумерный массив записать (построчно), если не известно количество строк в файле?
0
Eraston
53 / 10 / 2
Регистрация: 09.09.2014
Сообщений: 127
30.07.2015, 14:15 #4
Цитата Сообщение от CyberTrader Посмотреть сообщение
Есть файл вида:
Начнем с того, что файл такого вида вообще не подразумевает табличные данные, и восстановить таблицу из него ты не сможешь ( 2 х 4 равно 4 х 2, если предполагать это для 8и элементов в файле, разделенных "," ).
Как минимум файл должен содержать 2 управляющих символа (признак поля и признак конца строки).
Соответственно, пока не встретишь признак конца строки, читаешь данные в одну строку.

Добавлено через 2 минуты
У меня CSV файлы вообще, так выглядят:
CSVgigant,"0,5900"
earth,"0,3000"
dwarf,"0,1050"
asteroid,"0,0050"
0
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
30.07.2015, 14:23 #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;
   }
}
1
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
30.07.2015, 22:47  [ТС] #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 сделать? Он быстрее файлы читает.
0
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
31.07.2015, 10:44 #7
CyberTrader, Да как хотите можете делать.)
0
CyberTrader
0 / 0 / 0
Регистрация: 30.07.2015
Сообщений: 11
03.08.2015, 12:58  [ТС] #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)
0
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
03.08.2015, 14:28 #9
CyberTrader, Оператор >> возвращает поток, который приводится к bool (void*) в контексте проверки.
http://en.cppreference.com/w/cpp/io/.../operator_bool
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2015, 14:28
Привет! Вот еще темы с ответами:

двумерный массив из файла. С++ - C++
Добрый день! Тема не раз обсуждалась, но я не смог найти ответ на свой вопрос, к сожалению Суть проблемы следущая - есть файл,...

Чтение из файла в массив - C++
//--------------------------------------------------------------------------- #include &lt;clx.h&gt; #include &lt;stdio.h&gt; #pragma...

Чтение из файла в массив - C++
Здравствуйте, уважаемые программисты. Подскажите, пожалуйста. Есть текстовый файл примерно такого содержания: 15, 50, 30 155 ...

Чтение из файла в массив - C++
Всем привет! Извините, если такая тема уже поднималась, но я ничего не нашла.... У меня такая задачка. Есть два файлика, в одном матрица...


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

Или воспользуйтесь поиском по форуму:
9
Yandex
Объявления
03.08.2015, 14:28
Ответ Создать тему
Опции темы

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