Я видел твой ответ, и хотя он не плохой, я не думаю, что он тоже идеален. По крайней мере, как я понимаю ваш первоначальный вопрос, первый комментарий в основном указывает, сколько столбцов у вас будет в каждой из оставшихся строк. например тот, который вы дали («1 4 6 28»), содержит четыре числа, которые можно интерпретировать как выражение, что каждая последующая строка будет содержать 4 числа.
Предполагая, что это правильно, я бы использовал эти данные для оптимизации чтения данных. В частности, после этого (опять же, насколько я понимаю) файл просто содержит строку за строкой чисел. В таком случае я бы собрал все числа в один вектор и использовал бы количество столбцов из заголовка для индексации по остальным:
class matrix {
std::vector<double> data;
int columns;
public:
// a matrix is 2D, with fixed number of columns, and arbitrary number of rows.
matrix(int cols) : columns(cols) {}
// just read raw data from stream into vector:
std::istream &read(std::istream &stream) {
std::copy(std::istream_iterator<double>(stream),
std::istream_iterator<double>(),
std::back_inserter(data));
return stream;
}
// Do 2D addressing by converting rows/columns to a linear address
// If you want to check subscripts, use vector.at(x) instead of vector[x].
double operator()(size_t row, size_t col) {
return data[row*columns+col];
}
};
Это все довольно просто - матрица знает, сколько у нее столбцов, поэтому вы можете выполнять индексирование x, y в матрице, даже если она хранит все свои данные в одном векторе. Чтение данных из потока просто означает копирование этих данных из потока в вектор. Чтобы иметь дело с заголовком и упростить создание матрицы из данных в потоке, мы можем использовать простую функцию, подобную этой:
matrix read_data(std::string name) {
// read one line from the stream.
std::ifstream in(name.c_str());
std::string line;
std::getline(in, line);
// break that up into space-separated groups:
std::istringstream temp(line);
std::vector<std::string> counter;
std::copy(std::istream_iterator<std::string>(temp),
std::istream_iterator<std::string>(),
std::back_inserter(counter));
// the number of columns is the number of groups, -1 for the leading '#'.
matrix m(counter.size()-1);
// Read the remaining data into the matrix.
m.read(in);
return m;
}
Как написано прямо сейчас, это зависит от того, как ваш компилятор реализует «оптимизацию именованных возвращаемых значений» (NRVO). Без этого компилятор скопирует весь matrix
(возможно, пару раз), когда он будет возвращен из функции. При оптимизации компилятор предварительно выделяет место для матрицы и read_data()
создает матрицу на месте.