Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Подсчёт числа столбцов


Автор: W4FhLF 6.7.2008, 12:10
Есть такой файл:

Цитата

    0     0    -1.87
  25     0    -1.83
  50  0  -1.8
    75  0  -1.78


Известно, что кол-во чисел в каждой строке постоянно. Отступов(tab, space) может быть сколько угодно. 

Т.к. кол-во столбцов в файле << кол-ва строк, а общее число столбцов и строк заранее неизвестно, файл описывается такой структурой:

Код

typedef vector < vector< double >* > VecTable;


т.е. каждый столбец - отдельный вектор.

Задача: рассчитать кол-во необходимых столбцов, выделить память и заполнить массив. 

С выделением памяти и заполнение всё понятно. Рассчёт кол-ва столбцов реализовал следующим образом:

Код

using namespace std;
typedef vector < vector< double >* > VecTable;

void read_txt(string& path, VecTable& vector_table)
{
    ifstream data_file(path.c_str());
    if (data_file.fail())
        throw ios::failure("Can't open file. Make sure the file existing and accessing.");
    
    // Подсчёт столбцов, выделение памяти.
    string s;
    getline(data_file, s);
    istringstream stream(s);
    
    for (istream_iterator<double> it = stream; it != istream_iterator<double>(); ++it)
        vector_table.push_back(new vector<double>());

    data_file.seekg(ios::beg);
...
// заполнение массива
...
}  


Глядя на код не получаю морального удовлетворения smile, т.к. использование 2х временных объектов и фокусы с потоковым указателем в этом коде смотрятся словно лишний костыль. Напрашивается выделение этого функционала в отдельный метод, так и сделаю, если кто-нибудь из форумчан не предложит более элегантный способ решения этой небольшой задачки. STL и boost приветствуются. 

Автор: jonie 6.7.2008, 12:45
а почему бы не 
Код

typedef vector<vector<double>> VecTable;
и если стобцов количество постоянное, то можно сразу приступать к заполнению, и забить на высчитывание нужного количества. т.е. нечто вроде:
Код

    string s;
    while(getline(inf, s))
    {
        vector_table.push_back(vector<double>());
        double d;
        while(extractDouble(s,d))
        {
            vector_table.back().push_back(d);
        }
    }

Автор: W4FhLF 6.7.2008, 13:30
jonie, ну у тебя для каждой строки выделяется вектор, а у меня наоборот - каждый столбец это отдельный вектор. В случае:

Цитата(W4FhLF @  6.7.2008,  12:10 Найти цитируемый пост)
кол-во столбцов в файле << кол-ва строк


плодить столько объектов не очень-то рационально(например сейчас в файле кол-во столбцов 3, а строк 10 000). Функция extractDouble в любом случае потребует прохождения по всей строке. В общем, кода придётся писать не меньше, а ресурсов он сожрёт больше smile



Автор: JackYF 6.7.2008, 18:12
Решение вполне неплохое, по мне.

Автор: jonie 6.7.2008, 23:41
W4FhLF я невнимателен)
ни как минимум ...
Код

data_file.seekg(ios::beg);
это можно убрать, если сразу вносить данные в только что созданный vector:
Код

    for (istream_iterator<double> it = stream; it != istream_iterator<double>(); ++it) {
        vector_table.push_back(new vector<double>());
        vector_table.back()->push_back(*it);
    }
если я, конечно, не туплю нигде)
ну а далее дочитывать...

конечно, можно вообще всех запутать, сделав все на старом добром..
Код

const char* p = s.c_str();
char* p_end = const_cast<char*>(s.c_str())+s.size();
char* p_end_t = 0;

//parse line
while(p_end>p_end_t){
  p_end_t = p_end;
  double d = strtod(p,&p_end_t);
  p = p_end_t;
  cout<<d<<'\t';
}
писал тут, так что извиняйте за ошибки...

а если строки заканчиваются без пробела, то пойдет и такое:
Код

while(true) {
  double d;
  inf>>d;
  if(inf.fail()) break;
  push_back_here
  if (inf.peek()=='\n')
   next_line_is_new_line
}

это в тему "мне не нравится создание временных обхектов"... выбора дофига.
-------------
вообще есть boost::spirit... это чтоб вообще никто не понял че делает код 8-)

но имхо так не стоит извращаться) стоит сделать так чтобы это было понятно не только тебе..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)