如何方便地打印出std::stack或std::queue中的所有元素?

问题描述 投票:0回答:9

如果我不想为此创建一个新容器?

c++ queue stack
9个回答
16
投票

我已经编写了一个代码片段来执行此操作以进行调试。例如:

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


11
投票

您无法迭代堆栈或队列。其实SGI的文档是这么说的(是关于栈的,但是对于队列也是同样的道理):

这个限制是堆栈存在的唯一原因。请注意,任何前插入序列或后插入序列都可以用作堆栈;例如,对于向量,堆栈操作是成员函数 back、push_back 和 pop_back。使用容器适配器堆栈的唯一原因是明确您仅执行堆栈操作,而不执行其他操作。

所以,如果你真的想这样做,你必须清空堆栈(或队列):

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

6
投票
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;*/

2
投票

可以使用递归轻松完成,您只需要知道何时重新添加下一个元素

对于堆栈

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);
}

祝你好运


2
投票

发布 b/c 我发现这对于调试很有用。 从原始文件弹出到临时文件,然后从临时文件弹回到原始文件:

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);
  }
}

1
投票

我找到了应该适用于 std::stack 的所有实现(IMO)的解决方案,但不幸的是堆栈必须使用 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 是动态数组,因此我们可以使用指针 arytmetics。

问题的标记答案假设堆栈有名为“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;
}

1
投票

试试这个:

template<typename T, typename C>
struct myStack : std::stack<T, C> {
    typedef std::stack<T, C> Stack;
    using Stack::stack;
    using Stack::c;                   
};

int main() 
{
    myStack<int, std::deque<int>> s;
    s.push(1);
    s.push(2);

    std::deque<int>::iterator it = s.c.begin();
    while (it != s.c.end())
        std::cout << ' ' << *it++;
}

这里我们将 std::stack 的底层容器公开为成员 c。


0
投票
  1. 如果你需要这样做,那么堆栈或队列不是容器的正确选择。
  2. 如果您仍然坚持这样做,最好的方法是制作副本并从中弹出元素并打印它们。 我不会建议其他方法,因为没有意义。

0
投票

您可以在此处使用答案:https://stackoverflow.com/a/29325258/177259制作一个简单的

get_container
,它公开了保存
std::stack
容器适配器的底层容器的底层受保护成员。

诚然,使用了一些黑客技术,但它应该可以工作。 我已经修改了它,因此它返回一个 const 引用到内部容器。

然后你可以轻松地迭代堆栈的内部容器:

#include <iostream>
#include <stack>
#include <vector>

template <class Adapter>
const typename Adapter::container_type & get_container (Adapter &a)
{
    struct hack : Adapter {
        static typename Adapter::container_type & get (Adapter &a) {
            return a.*&hack::c; // access protected member variable
        }
    };
    return hack::get(a);
}

int main () { 
    std::deque<int> inner{1, 2, 3};
    std::stack<int> s{inner};

    // for (auto x : s) std::cout << x << " "; // not allowed
    for (auto x : get_container(s)) std::cout << x << " ";
    // for (auto& x : get_container(s)) x = 42; // not allowed, thankfully
}
© www.soinside.com 2019 - 2024. All rights reserved.