Итерирование очереди типа структуры в stl - PullRequest
1 голос
/ 15 июня 2019

У меня есть простой пример очереди типа struct. Вот выродки иди ссылку: https://ide.geeksforgeeks.org/PDvXlup2Z6

#include<bits/stdc++.h>
using namespace std;

struct Task{
    int pid;
    int days;
    int depend;
};

int main()
{
    int w,i,j,t,id,day,dep;
    cin>>t;
    Task task[t];
    for(i=0;i<t;i++)
    {
        cin>>id>>day>>dep;
        task[i].pid=id;
        task[i].days=day;
        task[i].depend=dep;
    }
    //for(i=0;i<t;i++)
    //cout<<task[i].pid<<" "<<task[i].days<<" "<<task[i].depend<<endl;

    queue<Task> job_queue;
    //queue<struct Task>::iterator it;

    for(i=0;i<t;i++)
        job_queue.push(task[i]);

    cout<<"Queue size is: "<<job_queue.size()<<endl;
    /*for(auto it = job_queue.begin();it!=job_queue.end();it++)
    {
        cout<<*it->pid<<endl;
    }*/
    return 0;
}

Я сталкиваюсь с проблемой в очереди итерации, чтобы напечатать все ее элементы, а также как я могу взять конкретный элемент содержимого очереди, например queue[i].id or queue[i].depend? Пожалуйста, помогите мне, так как я не знаю правильный синтаксис. Для вышеприведенного ввода кода:

4
1 2 0
2 4 1
3 7 0
4 12 1

Вывод: Размер очереди: 4

Вот ссылка для гиков и ид: https://ide.geeksforgeeks.org/PDvXlup2Z6

Ответы [ 2 ]

1 голос
/ 15 июня 2019

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

Итак, вы хотели бы хранить элементы в FIFO, «First In First Out» - контейнере. Вы проверили STL и нашли наиболее подходящую очередь std :: queue. Это именно то, что вам нужно:

  • передний
  • назад
  • 1010 * толчок *
  • поп

Итак, вы выбрали std :: queue в качестве контейнера для ваших элементов «Задача». Теперь, глядя на ваш код, можно сделать несколько шагов для улучшения, чтобы создать современную программу на C ++.

Сначала нам нужно устранить синтаксическую (и семантическую) ошибку C ++. В C ++ вы не можете определять динамические простые массивы. Размерность массива должна быть постоянной времени компиляции. Так что настоящий компилятор C ++ не будет есть

Task task[t];

Но, к счастью, в C ++ есть контейнер, который ведет себя подобно обычным массивам, но может динамически расти: std :: vector. Вы должны предпочесть std :: vector (или другие контейнеры) над обычными массивами. Результат таков:

std::vector<Task> task(t);

Это создаст вектор с t пустыми заданиями.

Следующая оптимизация - удаление временных переменных. В вашем цикле ввода вы можете написать:

cin >> task[i].pid >> task[i].days >> task[i].depend;

С этим вы можете исключить 3 временные переменные: id, day, dep И, кроме того, вы также можете удалить w и j. Они не нужны.

Следующий шаг: класс или структура знает, как их значения должны быть прочитаны (или записаны). Таким образом, вы перегрузите оператор >> для вашего класса Task. При этом начало вашего урока будет выглядеть так:

struct Task {
    int pid;
    int days;
    int depend;
    friend istream& operator>>(istream& is, Task& task) { return is >> task.pid >> task.days >> task.depend;  }
};

int main()
{
    int t, i;
    cin >> t;
    std::vector<Task> task(t);
    for (i = 0; i < t; i++)
    {
        cin >> task[i];
    }

    . . . . 

Уже намного лучше. Теперь следующая и главная проблема и ответ на ваш вопрос. В целях отладки вы хотите перебрать свой job_queue. И вы спрашиваете:

Итерация очереди типа структуры в stl

И ответ: не возможно.

std :: queue не имеет итераторов и оператора индекса []. Причина в том, что std :: queue является оберткой вокруг другого контейнера STL. Цель std :: queue состоит в том, чтобы скрыть свои «внутренние» значения и разрешить доступ только вперед и назад. Это нормально для ваших обычных целей, но не для вашего желания получить доступ к «внутренним» членам в случае отладки. Решение простое. Выберите другой контейнер и, в этом случае и для ваших целей, std :: deque. Имеет также ваши необходимые функции, например, спереди, сзади. Функции push и pop имеют расширенные имена, потому что есть pop_front и pop_back, а также psuh_front и push_back. И в том-то и дело, что у него есть итераторы и оператор индексации []. Теперь вы можете сделать свою программу такой:

#include <iostream>
#include <vector>
#include <deque>

using namespace std;

struct Task {
    int pid;
    int days;
    int depend;
    friend istream& operator>>(istream& is, Task& task) { return is >> task.pid >> task.days >> task.depend; }
    friend ostream& operator<<(ostream& os, const Task& task) { return os << task.pid << ' ' << task.days << ' ' << task.depend; }
};

int main()
{
    int t, i;
    cin >> t;
    std::vector<Task> task(t);
    for (i = 0; i < t; i++)
    {
        cin >> task[i];
    }
    deque<Task> job_queue;
    for (i = 0; i < t; i++)
        job_queue.push_back(task[i]);

    cout << "Queue size is: " << job_queue.size() << endl;
    // Option 1
    for (i = 0; i < t; ++i) {
        cout << task[i] << '\n';
    }
    // Option 2, more C++
    for (auto it = job_queue.begin(); it!=job_queue.end(); ++it){
        cout << *it << '\n';
    }
    // Or, even better, taking C++ range based for
    for (const auto& taskref : job_queue) {
        cout << taskref  << '\n';
    }
    return 0;
}

Но это не конец. В C ++ вы можете использовать алгоритмы для всего. Для ввода и вывода вы можете особенно использовать функции std :: istream_iterator и std :: ostream: iterator и std :: copy.

С этим, и, возможно, это окончательная оптимизация, ваша программа выглядит следующим образом:

#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <iterator>

struct Task {
    int pid;
    int days;
    int depend;
    friend std::istream& operator>>(std::istream& is, Task& task) { return is >> task.pid >> task.days >> task.depend; }
    friend std::ostream& operator<<(std::ostream& os, const Task& task) { return os << task.pid << ' ' << task.days << ' ' << task.depend; }
};

int main()
{
    int numberOfTasks{ 0 };
    std::deque<Task> jobQueue{};

    std::cin >> numberOfTasks;

    // Read all task values
    std::copy_n(std::istream_iterator<Task>(std::cin), numberOfTasks, std::back_inserter(jobQueue));

    // For Debug purposes. Print job Queue
    std::copy(jobQueue.begin(), jobQueue.end(), std::ostream_iterator<Task>(std::cout, "\n"));

    return 0;
}

Это решение "more-C ++".

Я надеюсь, что смогу вам немного помочь. , .

1 голос
/ 15 июня 2019

Наконец-то я получил свое решение:

for(i=0;i<t;i++)
        job_queue.push(task[i]);

    auto iter=0;
    int size =job_queue.size();
    Task temp;
    while(iter++ <size)
    {
        temp=job_queue.front();
        cout<<"Entry "<< temp.pid<<" "<<temp.days<<" "<<" "<<temp.depend<<endl;
        job_queue.pop();
        job_queue.push(temp);
    }
...