2016-07-03 6 views
2

Итак, я создал матрицу, как это:Есть ли способ заполнить матрицу (вектор векторов) элегантно, используя STL?

constexpr size_t row = 3, col = 5; 

std::vector<std::vector<int>> matrix(row, std::vector<int>(col)); 

И я пытаюсь заполнить его с вводом пользователя. Это лучшее решение, у меня до сих пор:

for (size_t i = 0; i < matrix.size(); i++) 
{ 

    for (size_t j = 0; j < matrix[i].size(); j++) 
    { 
     std::cout << "Matrix[" << i << "][" << j << "] = "; 

     std::cin >> matrix[i][j]; 
    } 

    std::cout << "\n"; 
} 

Это выглядит хорошо, работает хорошо, но должен быть способ достижения этого с использованием STL, чтобы сделать этот код менее громоздким.

Так что я прошу вас о помощи, заполнив мою матрицу с помощью ввода пользователем. Любая помощь будет оценена!

Спасибо.

+0

Это выглядит элегантно для меня, это то, что вы ожидаете от построения 2D-матрицы. Вы можете запутать его дальше, если хотите, используя трюки, например, генерируя список индексов для каждого размера и обменивая их двумя, чтобы получить пары (X, Y), но я не вижу в этом большой помощи. Единственное улучшение, которое я вижу, это обернуть вектор > в один класс Matrix и работать с ним. –

+0

@ AlexM. Или определить оператор >> для std :: vector и использовать istream_iterator –

ответ

3

Если все вы после приукрасить it..then вы можете сделать что-то вроде:

constexpr size_t row = 3, col = 5; 
    constexpr size_t total = row * col; 
    std::vector<std::vector<int>> matrix(row, std::vector<int>(col)); 

    int j = -1; 
    for (int i = 0; i < total; i++) { 
    std::cin >> matrix[(i % col) ? j : ++j][i % col]; 
    } 

И с C++ 14:

std::for_each(std::begin(matrix), std::end(matrix), [](auto& v) mutable{ 
     for (auto& e : v) std::cin >> e; 
}); 

Вы также можете сделать выше C++ 11 без вывода auto для лямбда.

+0

Wow, поэтому' std :: for_each' может изменить мой вектор? Мне нужно только добавить 'mutable' до фигурных скобок ... Круто, спасибо! –

0

Вы можете попробовать std :: for_each, чтобы уменьшить ваш код. Таким образом вам нужно определить две функции (одну для строк, одну для столбцов) для инициализации вашей матрицы.

+0

Не уверен, что это сработает, 'std :: for_each' - операция без модификации. Я могу передавать только одну строку по значению за раз, что означает, что я вообще не буду изменять мою матрицу. –

+0

Ничего, это сработает. Я слишком новичок в C++, я не знал о 'mutable' ключевое слово ... –

0

пользователя Входной никогда не легко
Существует много, что может пойти не так, и вы всегда должны обращаться осторожно.

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

Например:

#include <algorithm> 
#include <cctype> 
#include <iostream> 
#include <iterator> 
#include <vector> 
#include <sstream> 
#include <string> 

struct matrix: public std::vector<std::vector<int>> { }; 

std::istream& operator >> (std::istream& ins, matrix& m) 
{ 
    std::string s; 
    std::size_t cols = 0; 

    // while input and not a blank line 
    while (std::getline(ins, s) and !s.empty()) 
    { 
    // scan one row from the input line 
    std::istringstream ss{ s }; 
    std::vector<int> row; 
    std::copy(std::istream_iterator<int>(ss), std::istream_iterator<int>(), std::back_inserter(row)); 

    // make sure that the source input stream fails if the intermediary fails 
    if (ss.fail()) 
    { 
     ins.setstate(std::ios::failbit); 
     return ins; 
    } 
    m.emplace_back(row); 

    // keep track of maximum number of columns 
    cols = std::max(cols,row.size()); 
    } 

    // make sure the matrix has the same number of columns in each row 
    for (auto& row : m) row.resize(cols); 
    return ins; 
} 

int main() 
{ 
    matrix m; 

    std::cout << "Enter the matrix, one row per line.\n" 
       "Press Enter twice when done:\n"; 
    std::cin >> m; 

    auto rows = m.size(); 
    auto cols = m.size() ? m[0].size() : 0; 
    std::cout << "Your matrix has " << rows << " rows and " << cols << " columns.\n"; 
} 

Очевидно, что это далеко не достаточно. Но он делает правильную вещь.

Надеюсь, это поможет.

+0

Пожалуйста, соблюдайте стандартные контейнеры. Это не так. – Arunmu

+0

_right_ вещь в соответствии с каким стандартом? Вы просто являетесь бессмысленным педантом - нет ничего плохого в унаследовании от стандартного контейнера, если вы не будете потом пытаться рассматривать его как нечто, что это не так. http: // stackoverflow.com/questions/6806173/subclass-inherit-standard-container/7302165 # 7302165 Если это имеет для вас большое значение, поместите его в пространство имен или примените личное наследование или используйте композицию или просто создайте именованную функцию. О, и не динамически выделять стандартные контейнеры, ОК? Он указывает на проблемы _bad design_. –