2010-09-15 2 views
1

У меня возникли проблемы «погубил» этот метод, который сваливает по существу матрицы чисел переменного размера в текстовом файл:C++ читать числа из файла и хранить в векторах

void vectorToFile(char *name, vector<vector<double>>* a){ 
    FILE* fp = fopen(name, "w"); 
    for(int i=0;i<a->size();i++){ 
     for(int j=0;j<a->at(i).size();j++){ 
      fprintf(fp, "%f ", a->at(i).at(j)); 
     } 
     fprintf(fp, "\n"); 
    } 
    fclose(fp); 
} 

У меня возникают проблемы, реализующие реверс:

vector<vector<double>> fileToVector(char *name){ ??? } 

Я гарантировано, что числа в файле образует «прямоугольник», то есть размеры внутренних векторов все равны, но я не знаю, как выяснить количество записей в строку , а также количество столбцов.

Может ли кто-нибудь указать мне правильное направление? Каждый пример, который я нашел до сих пор, реализует что-то намного проще, с жестко заданными размерами или размерами, указанными в первой строке (чего я не могу себе позволить, к сожалению)

+0

Как предполагается, что данные, которые будут организованы в файле? Можете ли вы привести нам пример? Между тем есть пример, который может помочь: http://stackoverflow.com/questions/2677029/read-numbers-from-files-in-columns-one-column-whole-numbers-other-column-number/2677098# 2677098 – karlphillip

+1

Я думал, что метод иллюстрирует. В основном, как матрица чисел: m чисел, разделенных пробелом в n строках – karpathy

ответ

10

Я новичок в C++, поэтому я не уверен, что это хороший подход или нет, но я бы открыл файл, прочитанный во входной строке за строкой, разбор каждой строки при чтении. Вот несколько примеров коды (непроверенная, Неоткомпилированный):

#include <iostream> 
#include <sstream> 
#include <fstream> 
#include <string> 
#include <vector> 

std::vector<std::vector<double> > fileToVector(const char *name) 
{ 
    std::vector<std::vector<double> > result; 
    std::ifstream input (name); 
    std::string lineData; 

    while(getline(input, lineData)) 
    { 
     double d; 
     std::vector<double> row; 
     std::stringstream lineStream(lineData); 

     while (lineStream >> d) 
      row.push_back(d); 

     result.push_back(row); 
    } 

    return result; 
} 
+0

работал отлично, спасибо, сэр! – karpathy

+0

Отличный ответ для новичка, '+ 1' от меня.Единственное, что я хотел бы добавить, это проверить, действительно ли потоки когда-либо достигли EOF, прежде чем вы их закрыли: 'if (! LineStream.eof()) throw inputError (« Dammit! »);' Или еще лучше, чтобы не быть отбрасывается конечными пробелами 'if (! (lineStream >> std :: ws) .eof()) throw inputError (« Dammit! »);'. – sbi

0

Вы можете читать строки, разделять с помощью разделителя, которые у вас есть, а затем анализировать на цифры , Вы можете использовать getline, чтобы читать строки как строки, и вам не нужно знать точное число.

1

Было бы проще, если бы вы использовали C++ I/O вместо C I/O. Я бы предложил использовать ifstream для чтения в файле и использовать getline() для чтения каждой строки. Каждая строка - это числа, которые должны идти в vector. Вероятно, самым простым способом разобрать string было бы использование stringstream. Затем вы можете разобрать каждый double и push_back() на vector, поэтому вам не придется заботиться о размере vectors. Я бы также предложил использовать std::string вместо char*, где бы вы ни находились (хотя для имен файлов обычно вам нужно использовать c_str(), так как файлы ввода/вывода всегда, кажется, принимают const char* вместо std::string).

-2

Есть ли какая-либо конкретная причина использовать вектор> вместо использования только двойной ** и используя новый двойной [], чтобы выделить массив и каждый суб-элемента? Я предполагаю, что массив может динамически изменяться во время выполнения, но если массив выделяется только один раз, использование double ** будет намного более эффективным, чем итерация по вектору.

В любом случае, решение вашей проблемы сваливать границы массива до фронта в файл и читать его обратно ...

+1

Это не очень хороший совет. Вектор предоставляет много дополнительных преимуществ (заботится об управлении памятью, предоставляет итераторы для использования со многими алгоритмами в '', обеспечивает проверку границ, если вы используете 'at()' и т. Д.). На данный момент производительность не должна рассматриваться. – dreamlax

+0

, просто чтобы ответить на вопрос, который вы указали, то есть ли какая-либо конкретная причина использовать вектор вместо массива c-style - основная причина заключается в том, что OP задает в контексте C++, а не C. – erjot

+1

Итерация над 'vector' вероятно, будет почти таким же эффективным, если не так эффективен, как итерация чрезмерно динамических массивов. Вероятность того, что итераторы для вектора являются указателями в любом случае (по крайней мере, в режиме деблокирования), хотя это зависит от реализации. Кроме того, использование 'push_back()' будет более эффективным, чем постоянное изменение размера массива, поскольку вы добавляете к нему больше элементов. Независимо от того, что затраты на ввод/вывод файлов могут заглушить любые различия в производительности между итерацией по динамическому массиву и «вектором». Кроме того, использование векторов приведет к увеличению количества поддерживаемых кодов, чем использование массивов. –

2

Вы можете попробовать еще C++ иш подход:

void vectorToFile(std::vector<double> const& vec, std::string const& filename) { 
    std::ofstream file(filename); 
    if(file.good()) { 
     file.flags(std::ios::fixed); 
     std::copy(vec.begin(), vec.end(), std::ostream_iterator<double>(file)); 
    } else { 
     // throw error or sth 
    } 
    file.close(); 
} 

Если вы хотите сохранить как двоичный файл, вы можете использовать ostream_binary_iterator как этот - http://bit.ly/9JAxdp:

void vectorToFile(std::vector<double> const& vec, std::string const& filename) { 
    std::ofstream file(filename, std::ios::binary); 
    if(file.good()) { 
     file.flags(std::ios::fixed); 
     std::copy(vec.begin(), vec.end(), ostream_binary_iterator<double>(file)); 
    } else { 
     // throw error or sth 
    } 
    file.close(); 
} 
Смежные вопросы