#c #templates #if-statement #linked-list #switch-statement
#c #шаблоны #if-оператор #связанный список #оператор переключения
Вопрос:
Я написал рабочую связанную очередь, которая соответствует шаблону для своего типа данных, однако пользователь может вводить данные в одном из нескольких разных типов. Как я могу выбрать, какой тип данных будет использоваться во время выполнения?
Он отлично работает, если я использую каждый тип по отдельности; Мне просто нужно охватить все возможности без изменения кода или переписывания перегруженных функций для каждого типа данных.
Ниже я привел соответствующие фрагменты своего кода. Как я уже сказал, никаких проблем с функциями-членами моего класса нет.
Я уже пробовал оператор switch, который создает версию очереди типа x, но это не может работать, поскольку более поздние возможности в коммутаторе «противоречат» другим типам данных очереди. В настоящее время я пытаюсь использовать операторы if / else if без каких-либо ошибок, кроме тех, когда я пытаюсь использовать ввод типа x, он говорит, что он не определен.
// From Source.cpp
#include <iostream>
#include <string>
using namespace std;
#include "LQueue.h"
int mainMenu();
int main()
{
int value;
bool stop = false;
Queue<int> *theQueue;
int choice = mainMenu();
if (choice == 1) {
Queue<int> theQueue;
int dataType;
}
else if (choice == 2) {
Queue<double> theQueue;
double dataType;
}
else if (choice == 3) {
Queue<string> theQueue;
string dataType;
}
else if (choice == 4) {
Queue<char> theQueue;
char dataType;
}
cout << "nnHow many items would you like to initially"
<< " populate the queue with? ";
int howMany;
cin >> howMany;
for (int i = 0; i < howMany; i )
{
cin >> dataType;
theQueue.enqueue(dataType)
}
theQueue.display(cout);
theQueue.dequeue();
theQueue.display(cout);
return 0;
}
int mainMenu()
{
int choice;
cout << "What type of data will you be storing in the queue?n"
<< "1. integersn2. decimal numbersn3. wordsn4. charsnn";
cin >> choice;
if (choice > 0 amp;amp; choice < 5)
return choice;
cout << "nnInvalid choicenn";
mainMenu();
}
// Guess I'll include shown functions from the Queue class file below
//--- Definition of enqueue()
template <typename QueueElement>
void Queue<QueueElement>::enqueue(const QueueElement amp; value)
{
if (empty())
{
myFront = myBack = new Node(value);
}
else
{
myBack->next = new Node(value);
myBack = myBack->next;
}
}
//--- Definition of dequeue()
template <typename QueueElement>
void Queue<QueueElement>::dequeue()
{
if (empty() == false)
{
Queue::NodePointer oldFront = myFront;
myFront = myFront->next;
delete oldFront;
}
}
//--- Definition of display()
template <typename QueueElement>
void Queue<QueueElement>::display(ostream amp; out) const
{
Queue::NodePointer ptr;
for (ptr = myFront; ptr != 0; ptr = ptr->next)
out << ptr->data << " ";
out << endl;
}
//--- Definition of front()
template <typename QueueElement>
QueueElement Queue<QueueElement>::front() const
{
if (!empty())
return (myFront->data);
else
{
cerr << "*** Queue is empty "
" -- returning garbage ***n";
QueueElement * temp = new(QueueElement);
QueueElement garbage = *temp; // "Garbage" value
delete temp;
return garbage;
}
}
Compiler (visual studio 2017) is showing identifier "dataType" is undefined within the following loop:
```c
for (int i = 0; i < howMany; i )
{
cin >> dataType;
theQueue.enqueue(dataType);
}
2 ошибки: E0020 и C2065 в строке «cin>> Тип данных;», а также другая
C2065 в следующей строке
Может быть, есть более эффективный способ сделать это в целом? Я открыт для любых предложений, спасибо!
Комментарии:
1. обновление: я добавил typedef в начале основной функции.. и также изменил объявления переменных в if на typedefs… Сейчас работает, но я теряю данные после первого display(); вероятно, потому, что у меня нет нескольких определений для моего оператора присваивания. Для целых переменных работает просто отлично…. Уже спасибо тем, кто просмотрел lol xD
Ответ №1:
Проблема (проблема) заключается в том, что когда вы пишете
if (choice == 1) {
Queue<int> theQueue;
int dataType;
}
else if (choice == 2) {
Queue<double> theQueue;
double dataType;
}
else if (choice == 3) {
Queue<string> theQueue;
string dataType;
}
else if (choice == 4) {
Queue<char> theQueue;
char dataType;
}
вы определяете четыре разные theQueue
и четыре разные dataType
переменные, каждая из которых действительна только внутри соответствующего тела соответствующего if
.
Итак, когда вы пишете
for (int i = 0; i < howMany; i )
{
cin >> dataType;
theQueue.enqueue(dataType)
}
theQueue.display(cout);
theQueue.dequeue();
theQueue.display(cout);
больше нет dataType
и theQueue
доступны (все они находятся вне области видимости).
Я предлагаю что-то вроде следующего
if (choice == 1) {
foo<int>();
}
else if (choice == 2) {
foo<double>();
}
else if (choice == 3) {
foo<std::string>();
}
else if (choice == 4) {
foo<char>();
}
где foo()
находится функция шаблона, похожая на эту (внимание: код не тестировался)
template <typename T>
void foo ()
{
Queue<T> theQueue;
T dataType;
std::cout << "nnHow many items would you like to initially"
<< " populate the queue with? ";
int howMany;
std::cin >> howMany;
for (int i = 0; i < howMany; i )
{
std::cin >> dataType;
theQueue.enqueue(dataType)
}
theQueue.display(cout);
theQueue.dequeue();
theQueue.display(cout);
}
Комментарии:
1. так следует ли определять foo() в файле заголовка, поскольку это шаблонная функция?
2. @K.Rile — Может быть. Или также в том же cpp-файле, где вызывается, если он вызывается только в этом cpp-файле.
3. Потрясающе! ваше предложение работает великолепно! Большое спасибо! 10/10 снова спросит, лол
4. Я предоставляю альтернативный метод, который ищет функцию по индексу
Ответ №2:
Напишите шаблонную функцию-член, которая выполняет то, что вы хотите:
template<class DataType>
void processInput(int howMany) {
DataType value;
for (int i = 0; i < howMany; i )
{
cin >> value;
theQueue.enqueue(value);
}
theQueue.display(cout);
theQueue.dequeue();
theQueue.display(cout);
}
Метод 1 — оператор переключения
Затем мы можем использовать оператор switch для выбора между ними в main
:
int main()
{
int choice = mainMenu();
cout << "nnHow many items would you like to initially "
"populate the queue with? ";
int howMany;
cin >> howMany;
switch(choice) {
case 1:
processInput<int>(howMany);
break;
case 2:
processInput<double>(howMany);
break;
case 3:
processInput<string>(howMany);
break;
case 4:
processInput<char>(howMany);
break;
}
}
Метод 2 — массив методов
Мы можем использовать массив для выполнения поиска!
using func_t = void(*)(int);
int main() {
std::vector<func_t> options = {
processInput<int>,
processInput<double>,
processInput<string>,
processInput<char>
};
int choice = mainMenu();
func_t selectedOption = options[choice - 1];
cout << "nnHow many items would you like to initially "
"populate the queue with? ";
int howMany;
cin >> howMany;
selectedOption(howMany);
}