根据用户选择从 class 模板定义对象并解析本地定义对象的范围 - 新问题

Defining object from class template based on user choice and resolving scope for locally defined objects - new question

我正在使用两个堆栈实现一个队列。整个代码基于模板,支持多种数据类型。

#include <iostream>
#define STACKSIZE 100

template <class T>
class Stack
{
private:
    int top;
    T *nodes;
public:
    Stack();
    T gettop();
    bool empty();
    void push(T&);
    T pop();
    ~Stack();
};

template <class T>Stack<T>::Stack()
{
    top=-1;
    nodes=new T[STACKSIZE];
}

template <class T>Stack<T>::~Stack()
{
    delete nodes;
}

template <class T> bool Stack<T>::empty()
{
    return(top<0);
}

template <class T> void Stack<T>::push(T&j)
{
    if(top==STACKSIZE-1)
    {
        std::cout<<"Stack Overflow"<<std::endl;
        return;
    }
    nodes[++top]=j;
}

template <class T>T Stack<T>::pop()
{
    T p;
    if (empty())
    {
        std::cout<<"Stack Underflow"<<std::endl;
        return p;
    }
    p=nodes[top--];
    return p;
}

template <class T>T Stack<T>::gettop()
{
    return this->top;
}

template <class T>
class Queue
{
    Stack<T>s1;
    Stack<T>s2;
public:
    void insert_into_queue(T data)
    {
        s1.push(data);
        std::cout<<"The value: "<<data<<" has been inserted into the Queue"<<std::endl;
    }
    void delete_from_queue()
    {
        if(s1.empty())
        {
            std::cout<<"The Stack S1 is Empty which implies Queue is Empty, nothing to delete"<<std::endl;
            return;
        }
        while(!s1.empty())
        {
            T top=s1.gettop();
            s1.pop();
            s2.push(top);
        }
        T d_val;
        d_val=s2.gettop();
        s2.pop();
        std::cout<<"The value: "<<d_val<<" has been deleted from the Queue"<<std::endl;
        while(!s2.empty())
        {
            T top=s2.gettop();
            s2.pop();
            s1.push(top);
        }
    }
};

int main()
{
    char choice;
    int option;
    int val;
    while(1)
    {
    std::cout<<"Provide the choice of DATA to work on: I for Integer, F for float, C for Character"<<std::endl;
    std::cin>>choice;
        if (choice == 'I' || choice == 'i')
        {
            Queue<int> q;
            break;
        }
        else if (choice == 'F' || choice == 'f')
        {
            Queue<float> q;
            break;
        }
        else if (choice == 'C' || choice == 'c')
        {
            Queue<char> q;
            break;
        }
        else
        {
            std::cout << "Not a valid choice" << std::endl;
        }
    }
    while(1)
    {
        std::cout<<"#######################################################################################"<<std::endl;
        std::cout<<"Press 1 to Insert a value into Queue: "<<std::endl;
        std::cout<<"Press 2 to Delete a value into Queue: "<<std::endl;
        std::cout<<"Press 3 to Exit the Program"<<std::endl;
        std::cin>>option;
        switch(option)
        {
            case 1:
                std::cout<<"Insert the value: "<<std::endl;
                std::cin>>val;
                q.insert_into_queue(val);
                break;
            case 2:
                q.delete_from_queue();
                break;
            case 3:
                exit(0);
                break;
            default:
                std::cout<<"Selected Option is Invalid"<<std::endl;
        }
    }
    return 0;
}

我的问题是我想从用户那里获得一个选择来为我的队列指定数据类型,直到用户为队列值提供正确的输入。

然后我希望用户向队列中插入数据或从队列中删除数据或退出程序。

我试图在 main() 函数内使用两个无休止的 while(1) 循环来拉动它们,但是当我这样做时,我失去了 q 的范围。

请建议对代码进行适当的修改(或)修改代码以实现所需的功能。

这个问题与

意义上提到的其他问题不同
  1. 我无法为队列创建基础 class,因为在这种情况下我无法定义成员
 Stack<T>s1;
 Stack<T>s2;

和方法

 void insert_into_queue(T data)
    {
        s1.push(data);
        std::cout<<"The value: "<<data<<" has been inserted into the Queue"<<std::endl;
    }
    void delete_from_queue()
    {
        if(s1.empty())
        {
            std::cout<<"The Stack S1 is Empty which implies Queue is Empty, nothing to delete"<<std::endl;
            return;
        }
        while(!s1.empty())
        {
            T top=s1.gettop();
            s1.pop();
            s2.push(top);
        }
        T d_val;
        d_val=s2.gettop();
        s2.pop();
        std::cout<<"The value: "<<d_val<<" has been deleted from the Queue"<<std::endl;
        while(!s2.empty())
        {
            T top=s2.gettop();
            s2.pop();
            s1.push(top);
        }
    }

完全依赖于模板。

此外,如果条件

,q是在本地定义的
 if (choice == 'I' || choice == 'i')
        {
            Queue<int> q;
            break;
        }

现在如何解析 q 的范围以便

 case 1:
                std::cout<<"Insert the value: "<<std::endl;
                std::cin>>val;
                q.insert_into_queue(val);
                break;

可以实施。

C++ 不是动态类型的。因此,您不能根据某些运行时条件(例如用户输入)来更改类型。无论你声明什么,它就是什么。

处理这个问题的最简单方法就是制作 3 个队列。然后,根据用户选择的类型,将值插入三个队列之一。

Queue<int> q1;
Queue<float> q2;
Queue<char> q3;

/* ... */

if (choice == 'I' || choice == 'i') {
    q1.insert_into_queue(...);
}

如果你的作业或挑战要求你只有一个对象,你可以使用std::variant得到一个space可以被不同类型的队列占用。

#include <variant>
std::variant<Queue<int>, Queue<float>, Queue<char>> q;

/* ... */

if (choice == 'I' || choice == 'i') {
    q = Queue<int> {};
}

/* ... */

if (choice == 'I' || choice == 'i') {
    std::get<Queue<int>>(q).insert_into_queue(...);
}

如果你只是稍微复制你的代码,你也可以避免这种幻想:

if (choice == 'I' || choice == 'i') {
    Queue<int> q;
    while (1) {
        /* ... input loop */
    }
}

或者甚至将重复的代码包装在模板中(whelp,现在又很漂亮了):

if (choice == 'I' || choice == 'i') {
    Queue<int> q;
    while (1) {
        input_loop<int>(q); // implementation left as exercise
    }
}

所以,您知道,有很多方法可以解决您的问题(但我推荐最简单的方法)。

最终代码供他人参考


int main()
{
    char choice;
    int option;
    int val1;
    float val2;
    char val3;
    Queue<int> q1;
    Queue<float> q2;
    Queue<char> q3;
    while(1)
    {
        std::cout<<"Provide the choice of DATA to work on: I for Integer, F for float, C for Character"<<std::endl;
        std::cin>>choice;
        if (choice == 'I' || choice == 'i')
        {
            break;
        }
        else if (choice == 'F' || choice == 'f')
        {
            break;
        }
        else if (choice == 'C' || choice == 'c')
        {
            break;
        }
        else
        {
            std::cout << "Not a valid choice" << std::endl;
        }
    }
    while(1)
    {
        std::cout<<"#######################################################################################"<<std::endl;
        std::cout<<"Press 1 to Insert a value into Queue: "<<std::endl;
        std::cout<<"Press 2 to Delete a value into Queue: "<<std::endl;
        std::cout<<"Press 3 to Exit the Program"<<std::endl;
        std::cin>>option;
        switch(option)
        {
            case 1:
                std::cout<<"Insert the value: "<<std::endl;
                if (choice == 'I' || choice == 'i')
                {
                    std::cin>>val1;
                    q1.insert_into_queue(val1);
                }
                else if (choice == 'F' || choice == 'f')
                {
                    std::cin>>val2;
                    q2.insert_into_queue(val2);
                }
                else if (choice == 'C' || choice == 'c')
                {
                    std::cin>>val3;
                    q3.insert_into_queue(val3);
                }
                break;
            case 2:
                if (choice == 'I' || choice == 'i')
                {
                    q1.delete_from_queue();
                }
                else if (choice == 'F' || choice == 'f')
                {
                    q2.delete_from_queue();
                }
                else if (choice == 'C' || choice == 'c')
                {
                    q3.delete_from_queue();
                }
                break;
            case 3:
                exit(0);
                break;
            default:
                std::cout<<"Selected Option is Invalid"<<std::endl;
        }
    }
    return 0;
}