使用std :: ostream作为打印函数的参数

时间:2015-01-04 20:32:48

标签: c++ iostream ostream

我一直使用cout来打印语句,但现在我想通过passing the stream学习打印,类似void print(std::ostream&) const;我当前的打印功能看起来像

template <class T>

void Mystack<T>::print()
{
    for (int i = 0; i <= top; i++)
    {
        std::cout << input[i] << " ";
    }
}

我有两个问题:

  1. 使用ostream从上面实现的普通打印功能切换到打印功能有什么好处。
  2. 如何在我的函数中实现ostream。我尝试从互联网来源了解ostream但无法理解。请帮忙。
  3. 以下是完整的运行代码:

    //*************STACK CODE***************//
    
    //VERY GOOD EXAMPLE TO UNDERSTAND RULE OF THREE FOR BEGINEERS http://www.drdobbs.com/c-made-easier-the-rule-of-three/184401400
    //RULE OF THREE : Video : https://www.youtube.com/watch?v=F-7Rpt2D-zo
    //Thumb Rule : Whenever we have class which has members pointing to heap space we should implement Rule of three.
    //Concepts : Shallow Copy and Deep Copy
    
    #include <iostream>
    template <class T>
    class Mystack
    {
    private:
        T *input;
        int top;
        int capacity;
    public:
        Mystack();
        ~Mystack();
        void push(T const& x);
        void pop();
        T& topElement() const;
        bool isEmpty() const;
        void print();
    };
    template <class T>
    Mystack<T>::Mystack()
    {
        top = -1;
        capacity = 5;
        input = new T[capacity];
    }
    template <class T>
    Mystack<T>::~Mystack() //Since we are using destructor explictly we need to apply Rule of 3
    {
        delete [] input;
    }
    template <class T>
    void Mystack<T>::push(T const& x)  //Passing x by Const Reference // Valus of x cannot be changed now in the function!
    {
        if (top + 1 == capacity)
        {
            T *vec = new T[capacity * 2];
            for (int i = 0; i <= top; i++)
            {
                vec[i] = input[i];
            }
            delete []input; // Avoiding Memory Leak.
            input = vec;
            capacity *= capacity;
        }
        top++;
        std::cout << x;
        std::cout << &x;
        input[top] = x;
    }
    template <class T>
    void Mystack<T>::pop()
    {
        if (isEmpty())
        {
            throw std::out_of_range("Stack Underflow");
        }
        else
        {
            std::cout << "The popped element is" << input[top--];
    
        }
    }
    template <class T>
    bool Mystack<T>::isEmpty() const
    {
        if (top == -1)
        {
            std::cout << "Is Empty" << std::endl;
            return true;
        }
        else
        {
            std::cout << "Not Empty" << std::endl;
            return false;
        }
    }
    template <class T>
    T& Mystack<T>::topElement() const
    {
        if (top == -1)
        {
            throw std::out_of_range("No Element to Display");
        }
        else
        {
            std::cout << "The top element is : " << input[top];
            return input[top];
        }
    }
    template <class T>
    void Mystack<T>::print()
    {
        for (int i = 0; i <= top; i++)
        {
            std::cout << input[i] << " ";
        }
    }
    int main()
    {
        Mystack<int> s1;
        Mystack<float> s2;
        Mystack<char> s3;
        int choice;
        int int_elem;
        float float_elem;
        char char_elem;
        std::cout << "Enter the type of stack" << std::endl;
        std::cout << "1. int ";
        std::cout << "2. float ";
        std::cout << "3. Char"<< std::endl;
        std::cin >> choice;
        if (choice == 1)
        {
            int  ch = 1;
            while (ch > 0)
            {
                std::cout << "\n1. Push ";
                std::cout << "2. Top ";
                std::cout << "3. IsEmpty ";
                std::cout << "4. Pop ";
                std::cout << "5. Exit ";
                std::cout << "6. Print"<<std::endl;
                std::cout << "Enter the choice" << std::endl;
                std::cin >> ch;
                switch (ch)
                {
                case 1:
                    std::cout << "Enter the number to be pushed" << std::endl;
                    std::cin >> int_elem;
                    s1.push(int_elem);
                    break;
                case 2:
                    std::cout << "Get the TOP Element" << std::endl;
                    try
                    {
                        s1.topElement();
                    }
                    catch (std::out_of_range &oor)
                    {
                        std::cerr << "Out of Range error:" << oor.what() << std::endl;
                    }
                    break;
                case 3:
                    std::cout << "Check Empty" << std::endl;
                    s1.isEmpty();
                    break;
                case 4:
                    std::cout << "POP the element" << std::endl;
                    try
                    {
                        s1.pop();
                    }
                    catch (const std::out_of_range &oor)
                    {
                        std::cerr << "Out of Range error: " << oor.what() << '\n';
                    }
                    break;
                case 5:
                    exit(0);
                case 6:
                    s1.print();
                    break;
                default:
                    std::cout << "Enter a valid input";
                    break;
                }
            }
        }
        else if (choice == 2)
        {
            int  ch = 1;
            while (ch > 0)
            {
                std::cout << "\n1. PUSH" << std::endl;
                std::cout << "2. TOP" << std::endl;
                std::cout << "3. IsEmpty" << std::endl;
                std::cout << "4. POP" << std::endl;
                std::cout << "5. EXIT" << std::endl;
                std::cout << "6. Print" << std::endl;
                std::cout << "Enter the choice" << std::endl;
                std::cin >> ch;
                switch (ch)
                {
                case 1:
                    std::cout << "Enter the number to be pushed" << std::endl;
                    std::cin >> float_elem;
                    s2.push(float_elem);
                    break;
                case 2:
                    std::cout << "Get the TOP Element" << std::endl;
                    try
                    {
                        s2.topElement();
                    }
                    catch (std::out_of_range &oor)
                    {
                        std::cerr << "Out of Range error:" << oor.what() << std::endl;
                    }
                    break;
                case 3:
                    std::cout << "Check Empty" << std::endl;
                    s2.isEmpty();
                    break;
                case 4:
                    std::cout << "POP the element" << std::endl;
                    try
                    {
                        s2.pop();
                    }
                    catch (const std::out_of_range &oor)
                    {
                        std::cerr << "Out of Range error: " << oor.what() << '\n';
                    }
                    break;
                case 5:
                    exit(0);
                case 6:
                    s2.print();
                    break;
                default:
                    std::cout << "Enter a valid input";
                    break;
                }
            }
        }
        else if (choice == 3)
        {
            int  ch = 1;
            while (ch > 0)
            {
                std::cout << "\n1. PUSH" << std::endl;
                std::cout << "2. TOP" << std::endl;
                std::cout << "3. IsEmpty" << std::endl;
                std::cout << "4. POP" << std::endl;
                std::cout << "5. EXIT" << std::endl;
                std::cout << "6. Print" << std::endl;
                std::cout << "Enter the choice" << std::endl;
                std::cin >> ch;
                switch (ch)
                {
                case 1:
                    std::cout << "Enter the number to be pushed" << std::endl;
                    std::cin >> char_elem;
                    s3.push(char_elem);
                    break;
                case 2:
                    std::cout << "Get the TOP Element" << std::endl;
                    try
                    {
                        s3.topElement();
                    }
                    catch (std::out_of_range &oor)
                    {
                        std::cerr << "Out of Range error:" << oor.what() << std::endl;
                    }
                    break;
                case 3:
                    std::cout << "Check Empty" << std::endl;
                    s3.isEmpty();
                    break;
                case 4:
                    std::cout << "POP the element" << std::endl;
                    try
                    {
                        s3.pop();
                    }
                    catch (const std::out_of_range &oor)
                    {
                        std::cerr << "Out of Range error: " << oor.what() << '\n';
                    }
                    break;
                case 5:
                    exit(0);
                case 6:
                    s3.print();
                    break;
                default:
                    std::cout << "Enter a valid input";
                    break;
                }
            }
        }
        else
            std::cout << "Invalid Choice";
        std::cin.get();
    }
    

2 个答案:

答案 0 :(得分:6)

切换到ostream版本的好处是,如果您以后需要打印到除std::cout之外的其他位置,那么您可以使用相同的函数实现来执行此操作,而在此时刻如果你想打印到一个文件,你需要使用不同的功能。

如何实现它的一个例子不是这样做的:

void print()
{   
    std::cout << "Print something always to cout" << std::endl;
}

你这样做(注意我们正在传递参考资料):

void print(std::ostream& os) 
{   
    os << "Print something to wherever the caller wants to" << std::endl;
}   

现在不是像以下那样调用函数:

print();

您将调用这样的函数打印到cout

print(std::cout);

或像这样打印到文件:

std::ofstream some_file("test.txt");
a.print(some_file);

请参阅,使用相同的功能,您可以决定打印的位置。

答案 1 :(得分:1)

将流作为参数传递给打印功能允许您使用具有不同流的相同打印功能,例如,您可以使用std::stringstream并获取&#34;输出&#34;作为字符串的内容而不是输出到控制台或文件。我建议你为&#34;&lt;&lt;&#34;运算符,这样你的代码在C ++中看起来更自然/惯用。我通常通过定义一个朋友&#34;来做到这一点。 &#34;运算符&lt;&lt;&##;在我班上。

这是运营商&lt;&lt;&lt;&lt;&lt;&lt;&lt;重载,请注意,因为它不是一个成员函数,你还需要传递它想要输出的对象的实例,我将它作为const引用传递给对象,你也可以通过值传递它:

    friend std::ostream & operator<<( std::ostream & o, const Mystack & stack ) {
        for (int i = 0; i <= stack.top; i++)
        {
            o << stack.input[i] << " ";
        }
        return o;
    }

这是您的类在定义函数时的样子

template <class T>
class Mystack
{
private:
    T *input;
    int top;
    int capacity;
public:
    Mystack();
    ~Mystack();
    void push(T const& x);
    void pop();
    T& topElement() const;
    bool isEmpty() const;
    void print();
    friend std::ostream & operator<<( std::ostream & o, const Mystack & stack ) {
        for (int i = 0; i <= stack.top; i++)
        {
            o << stack.input[i] << " ";
        }
        return o;
    }
};

然后你会像这样使用它

    case 6:
        std::cout << "The stack contents: " << s2 << std::endl;
        break;