【问题标题】:Using std::ostream as argument to a print function使用 std::ostream 作为打印函数的参数
【发布时间】:2015-03-02 10:21:03
【问题描述】:

我一直使用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,但无法理解。请帮忙。

下面是完整的运行代码:

//*************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();
}

【问题讨论】:

  • std::cout 是一个特殊的std::ostream。还有其他的,比如输出文件流。也就是说,采用std::ostream 参考参数将允许您打印到文件和其他内容。但是,print 函数通常不是执行此操作的最佳方法。相反,你应该为std::ostream 重载operator&lt;&lt;,这样你就可以只做cout &lt;&lt; my_stack;,例如。
  • std::cout std::ostream的一个实例,所以如果你的函数接受该类型的参数,你可以传入std::cout,包括@987654340的其他实例@like 文件、字符串流等。
  • 无关,您可能希望在不久的将来使您的堆栈Rule of Three 兼容。您目前缺少几件。
  • @JosephMansfield 如果您想要流插入器/提取器中的多态行为,则打印函数非常有用,方法是在基类中将其设为虚拟并使其成为这些运算符的委托。

标签: c++ iostream ostream


【解决方案1】:

切换到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);

看,使用相同的功能,您可以决定要打印的位置。

【讨论】:

    【解决方案2】:

    将流作为参数传递给打印函数允许您对不同的流使用相同的打印函数,例如您可以使用std::stringstream 并将“输出”作为字符串的内容而不是输出到控制台或文件。我建议您为“

    这里是一个操作符

        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;
    

    【讨论】:

      猜你喜欢
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-02
      • 2012-03-01
      • 2015-02-07
      • 1970-01-01
      • 2011-01-22
      相关资源
      最近更新 更多