Как распечатать все элементы в std:: stack или std:: queue удобно

Если я не хочу создавать новый контейнер для этого?

Ответ 1

Я написал фрагмент, чтобы сделать это для отладки. Например:

std::stack<int> s; // works with std::queue also!
s.push(1);
s.push(2);

std::cout << s; // [ 1, 2 ]

Пожалуйста, простите меня за этот хакерский код! но это то, что я написал несколько месяцев назад:

#include <stack>
#include <queue>
#include <ostream>

template <class Container, class Stream>
Stream& printOneValueContainer
    (Stream& outputstream, const Container& container)
{
    typename Container::const_iterator beg = container.begin();

    outputstream << "[";

    while(beg != container.end())
    {
        outputstream << " " << *beg++;
    }

    outputstream << " ]";

    return outputstream;
}

template < class Type, class Container >
const Container& container
    (const std::stack<Type, Container>& stack)
{
    struct HackedStack : private std::stack<Type, Container>
    {
        static const Container& container
            (const std::stack<Type, Container>& stack)
        {
            return stack.*&HackedStack::c;
        }
    };

    return HackedStack::container(stack);
}

template < class Type, class Container >
const Container& container
    (const std::queue<Type, Container>& queue)
{
    struct HackedQueue : private std::queue<Type, Container>
    {
        static const Container& container
            (const std::queue<Type, Container>& queue)
        {
            return queue.*&HackedQueue::c;
        }
    };

    return HackedQueue::container(queue);
}

template
    < class Type
    , template <class Type, class Container = std::deque<Type> > class Adapter
    , class Stream
    >
Stream& operator<<
    (Stream& outputstream, const Adapter<Type>& adapter)
{
    return printOneValueContainer(outputstream, container(adapter));
}

Вы можете передавать std::stack и std::queue точно так же, как и любой другой поддерживаемый тип!

Ответ 2

Вы не можете проходить через стек или очередь. Фактически, документация SGI говорит об этом (это о стеке, но по той же причине для очереди):

Это ограничение - единственная причина существования стека. Обратите внимание, что любая последовательность вставки вставки или обратная последовательность вставки могут использоваться как стек; в случае вектора, например, операциями стека являются функции-члены назад, push_back и pop_back. Единственная причина использовать стек контейнера-контейнера - это четко указать, что вы выполняете только операции стека и никаких других операций.

Итак, если вы действительно хотите это сделать, вам придется очистить стек (или очередь):

std::stack<Whatever> s;
// ...
while(!s.empty())
{
    Whatever w = s.top();
    std::cout << w;
    s.pop();
}

Ответ 3

  • Если вам нужно это сделать, то стек или очередь не являются правильным выбором контейнера.
  • Если вы все еще настаиваете на этом, лучший способ - сделать копию и поп-элементы и распечатать их. Я не собираюсь предлагать другой путь, потому что нет смысла.

Ответ 4

ostream & operator<<(ostream & os, stack<double> my_stack) //function header
{
    while(!my_stack.empty()) //body
    {
        os << my_stack.top() << " ";
        my_stack.pop();
    }
    return os; // end of function
}


/*
using this simple overloaded operator function, you're able to print out all the components of a stack by doing a simple cout << your_stack_name;*/

Ответ 5

Это можно легко сделать с помощью рекурсии, которую вам просто нужно знать, когда добавить следующий элемент

Для стека

void print(stack<char> &s)
{
    if(s.empty())
    {
        cout << endl;
        return;
    }
    char x= s.top();
    s.pop();
    print(s);
    s.push(x);
    cout << x << " ";
 }

И этот для очереди

void print(queue<char> &s,int num)
{
    if(!num)
    {
        cout << endl;
        return;
    }
    char x= s.front();
    s.pop();
    cout << x << " ";
    s.push(x);
    print(s,--num);
}

Удача

Ответ 6

Posting b/c Я нашел это полезным для отладки. Поп из оригинала в темп, а затем поп из temp обратно в оригинал:

template <typename T>
void dump_stack(std::stack<T>& stack) {
  std::stack<T> temp;
  while (!stack.empty()) {
    T top = stack.top(); stack.pop();
    std::cout << top << " ";
    temp.push(top);
  }
  while (!temp.empty()) {
    T top = temp.top(); temp.pop();
    stack.push(top);
  }
}

Ответ 7

Я нашел решение, которое должно работать со всеми реализациями (IMO) std:: stack, но, к сожалению, стек должен использовать std::vector вместо очереди.

template<typename T>
void printStack(const std::stack<T, std::vector<T>>& s)
{
    typedef typename std::stack<T>::const_reference EntryTypeRef;
    typedef std::remove_reference_t<EntryTypeRef> EntryType;

    for(size_t i=0; i < s.size(); ++i)
    {
        EntryType* e = &s.top();
        cout << *(e-i) << endl;
    }
}

std::vector - это динамический массив, поэтому мы можем использовать арифметику указателей.

Отмеченный ответ на вопрос предполагает, что в стеке есть поле с именем 'c', у меня есть другое решение, которое будет работать с реализацией std:: stack, которая имеет контейнер в качестве первого поля, но его имя не имеет значения:

template<typename T>
void printStack(const std::stack<T>& s)
{
    typedef typename std::stack<T>::container_type Container;

    const auto containerPtr = reinterpret_cast<const Container*>(&s);

    for(auto e : *containerPtr)
        cout << e << endl;
}