Help in Stacks
Jun 26, 2022 at 10:44am UTC
Hello. I've been studying stacks and I just want to know on how to modify this code below, wherein, This program can accept any data types. Can someone help me on how to fix this code below? Any help will do. Thanks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#include <iostream>
#include <stack>
using namespace std;
void printStackElements (stack<int ><float ><string> stack)
{
while (!stack.empty())
{
cout << stack.top() << endl;
stack.pop();
}
}
int main()
{
stack<int >numbersStack;
numbersStack.push(1);
numbersStack.push('a' );
numbersStack.push(1.34);
numbersStack.push(4);
numbersStack.push(5);
printStackElements(numbersStack);
}
Last edited on Jun 26, 2022 at 10:46am UTC
Jun 26, 2022 at 11:30am UTC
A stack can contain only elements of one type. Using templates you can have a function that accepts a stack of a templated param. eg.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#include <iostream>
#include <stack>
template <typename T>
void printStackElements(std::stack<T> stack) {
while (!stack.empty()) {
std::cout << stack.top() << '\n' ;
stack.pop();
}
}
int main() {
std::stack<int > numbersStack;
numbersStack.push(1);
numbersStack.push(4);
numbersStack.push(5);
printStackElements(numbersStack);
std::stack<double > stkdbl;
stkdbl.push(4.567);
stkdbl.push(1.34);
printStackElements(stkdbl);
}
Since C++17, there are two types std::variant and std::any that can hold values of different types. You can have a std::stack of these types. However these aren't simple types to use.
https://en.cppreference.com/w/cpp/utility/variant
https://en.cppreference.com/w/cpp/utility/any
Jun 26, 2022 at 12:01pm UTC
As an example, consider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#include <iostream>
#include <stack>
#include <variant>
using VarT = std::variant<int , double , char >;
void printStackElements(std::stack<VarT> stack) {
const auto PrintVisitor { [](const auto & t) { std::cout << t << '\n' ; } };
while (!stack.empty()) {
std::visit(PrintVisitor, stack.top());
stack.pop();
}
}
int main() {
std::stack<VarT> stk;
stk.push(1);
stk.push(1.34);
stk.push('a' );
printStackElements(stk);
}
Jun 26, 2022 at 1:28pm UTC
> how to modify this code below, wherein, This program can accept any data types.
Accept any data type that can be sent to an output stream.
C++20:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include <iostream>
#include <concepts>
#include <variant>
#include <stack>
#include <list>
#include <string>
template < typename T >
concept output_streamable = requires( const T& v, std::ostream& stm ) { { stm << v } -> std::same_as<std::ostream&> ; } ;
template < output_streamable T, typename CNTR > // print the contents of a stack of an output_streamable type
void print_elements( std::stack<T,CNTR> stk, std::ostream& stm = std::cout )
{
while ( !stk.empty() )
{
stm << stk.top() << '\n' ;
stk.pop() ;
}
stm << "-----------------------\n" ;
}
template < output_streamable... T > // a variant of output_streamable types is also output_streamable
std::ostream& operator << ( std::ostream& stm, const std::variant<T...>& var )
{
static const auto printer = [&stm]( const output_streamable auto & v ) -> std::ostream& { return stm << v ; } ;
return std::visit( printer, var ) ;
}
int main()
{
std::stack<int > stkint ;
std::stack< double , std::list<double > > stkdbl ;
std::stack < std::variant<std::string,double > > stkvar ; // string or double
for ( int v = 0 ; v < 10 ; ++v )
{
stkint.push(v) ;
stkdbl.push( 1.0 / (v+3) ) ;
if ( v%2 == 1 ) stkvar.push( "###" + std::to_string(v+100) + "+++" ) ; // string
else stkvar.push( 1.0 / (v+3) ) ; // double
}
print_elements(stkint) ;
print_elements(stkdbl) ;
print_elements(stkvar) ; // fine: both std::string and double are output_streamable
struct AAA {} ; std::stack<AAA> stkaaa ;
// print_elements(stkaaa) ; // *** error *** no matching function; constraint not satisfied (AAA is not output_streamable)
std::stack< std::variant<AAA,int ,double > > stkaid ; // AAA or int or double
// print_elements(stkaid) ; // *** error *** no matching function (std::variant<AAA,int,double> is not output_streamable)
}
Jun 26, 2022 at 5:04pm UTC
printStackElements() is very inefficient as it first copies the stack (as the param is passed by value) then it destroys the copied stack as it prints the top element in each loop iteration. Using std::stack, there's not really an efficient way of doing this as you're not provided with a mechanism to access stack elements other than the top one - not even begin() and end()!
However, std::stack is based around another container (dequeue by default) and the various elements of these can be accessed. If a new class is derived from std::stack then you can have function(s) in this derived class that directly access the stack's elements. Consider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#include <iostream>
#include <stack>
#include <variant>
using VarT = std::variant<int , double , char >;
template <typename T>
class MyStack : public std::stack<T> {
public :
using std::stack<T>::stack;
void print() {
const auto PrintVisitor { [](const auto & t) { std::cout << t << '\n' ; } };
for (auto itr { this ->c.crbegin() }; itr != this ->c.crend(); ++itr)
std::visit(PrintVisitor, *itr);
}
};
int main() {
MyStack<VarT> stk;
stk.push(1);
stk.push(1.34);
stk.push('a' );
stk.print();
}
which is much more efficient as display just iterates the stack container.
Last edited on Jun 26, 2022 at 5:04pm UTC
Topic archived. No new replies allowed.