Функция для создания 1D-векторов из 2D-векторов (Ошибка: выражение должно иметь тип указатель на объект) - PullRequest
0 голосов
/ 12 марта 2020

Привет, я новичок в C ++ и программировании. Я пытаюсь создать функцию для преобразования 2D-вектора в одномерный вектор Row. К сожалению, я получаю сообщение об ошибке: «выражение должно иметь указатель на объектный тип». Если я вписываю точно такой же код в основную функцию без указания функции, она работает нормально, похоже, просто не работает, если я хочу создать функцию. Вот код:

std::vector<float> onelinevector(std::vector<std::vector<float>> invector, int column){

int vsize = (int) invector.size() * column;
std::vector<float> v1d(vsize);
std::cout << "Creating 1D Vector:\n"<< "Inputvector Size: " << invector.size() << "Rows " << column << " Columns" << std::endl;
int k = 0;

for (int i = 0; i<invector.size(); i++) {

    for (int j = 0; j<column ; j++) {
      v1d[k] = invector[i][j];
      k++;
    }

}
return v1d;
}

Эта строка вызывает ошибку: v1d[k] = invector[i][j];

Надеюсь, вы можете помочь мне с этим.

Ответы [ 2 ]

0 голосов
/ 12 марта 2020

Если вы хотите сначала преобразовать 2d-вектор в 1d-вектор, вам нужно передать в функцию 2d-вектор. В вашей программе вы пытались добавлять построчно, чтобы было проще. У вас есть несколько способов сделать это, как вы можете видеть ниже:

Важно отметить «&» в параметре. Это означает, что вектор передается по ссылке. Без этого вы скопируете весь вектор без необходимости. Также я установил его как const для правильности.

using namespace std;

vector<float> onelinevectorCStyle(const vector<vector<float>>& invector) {
    vector<float> OneD;

    for (vector<float>::size_type X = 0; X < invector.size(); ++X)
        for (vector<float>::size_type Y = 0; Y < invector[X].size(); ++Y)
                OneD.emplace_back(invector[X][Y]);

    return OneD;
}

vector<float> onelinevectorCPPIterator(const vector<vector<float>>& invector) {
    vector<float> OneD;

    for (auto X = invector.cbegin(); X != invector.cend(); ++X)
        for (auto Y = (*X).cbegin(); Y != (*X).cend(); ++Y)
            OneD.emplace_back(*Y);

    return OneD;
}

vector<float> onelinevectorElegantWay(const vector<vector<float>>& invector) {
    vector<float> OneD;

    for (auto& X : invector)
        for (auto& Y : X)
            OneD.emplace_back(Y);

    return OneD;
}
0 голосов
/ 12 марта 2020

Если я введу точно такой же код в основной функции без указания функции, она будет работать нормально

Нет. У вас была бы точно такая же проблема.

[...] Инвертор должен быть 2D-вектором [...]

Это не так. std::vector<float> invector - это вектор float s, не являющийся 2D-вектором любого вида.

Вы получаете ошибку, потому что invector[i] - это float, а float s не имеет operator[].

Другие незначительные проблемы в вашем коде:

Не передавайте большие векторы по значению. Вместо этого передайте по ссылке, чтобы избежать ненужной копии.

int vsize = (int) invector.size() * column;

Не используйте приведения в стиле c ((int)). Если вы хотите разыграть, используйте static_cast. Хотя вам вовсе не нужно сниматься здесь. Тип, используемый для размеров контейнера: size_t. Это без знака. int подписано, но размер контейнера не может быть отрицательным. На самом деле, не проходите column. Как только вы сделаете invector 2D, он будет знать свои размеры (см. Ниже), нет необходимости передавать его вместе с вектором.

Кроме того, отслеживание индекса k подвержено ошибкам и не является действительно необходимым. Циклы проще, когда они написаны как диапазоны, основанные на циклах.

Если все внутренние векторы имеют одинаковый размер и минимальные изменения применяются к вашему коду, это может выглядеть так:

using my1Dvector = std::vector<float>;
using my2Dvector = std::vector<my1Dvector>;
my1Dvector onelinevector(const my2Dvector& invector){
    my1Dvector v1d;
    if (invector.size() == 0) return v1d;
    v1d.reserve(invector.size() * invector.front().size());

    for (auto& innervector : invector) {
        for (auto& element : innervector) {
            v1d.push_back(element);
        }
    }
    return v1d;
}

Почти последнее, но не менее важное: вместо нажатия элемента вручную вы можете использовать insert (см. здесь ):

my1Dvector onelinevector(const my2Dvector& invector){
    my1Dvector v1d;
    if (invector.size() == 0) return v1d;
    v1d.reserve(invector.size() * invector.front().size());

    for (auto& innervector : invector) {
        v1d.insert(v1d.end(),innervector.begin(),innervector.end());
    }
    return v1d;
}

Последнее, но не менее важное, такое преобразование пахнет как ненужное Работа. Если вы хотите, чтобы данные хранились в плоском векторе, лучше сначала сохранить их в плоском векторе. С другой стороны, вы можете сохранить его в двумерном векторе и эмулировать 1D-доступ путем преобразования только индекса.

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