stack with menu option

Write your question here This is my program that convert an inflix expression to an postfix and prefix form and it run okay but im having trouble how to put a menu option like this

A]Prefixform
B]Postfixform
c]enter another expressio
d]exit


#include <iostream>
#include <stdio.h>
#include "conio.h"
#include <ctype.h>
#define MAX 50

typedef struct stack
{
int data[MAX];
int top;
}stack;

int precedence(char);
void init (stack *);
int empty (stack *);
int full (stack *);
int pop (stack *);
void push (stack *, int);
int top (stack *);
void infix_to_prefix (char infix[], char prefix[]);
void infix_to_postfix (char infix[], char postfix[]);
void eval_prefix (char prefix[]);
void eval_postfix (char postfix[]);
int evaluate (char x, int op1, int op2);

void main()
{
char infix[50], postfix[50], prefix[50];
system ("cls");
printf ("Enter an infix expression: ");
gets (infix);
infix_to_postfix (infix, postfix);
infix_to_prefix (infix, prefix);
printf("\nPrefix: %s\nPostfix: %s ", prefix, postfix);
printf("\n");
printf("\nPrefix Evaluation: ");
eval_prefix (prefix);
printf("\n");
printf("\nPostfix Evaluation: ");
eval_postfix (postfix);
_getch();
}

void infix_to_prefix(char infix[],char prefix[])
{
int i, j;
char temp,in1[30];

for (i = strlen(infix)-1, j=0; i>=0; i--, j++)
in1[j] = infix[i];
in1[j] = '\0';

for(i=0; in1[i]!='\0' ;i++)
{
if(in1[i] == '(')
in1[i] = ')';
else
if(in1[i] == ')')
in1[i]= '(';
}

infix_to_postfix(in1, prefix);

for(i = 0,j = strlen(prefix)-1; i<j; i++, j--)
{
temp = prefix[i];
prefix[i] = prefix[j];
prefix[j] = temp;
}
}

void infix_to_postfix(char infix[],char postfix[])
{
stack s;
char x;
int i, j;
char token;
init(&s);
j = 0;
for(i = 0; infix[i]!='\0'; i++)
{
token = infix[i];
if(isalnum(token))
postfix[j++] = token;
else
if(token == '(')
push(&s,'(');
else
if(token == ')')
while((x = pop(&s)) != '(')
postfix[j++] = x;
else
{
while(precedence(token)<=precedence(top(&s)) && !empty(&s))
{
x = pop(&s);
postfix[j++] = x;
}
push(&s,token);
}
}
while(!empty(&s))
{
x = pop(&s);
postfix[j++] = x;
}
postfix[j] = '\0';
}

void eval_postfix(char postfix[])
{
stack s;
char x;
int op1, op2, val, i;
init(&s);
for (i = 0; postfix[i] != '\0' ;i++)
{
x = postfix[i];
if(isalpha(x))
{
printf("\nEnter the value of %c: ", x);
scanf("%d", &val);
push(&s, val);
}
else
{

op2 = pop(&s);
op1 = pop(&s);
val = evaluate(x,op1,op2);
push(&s,val);
}
}
val = pop(&s);
printf("\nValue of expression = %d", val);

}
void eval_prefix(char prefix[])
{
stack s;
char x;
int op1, op2, val, i;
init(&s);
for(i = strlen(prefix)-1; i >= 0; i--)
{
x = prefix[i];
if(isalpha(x))
{
printf("\nEnter the value of %c: ", x);
scanf("%d", &val);
push(&s,val);
}

else
{

op1 = pop(&s);
op2 = pop(&s);
val = evaluate(x, op1, op2);
push(&s, val);
}
}
val = pop(&s);
printf("\nValue of expression = %d", val);

}

int evaluate(char x,int op1,int op2)
{
if(x == '+') return(op1 + op2);
if(x == '-') return(op1 - op2);
if(x == '*') return(op1 * op2);
if(x == '/') return(op1 / op2);
if(x == '%') return(op1 % op2);

}

int precedence(char x)
{
if(x == '(') return(0);
if(x == '+' || x == '-') return(1);
if(x == '*' || x == '/' || x == '%') return(2);
return(3);
}

void init(stack *s)
{
s->top = -1;
}

int empty(stack *s)
{
if(s->top == -1) return(1);
return(0);
}

int full(stack *s)
{
if(s->top == MAX-1) return(1);
return(0);
}

void push(stack *s,int x)
{
s->top = s->top+1;
s->data[s->top] = x;
}

int pop(stack *s)
{
int x;
x = s->data[s->top];
s->top = s->top-1;
return(x);
}

int top(stack * p)
{
return(p->data[p->top]);
}
One way to implement a menu is like this:
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
53
54
#include <iostream>
#include <cctype>

using namespace std;

void showMenu();
char getChoice();

int main()
{
  bool quit = false;

  while (!quit)
  {
    showMenu();
    char ch = getChoice();
    switch(ch)
    {
      case 'A': 
        // handle choice A
        break;
      case 'B':
        // handle choice B
        break;
      case 'C':
        // handle choice C
        break;
      case 'D':
        quit = true;
        break;
    }
  }
  
  system("pause");
  return 0;
}

char getChoice()
{
  cout << "\nEnter choice: ";
  char ch;
  cin >> ch;
  cin.ignore(255, '\n');

  return toupper(ch);
}

void showMenu()
{
  cout << "\nA\tPrefixform";
  cout << "\nB\tPostfixform";
  cout << "\nC\tAnother expression";
  cout << "\nD\tExit";
}


Inside the switch statement replace the // handle choice A with a call to the proper function.
closed account (48bpfSEw)
I tried to write a more flexible menu and stumbled in virtuality problems, maybe someone can lend me a hand or something in that way to find the way out...

First I created for each task a class which are derived from a base class.
Then I stored all the instances into a map.
When I call "MenuBase::exec();" : always the exec of the base class is called!

I tried to fix the problem with defining the exec of the base class as pure virtual ( = 0;) but then I can not store the instances into the map.


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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// #include "stdafx.h"
#include <map>
#include <iostream>

#include <windows.h>
#include <conio.h>


char pressanykey(void) // const char *prompt)
{
	DWORD        mode;
	HANDLE       hstdin;
	INPUT_RECORD inrec;
	DWORD        count;
	// char         default_prompt[] = "Press the 'any' key...";
	char         result = '\0';

	/* Set the console mode to no-echo, raw input, */
	/* and no window or mouse events.              */
	hstdin = GetStdHandle(STD_INPUT_HANDLE);
	if (hstdin == INVALID_HANDLE_VALUE
		|| !GetConsoleMode(hstdin, &mode)
		|| !SetConsoleMode(hstdin, 0))
		return result;

	// if (!prompt) prompt = default_prompt;

	/* Instruct the user * /
	WriteConsole(
		GetStdHandle(STD_OUTPUT_HANDLE),
		prompt,
		lstrlen(prompt),
		&count,
		NULL
	); */

	FlushConsoleInputBuffer(hstdin);

	/* Wait for and get a single key PRESS */
	do ReadConsoleInput(hstdin, &inrec, 1, &count);
	while ((inrec.EventType != KEY_EVENT) || !inrec.Event.KeyEvent.bKeyDown);

	/* Remember which key the user pressed */
	result = inrec.Event.KeyEvent.uChar.AsciiChar;

	/* Wait for and get a single key RELEASE */
	do ReadConsoleInput(hstdin, &inrec, 1, &count);
	while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);

	/* Restore the original console mode */
	SetConsoleMode(hstdin, mode);

	return result;
}



class TopicBase {
public:
	int				iMenuID;
	std::string		strMenuCaption;

public:
	virtual void exec(void) { 
		std::cout << "Executing Topic Base" << std::endl; 
	};
};

class TopicA_Sub : public TopicBase {
public:
	void exec (void) {
		std::cout << "Executing TopicA_Sub" << std::endl;
	}
};


class TopicA : public TopicBase {
public:
	void exec(void) {
		std::cout << "Executing TopicA" << std::endl;
	}
};

class TopicB : public TopicBase {
public:
	void exec(void) {
		std::cout << "Executing TopicB" << std::endl;
	}
};

class TopicFinish : public TopicBase {
public:
	void exec(void) {
		// clean up and shut down
		std::cout << "Executing TopicFinish" << std::endl;
		exit(0);
	}
};



class MenuBase {
public:
	std::map<int, TopicBase>				mapMenu;
	std::map<int, TopicBase>::iterator		it;

public:
	void exec(void) {
		while (true) {
			for (it = mapMenu.begin(); it != mapMenu.end(); ++it) {
				std::cout << it->second.iMenuID << ") " << it->second.strMenuCaption.c_str() << std::endl;
			}

			std::cout << "Insert Menu ID: ";
			char pszUserInput[2];
			pszUserInput[0] = pressanykey();
			pszUserInput[1] = '\0';
			int cUserInput = atoi(pszUserInput);

			it = mapMenu.find(cUserInput);
			if (it == mapMenu.end()) {
				std::cout << "Menu ID not found!" << std::endl;
				continue;
			}

			it->second.exec();
		}
	}
};

class MenuAB : public MenuBase {
public:
	void exec(void) {
		TopicA			topicA;
		TopicB			topicB;
		TopicFinish		topicFinish;

		topicA.iMenuID = 1;
		topicA.strMenuCaption = "Menu Topic A";

		topicB.iMenuID = 2;
		topicB.strMenuCaption = "Menu Topic B";

		topicFinish.iMenuID = 9;
		topicFinish.strMenuCaption = "Quit";
		
		mapMenu[topicA.iMenuID		] = topicA;
		mapMenu[topicB.iMenuID		] = topicB;
		mapMenu[topicFinish.iMenuID ] = topicFinish;

		MenuBase::exec();
	}
};


int main()
{
	MenuAB menuAB;
	menuAB.exec();
	
	return 0;
}
mapMenu requires a [smart] pointer to TopicBase in order to use the inheritance. Otherwise you copy only the data of base class.
closed account (48bpfSEw)
thank you coder777!

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 *	Menu with Submenu
 *
 *		1. Topic A			-->  1. Topic Sub A
 *		2. Topic B				 8. Return (to main menu)
 *		9. Exit					 9. Exit
 */



#include "stdafx.h"
#include <map>
#include <iostream>

#include <windows.h>
#include <conio.h>

// Helpfunctions
char pressanykey(void) {
	DWORD        mode;
	HANDLE       hstdin;
	INPUT_RECORD inrec;
	DWORD        count;
	char         result = '\0';

	/* Set the console mode to no-echo, raw input, */
	/* and no window or mouse events.              */
	hstdin = GetStdHandle(STD_INPUT_HANDLE);
	if (hstdin == INVALID_HANDLE_VALUE
		|| !GetConsoleMode(hstdin, &mode)
		|| !SetConsoleMode(hstdin, 0))
		return result;

	FlushConsoleInputBuffer(hstdin);

	/* Wait for and get a single key PRESS */
	do ReadConsoleInput(hstdin, &inrec, 1, &count);
	while ((inrec.EventType != KEY_EVENT) || !inrec.Event.KeyEvent.bKeyDown);

	/* Remember which key the user pressed */
	result = inrec.Event.KeyEvent.uChar.AsciiChar;

	/* Wait for and get a single key RELEASE */
	do ReadConsoleInput(hstdin, &inrec, 1, &count);
	while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);

	/* Restore the original console mode */
	SetConsoleMode(hstdin, mode);

	return result;
}


// Topic
class TopicBase {
public:
	int				iMenuID;
	std::string		strMenuCaption;

public:
	virtual void exec(void) = 0;
};

class TopicA_Sub : public TopicBase {
public:
	void exec (void) {
		std::cout << "Executing TopicA_Sub" << std::endl;
	}
};


class TopicA : public TopicBase {
public:
	void exec(void);
};

class TopicB : public TopicBase {
public:
	void exec(void) {
		std::cout << "Executing TopicB" << std::endl;
	}
};

class TopicFinish : public TopicBase {
public:
	void exec(void) {
		// clean up and shut down
		std::cout << "Executing TopicFinish" << std::endl;
		exit(0);
	}
};

class TopicReturn : public TopicBase {
public:
	void exec(void) {
		std::cout << "Executing TopicReturn" << std::endl;
	}
};

class MenuBase {
public:
	std::map<int, TopicBase*>				mapMenu;
	std::map<int, TopicBase*>::iterator		it;

public:
	void exec(void) {
		while (true) {
			for (it = mapMenu.begin(); it != mapMenu.end(); ++it) {
				std::cout << it->second->iMenuID << ") " << it->second->strMenuCaption.c_str() << std::endl;
			}

			std::cout << std::endl << "Insert Menu ID: ";
			char pszUserInput[2];
			pszUserInput[0] = pressanykey();
			pszUserInput[1] = '\0';
			int cUserInput = atoi(pszUserInput);

			it = mapMenu.find(cUserInput);
			if (it == mapMenu.end()) {
				std::cout << "Menu ID not found!" << std::endl;
				continue;
			}
			std::cout << std::endl;

			it->second->exec();


			TopicReturn* ptr = dynamic_cast<TopicReturn*> (it->second);
			if (ptr)
				break;
		}
	}
};

class MenuAB : public MenuBase {
public:
	void exec(void) {
		TopicA			topicA;
		TopicB			topicB;
		TopicFinish		topicFinish;

		topicA.iMenuID = 1;
		topicA.strMenuCaption = "Menu Topic A";

		topicB.iMenuID = 2;
		topicB.strMenuCaption = "Menu Topic B";

		topicFinish.iMenuID = 9;
		topicFinish.strMenuCaption = "Quit";
		
		mapMenu[topicA.iMenuID		] = &topicA;
		mapMenu[topicB.iMenuID		] = &topicB;
		mapMenu[topicFinish.iMenuID ] = &topicFinish;

		MenuBase::exec();
	}
};


class MenuA_Sub : public MenuBase {
public:
	void exec(void) {
		TopicA_Sub		topicA_Sub;
		TopicReturn		topicReturn;
		TopicFinish		topicFinish;

		topicA_Sub.iMenuID = 1;
		topicA_Sub.strMenuCaption = "Menu Topic A sub";

		topicReturn.iMenuID = 8;
		topicReturn.strMenuCaption = "Return";

		topicFinish.iMenuID = 9;
		topicFinish.strMenuCaption = "Quit";

		mapMenu[topicA_Sub.iMenuID]  = &topicA_Sub;
		mapMenu[topicReturn.iMenuID] = &topicReturn;
		mapMenu[topicFinish.iMenuID] = &topicFinish;

		MenuBase::exec();
	}
};


// Implementation
void TopicA::exec(void) {
	MenuA_Sub menuA_Sub;
	menuA_Sub.exec();
}



// MAIN
int main()
{
	MenuAB menuAB;
	menuAB.exec();
	
	return 0;
}
Last edited on
@Necip

First: You create dangling pointer.
Second: Did you hijack this thread?
closed account (48bpfSEw)
@coder777,

first: what is the difference between dangling and smart pointer?
second: no.



edit:
first: http://ootips.org/yonat/4dev/smart-pointers.html
http://stackoverflow.com/questions/17997228/what-is-a-dangling-pointer


ok, now I can answer your first question :
Since the instances are within the scopes they are not dangled!
The objects are freed when the application is finished.



edit:
second: let us ask the founder of this thread bubbles102289, if my solution is for the wastebasket. If he/she says "thumbs down" I'll delete all my contributions in this thread.
Last edited on
Topic archived. No new replies allowed.