How to write a console menu in ANSI/ISO C? - c

I'm trying to create a simple program in c, where the user has to choose between several options:
char command = '1';
while(command!='0') {
printf("Menu:\n");
printf("1. First option\n");
printf("2. Second option\n");
printf("0. Exit\n");
printf("Choose: 0,1,2?: ");
command = getchar();
while(getchar()!='\n');
switch(command) {
case '0': break;
case '1': functionCall1(); break;
case '2': functionCall2(); break;
}
}
The problem with my code is, that every second time I enter 1,2 or 0, nothing happens, only the menu prints itself again. With the debugger I can see, that the value of command, after command = getchar() equals '', every second time. I thought that eating the newline character is enough?

Try my customized menu, I implemented it to make my life easier when I work with programs which contains multiple choices operations.
Menu is navigable (arrows:up, down, left, right), and for making a selection you only need to press enter key, menu orientation can be set vertically or horizontally, padding can be set to a group of items(childrens), child starting position, and update with delay.
Menu call example (vertically):
int response = menu("OPTIONS","[*]","->",
1,3,3,0,5,
"PROFILES","ACTIVITY","VIDEO","SOUND","GAMEPLAY");
The most important thing is because function implementation takes only 60 lines of code.
Menu implementation:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <windows.h>
// LXSoft
// mod: cui/menu_021
// stdarg.h -> used for variable list of arguments (va_list, va_start ...)
// windows.h -> used for Sleep function, for *nix use unistd.h
typedef unsigned short int usint_t;
// Menu function prototype
int menu(char* name, char* prefix, char* cursor, usint_t orientation,
usint_t padding, usint_t start_pos, usint_t delay,
usint_t num_childs, ...);
int main()
{
int response = menu("OPTIONS","[*]","->",1,3,3,0,5,
"PROFILES","ACTIVITY","VIDEO","SOUND","GAMEPLAY");
switch(response)
{
case 1:
// doSomethingFoo1();
break;
case 2:
//doSomethingFoo2();
break;
/*
* .
* .
* .
* case n:
* break;
*/
}
printf("\nYour choice is: %d", response);
return 0;
}
// Menu implementation
int menu
(
char *name, // Menu name (eg.: OPTIONS)
char *prefix, // Menu prefix (eg.: [*])
char *cursor, // Menu cursor (eg.: ->)
usint_t orient, /*
* Menu orientation vertical or horzontal.
* 0 or false for horizontal
* 1 or true for vertical
*/
usint_t padding, // Menu childrens padding (eg.: 3)
usint_t start_pos, // Menu set active child (eg.: 1)
usint_t delay, // Menu children switch delay
usint_t childs, // Number of childrens
... /*
* Variable list of arguments char* type.
* Name of the childrens.
*/
)
{
va_list args;
int tmp=0,pos;
char chr;
usint_t opt=start_pos;
char* format=malloc
(
(
strlen(name)+strlen(prefix)+strlen(cursor)+
3+ /* menu suffix (1 byte) and backspace (2 bytes) */
(2*childs)+ /* newline (2 bytes) times childs */
(padding*childs)+ /* number of spaces times childs */
childs*15 /* children name maxlen (15 bytes) times childs*/
)*sizeof(char)
);
do
{
if(tmp!=0)chr=getch();
if(chr==0x48||chr==0x4B)
(opt>1&&opt!=1)?opt--:(opt=childs);
else if(chr==0x50||chr==0x4D)
(opt>=1&&opt!=childs)?opt++:(opt=1);
else {/* do nothing at this time*/}
strcpy(format,"");
strcat(format,prefix);
strcat(format,name);
strcat(format,":");
va_start(args,childs);
for (tmp=1;tmp<=childs;tmp++)
{
(orient)?strcat(format,"\n"):0;
pos=padding;
while((pos--)>0) strcat(format," ");
if(tmp==opt)
{
strcat(format,"\b");
strcat(format,cursor);
}
strcat(format,va_arg(args,char*));
}
/*if(tmp!=childs)
{
fprintf(stderr,"%s: recieved NULL pointer argument,"
" child not named", __func__);
return -1;
}*/
Sleep(delay);
system("cls");
printf(format);
va_end(args);
}while((chr=getch())!=0x0D);
return opt;
}

May be you should try to use int x as a key to use a desirable command, may be like that:
while(x != 0)
{
scanf("%d", &x);
switch (x)
{
printf("input '2' to...\n");
printf("input '3' to...\n");
printf("input '4' to...\n");
printf("input '5' to...\n");
printf("input '6' to...\n");
case 1:
head = Enqueue(head);
break;
case 2:
head1 = spisokMagazinovScenoiMensheiZadannoi(head, head1);
break;
case 3:
head1 = udalenieElementa(head1);
break;
case 4:
head1 = addNewMagazin(head1);
break;
case 5:
head1 = addNewMagazin(head1);
break;
case 6:
printToTheFile(head);
break;
}
}
I used it in my previous homework. Hope it will be usefull for you

it's my exaple of func menu.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <windows.h>
int menu(char s[][80],int kolop){
int pos = 0,push = 0,i,flag = 0;
printf("MENU:\n>");
puts(s[0]);
for(i = 1;i < kolop;i++){
printf(" ");
puts(s[i]);
}
printf("Enter 5 to move the cursor down 8 to the top(Press ENTER to end)\n");
do{
if(flag == 1)
printf("Error try to press 5,8 or ENTER\n");
push = getch();
flag = 1;
}
while(push != 56 && push != 53 && push != 13);
flag = 0;
system("cls");
while(push != 13){
if(push == 53){
puts("MENU:");
for(i = 0;i < kolop;i++){
if(i == pos + 1 && flag == 0){
printf(">");
puts(s[i]);
flag = 1;
pos++;
}
else{
printf(" ");
puts(s[i]);
}
}
}
if(push == 56){
puts("MENU:");
for(i = 0;i < kolop;i++){
if(i == pos - 1 && flag == 0){
printf(">");
puts(s[i]);
flag = 1;
pos--;
}
else{
printf(" ");
puts(s[i]);
}
}
}
_flushall();
printf("Enter 5 to move the cursor down 8 to the top(Press ENTER to end)\n");
flag = 0;
do{
if(flag == 1)
printf("Error try to press 5,8 or ENTER\n");
push = getch();
flag = 1;
}
while(push != 56 && push != 53 && push != 13);
flag = 0;
system("cls");
}
pos++;
return pos;
}
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
char s[][80] = {"1","2","3","4","5","6","7"};
int i,pos = 0,push,flag = 0;
pos = menu(s,7);
printf("%d",pos);
//system("cls");
return 0;
}

Related

My static stack code is not running properly

#include <stdio.h>
#include <stdlib.h>
#define N 5
int stack[N];
int top = -1;
void push()
{
int x;
printf("Enter data");
scanf("%d", &x);
if (top == N - 1)
{
printf("Overflow");
}
else
{
top++;
stack[top] = x;
}
}
void pop()
{
int item;
if (top == -1)
{
printf("Underlfow");
}
else
{
item = stack[top];
top--;
printf("%d", item);
}
}
void peek()
{
if (top == -1)
{
printf("Underflow");
}
else
{
printf("%d", stack[top]);
}
}
void display()
{
int i;
for (i = top; i >= 0; i--)
{
printf("%d\n", stack[top]);
}
}
int main()
{
int ch;
do
{
printf("\n1.push\n2.pop\n3.peek\n4.display");
scanf("%d", &ch);
switch (ch)
{
case 1:
push();
break;
case 2:
pop();
break;
case 3:
peek();
break;
case 4:
display();
break;
case 5:
exit(0);
break;
default:
printf("invalid key pressed");
break;
}
} while (ch != 0);
return 0;
}
So it is the code which i wrote following a tutorial on youtube
In push function if i excced the array size which is 5 it will still take values instead of printing overflow and when i try to display it, it will display all values same
before i was geting a error at getch(); while using void main() so i change it to int main() and used return 0; it is still not working.
So it is the code which i wrote following a tutorial on youtube In push function if i excced the array size which is 5 it will still take values instead of printing overflow and when i try to display it, it will display all values same
Your logic is to always allow you to enter values. But they are not inserted in the stack (and instead "Overflow" is printed). This is because you ask for the value before checking if the stack is full. Just make the test before, and put the scan inside the else part of the if statement.
void push()
{
int x;
if (top == N - 1) {
/* put \n chars at end of lines in output statements
* like this ---vv */
printf("Overflow\n");
} else {
printf("Enter data ");
fflush(stdout);
scanf("%d", &x);
top++;
stack[top] = x;
}
}
The problem of printing always the top of the stack is basically that you print stack[top], instead of stack[i], in the display() function loop. You should use this code instead.
void display()
{
int i;
for (i = top; i >= 0; i--)
{
/* use i here --------------v */
printf("%d: %d\n", i, stack[i]);
}
}
This is not an error, but will save you trouble in the future. Get used to put the \n char at the end of the printing format, instead of at the beginning, if you are going to print a complete line. I understand that you want to avoid it when prompting the user, so you avoid it. But the stdio library uses buffering, so it doesn't print things when you ask it for, so it delays the printing of strings (on an interactive session) until you do printf a '\n' char (if the output device is a terminal), or before reading from stdin (also, if the input device is a terminal). This can make a mess if you print your strings without the trailing '\n'. And more, if you redirect your output, this means using a pipe (so, it is not a terminal). Then, no output is done until the buffer fills completely (meaning over 10kb of data, usually 16kb on modern unix/linux systems) You will see your program doing things while no output has been output, and you won't know why.
You don't use getch() in your code, so i think you have posted a different version of the code you are talking about.
My code, after edition, leads to:
#include <stdio.h>
#include <stdlib.h>
#define N 5
int stack[N];
int top = -1;
void push()
{
if (top == N - 1) {
/* no overflow yet, not if we check beforehand :) */
printf("Stack full, cannot push()\n");
} else {
int x;
printf("Enter data ");
fflush(stdout); /* to flush the output (no \n at end) */
scanf("%d", &x);
top++;
stack[top] = x;
printf("Push: %d to position %d\n", x, top);
}
}
void pop()
{
if (top == -1) {
/* the appropiate message is stack empty, no underflow has
* occured yet. We are preventing it */
printf("Stack empty, cannot pop()\n");
} else {
int item = stack[top];
printf("Pop: %d from pos %d\n", item, top);
top--;
}
}
void peek()
{
if (top == -1) {
/* no underflow yet, we are preventing it */
printf("Stack empty, cannot peek()\n");
} else {
printf("Peek: %d on pos %d\n", stack[top], top);
}
}
void display()
{
int i;
printf("Stack contents:\n");
for (i = top; i >= 0; i--) {
printf("> %d: %d\n", i, stack[i]);
}
}
int main()
{
int ch = 5; /* so we exit if no valid input is made in scanf() */
do {
printf("1.push\n"
"2.pop\n"
"3.peek\n"
"4.display\n"
"5.exit\n");
scanf("%d", &ch);
switch (ch) {
case 1:
push();
break;
case 2:
pop();
break;
case 3:
peek();
break;
case 4:
display();
break;
case 5:
break;
default:
printf("Input invalid option\n");
break;
}
} while (ch != 5); /* option 5 is to exit */
return 0;
}

Input a string and an integer on the same line separated by a space

I am trying to make a mini game where you input a command about what to do, and you need to input your
since most of my inputs will look like this:atk 1
or:health 1
The input must in one line, but there are commands that don't have a number after them.
I need to input them in one line, so I use scanf("%s %d") to do this, but I also have some commands that don't have a number after the string, but if I don't use scanf I don't have ways to input them in a same line.
Is there solutions for situation like this? Sometimes the input is a string with a number, and sometimes a string only.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100
struct status
{
int hp;
char name[MAXSIZE];
};
int main()
{
struct status you;
struct status enemy;
//your name and hp
scanf("%s %d", you.name, &you.hp);
//enemy's name and hp
scanf("%s %d", enemy.name, &enemy.hp);
char move[MAXSIZE];
int damage = 0;
int poison = 0;
int round = 0;
//game start
//you start first, than you input what enemy do in next round
//atk means attack, poison means you got poison by enemy on every end of rounds, health means you heal yourself, none means you skip this round
//show means to show your and enemy's curreny status
//end means end the game the process stop, it also stops when someone's hp is zero
while((you.hp > 0)&&(enemy.hp > 0) )
{
scanf("%s %d", move, &damage);
if( strcmp(move,"atk") == 0 )
{
if((round%2) == 0)
enemy.hp = enemy.hp - damage;
else
you.hp = you.hp = damage;
round++;
}
else if( strcmp(move,"health") == 0 )
{
you.hp = you.hp + damage;
round++;
}
else if( strcmp(move,"poison") == 0 )
{
poison = poison + damage;
round++;
}
else if( strcmp(move,"none") == 0 )
{
round++;
}
else if( strcmp(move,"show") == 0)
{
printf("%s %d %s %d\n", you.name, you.hp, enemy.name, enemy.hp);
continue;
}
else
break;
}
if( strcmp(move, "atk") == 0)
{
if((round%2) == 0)
printf("%s were defeated by attack", you.name);
else
printf("%s were defeated by your attack", enemy.name);
}
else if( strcmp(move, "end") == 0)
{
return 0;
}
else
printf("%s were defeated by poison", you.name);
return 0;
}
The general advice is to avoid scanf.
Instead, fgets can be used to read an entire line of input from a stream into a buffer. Then the buffer can be freely manipulated, or parsed multiple times, without having to worry about the state of the stream.
The program below has examples of using both strtok (+ strtol) and sscanf to extract data from a string. Each of these tools has advantages and disadvantages; reading their documentation is recommended.
Some additional suggestions:
The use of an enum reduces the need to repeatedly compare strings, and its integral nature allows the use of a switch. An array kept in parallel (actions) to the enumeration type acts as a lookup table for string<->enum conversions. At the same time, this array can be used to indicate if a command requires an argument.
Placing your players in an array allows the use of modular arithmetic to determine the current player and next player without repeatedly checking the turn count. Alternatively, having a pointer to each player and swapping the values of the pointers each turn might prove easier to read.
poison should probably be an attribute of a player (struct status).
Here is an example program with a few of these concepts to play around with:
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100
#define SEP " \r\n"
struct status {
char name[MAXSIZE];
int hp;
int poison;
};
static const struct {
const char *method;
bool needs_value;
} actions[] = {
{ NULL },
{ "atk", true },
{ "health", true },
{ "poison", true },
{ "show", false },
{ "end", false },
{ "none", false }
};
enum ACTION {
ACTION_INVALID,
ACTION_ATK,
ACTION_HEALTH,
ACTION_POISON,
ACTION_SHOW,
ACTION_END,
ACTION_NONE,
ACTION_ACTIONS
};
enum ACTION get_action(int *value)
{
char buf[256];
if (!fgets(buf, sizeof buf, stdin))
exit(EXIT_FAILURE);
char *method = strtok(buf, SEP);
if (!method)
return ACTION_INVALID;
for (enum ACTION e = ACTION_ATK; e < ACTION_ACTIONS; e++) {
if (0 == strcmp(method, actions[e].method)) {
if (actions[e].needs_value) {
char *value_token = strtok(NULL, SEP);
if (!value_token || !*value_token)
break;
char *end;
errno = 0;
*value = strtol(value_token, &end, 10);
/* integer overflow or string was not completely parsed */
if (ERANGE == errno || *end)
break;
}
return e;
}
}
return ACTION_INVALID;
}
bool get_player(struct status *p)
{
char buf[256];
printf("Enter a name and hp: ");
if (!fgets(buf, sizeof buf, stdin))
exit(EXIT_FAILURE);
p->poison = 0;
return 2 == sscanf(buf, "%99s%d", p->name, &p->hp);
}
void print_status(struct status *s)
{
printf("%s has %d HP and %d poison.\n",
s->name, s->hp, s->poison);
}
int main(void)
{
struct status players[2] = { { "Alice", 123, 0 }, { "Bob", 42, 0 } };
/* uncomment for user input
if (!get_player(players) || !get_player(players + 1))
exit(EXIT_FAILURE);
*/
int current = 0;
while (1) {
int next = (current + 1) % 2;
int value;
printf("%s's turn. Enter an action: ", players[current].name);
switch (get_action(&value)) {
case ACTION_INVALID:
fprintf(stderr, "Invalid action.\n");
continue;
case ACTION_ATK:
printf("%s deals %d damage to %s\n",
players[current].name, value, players[next].name);
players[next].hp -= value;
break;
case ACTION_POISON:
printf("%s applies %d poison to %s\n",
players[current].name, value, players[next].name);
players[next].poison += value;
break;
case ACTION_HEALTH:
printf("%s heals %d health.\n",
players[current].name, value);
players[current].hp += value;
break;
case ACTION_SHOW:
print_status(players + current);
print_status(players + next);
continue;
case ACTION_END:
return EXIT_SUCCESS;
case ACTION_NONE:
break;
default:
continue;
}
if (players[next].hp < 1) {
printf("%s has slain %s!\n",
players[current].name, players[next].name);
break;
}
/* apply poison, and reduce poison by one */
if (players[current].poison)
players[current].hp -= players[current].poison--;
if (players[current].hp < 1) {
printf("%s has died to poison!\n", players[current].name);
break;
}
current = next;
}
}
Example usage:
Alice's turn. Enter an action: show
Alice has 123 HP and 0 poison.
Bob has 42 HP and 0 poison.
Alice's turn. Enter an action: poison 22
Alice applies 22 poison to Bob
Bob's turn. Enter an action: atk 50
Bob deals 50 damage to Alice
Alice's turn. Enter an action: none
Bob's turn. Enter an action: atk 50
Bob deals 50 damage to Alice
Bob has died to poison!

How Can I Pass a Menu Function Int Value Back To Main To Access Other Menu Functions Using Switch Statement?

I'm doing this for part of a school project and I am so lost and this is only the beginning of it. Our professor wants us to have 4 menu functions. Each menu has options to access other functions within the program. First, we are asked to have the program state if we would like to start or quit. That's no problem. My problem is when I run the main menu function and select an option I cannot get my choice to return to main to run the switch case to access the other menus. Right now I have all the other menus saying "coming soon..." just so I know I am getting it right. I'll add more once I get past this part. This is my first post here so I apologize if this is a lot of code to post. I greatly appreciate any help. Thank you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
//declare all working variables: mOption, FManOption, COption...etc...
int MOption = 0;
int FManOption = 0;
int FOption = 0;
int COption = 0;
int userChoice = 0;
int n = mainMenu();
switch(n)
{
case 1: while(FManOption != 3)
{
FManOption = FishermanMenu();
switch(FManOption)
{
case 1: //get a fisherman
//count fisherman
break;
case 2: //prompt for a ssn, validate, search
//if found display everything about this fisherman
break;
case 3: //hit any key to go back to main menu
//reset FManOption
break;
default: "error!";
}//end switch(FManOption)
}//end while(FManOption != 3)
break;
default: printf("error");
}
return 0;
}
int mainMenu()
{
int option = 0;
printf("-------Welcome to the Fishing Tournament Main Menu!-------\n\n");
do
{
printf("1 - Fisherman menu\n");
printf("2 - Fish menu\n");
printf("3 - Tournament(Catch) menu\n");
printf("4 - Close Tournament (determine winner)\n");
printf("5 - Quit Program\n\n");
printf("Please select a menu option: ");
if (scanf("%d", &option) != 1) /* check scanf() return value for input errors */
{
/* handle input error */
return -1;
}
} while (option < 1 || option > 5); /* check the range of option ( 1 - 5) */
return option; /* finally return the final correct option */
}
int FishermanMenu()
{
printf("Coming soon...");
/*
-1-Register fisherman
-2-Search fisherman
-3-Go back to main menu
*/
//FManOption
}//end Fisherman Menu
Your mainMenu() function doesn't return anything other than 0, in addition you ignore the return value in main, when you call mainMenu(); (this shouldn't even compile btw), this is probably what you are looking for,
int mainMenu(void)
{
int option = 0;
printf("-------Welcome to the Fishing Tournament Main Menu!-------\n\n");
do
{
printf("1 - Fisherman menu\n");
printf("2 - Fish menu\n");
printf("3 - Tournament(Catch) menu\n");
printf("4 - Close Tournament (determine winner)\n");
printf("5 - Quit Program\n\n");
printf("Please select a menu option: ");
if (scanf("%d", &option) != 1) /* check scanf() return value for input errors */
{
/* handle input error */
return -1;
}
} while (option < 1 || option > 5); /* check the range of option ( 1 - 5) */
return option; /* finally return the final correct option */
}
int main(void)
{
int n = mainMenu(); /* save the result to n */
/* your code */
return 0;
}

How to execute the second function in C?

Whenever I enter the choice of 2, it does not execute the view_list() function. Instead it start it from first function which is new_acc(). Also the else is not working. How to solve this problem?
#include <stdio.h>
#include <stdlib.h>
int new_acc();
int view_list();
int main(){
int one=1, two=2;
int new_account, list;
printf("%d. Create new account\n",one);
printf("%d. View customers list\n",two);
printf("Enter you choice: ");
if (scanf("%d",&one)){new_account = new_acc();} // calling a function
else if (scanf("%d",&two)){list = view_list();} // calling a function
else {printf("Sorry this is not the correct option"); break;}
return 0;
}
int new_acc(){
char name;
printf("Enter your name: ");
scanf("%s",&name);
return 0;
}
int view_list(){
printf("view list");
return 0;
}
The return value of scanf() is the number of values it returns, not the actual value it self. Code should be:
int value = 0;
scanf("%d",&value);
if(value == one){new_account = new_acc();}
else if (value == two){list = view_list();}
else {printf("Sorry this is not the correct option"); break;}
Other recommendations:
The final break is not doing anything;
Indent your code it makes it much easier to read:
int value =0;
scanf("%d",&value);
if(value == one)
{
new_account = new_acc();
}
else if (value == two)
{
list = view_list();
}
else
{
printf("Sorry this is not the correct option");
}
The return value of scanf() is number of data read.
printf("Enter you choice: ");
if (scanf("%d",&one)){new_account = new_acc();} // calling a function
else if (scanf("%d",&two)){list = view_list();} // calling a function
else {printf("Sorry this is not the correct option"); break;}
should be like
printf("Enter you choice: ");
if (scanf("%d",&one)) != 1) { puts("input read error"); return 1; }
if (one == 1){new_account = new_acc();} // calling a function
else if (one == 2){list = view_list();} // calling a function
else {printf("Sorry this is not the correct option"); return 1;}
or
printf("Enter you choice: ");
if (scanf("%d",&one)) != 1) { puts("input read error"); return 1; }
switch (one) {
case 1: new_account = new_acc(); break; // calling a function
case 2: list = view_list(); break; // calling a function
default: printf("Sorry this is not the correct option"); break;
}
By the way, executing your new_acc() is dangerous.
%s specifier will accepts positive-length string while your buffer has space for only one character.
Even input of one-character string will cause buffer overrun because there will be terminating null character.
It should be like
int new_acc(){
char name[1024]; /* allocate an array */
printf("Enter your name: ");
scanf("%1023s",name); /* specify length limit (buffer size - 1 (terminating null character)) to avoid buffer overrun */
return 0;
}

Why is my static stack not working?

static stack implementation
this is also not deleting according to the lifo principle
static stack implementation:
it is not taking name for the second time
this is the new code now tell me why is it not working
please help
typedef struct student {
char name[20];
int roll;
int age;
} mystruct;
#define size 40
int top;
static mystruct s[size];
void push()
{
if (top == size - 1) {
printf("\noverflow"); //
} else {
printf("\nenter the name of the student");
gets(s[top].name);//not taking name for d 2 time
printf("\nenter the roll number");
scanf("%d", &s[top].roll);
printf("\nenter the age of the student");
scanf("%d", &s[top].age);
++top;
}
}
void pop()
{
if (top == -1)
{
printf("\nunderflow");
} else {
printf("%s", s[top].name);
printf("%d", s[top].roll);
printf("%d", s[top].age);
printf("\npopped");
--top;
}
}
void display()
{
int i;
if (top == -1) {
printf("\nstack is empty");
} else {
for (i = top; i > 0; i--) {
printf("\nthe name of the student is%s", s[top].name);
}
printf("\nthe roll no of the student is%d", s[top].roll);
printf("\nthe age of the student is%d", s[top].age);
}
}
main()
{
top = -1;
char ch;
while (1) {
printf("\nwelcome to static stack menu");
printf("\n1.PUSH\n2.POP\n3.DISPLAY\n0.EXIT");
printf("\nplease enter your choice\n");
ch = getche();
if (ch == '0') {
break;
}
switch (ch) {
case '1':
push();
break;
case '2':
pop();
break;
case '3':
display();
break;
default:
printf("choice not valid");
break;
}
}
}
The first problem I noticed was that top is initialized to -1. Trying to access the member data of s[top] when top is initialized to -1 will result in unpredictable behavior.
I would suggest changing the line
top = -1;
to
top = 0;
That changes the basic assumption you have made in push, pop, and display about when the stack is empty and when it is full. Instead of checking if ( top == -1 ), you have to now check if (top == 0 ). Instead of checking if ( top == size - 1 ), you have to now check if ( top == size ).
In pop, you have to use top-1 instead of top.
The for loop in display is not scoped correctly. You need to use:
for (i = top-1; i >= 0; i--) {
printf("\nthe name of the student is %s", s[i].name);
printf("\nthe roll no of the student is %d", s[i].roll);
printf("\nthe age of the student is %d", s[i].age);
}
Also, reading the options for the menu and reading the subsequent input is little bit tricky.
After you read the menu option, you have to make sure that you eat up all the input until the next newline. Otherwise, gets() will read everything after your menu option until the end of the line. If you typed 1 for the menu and then typed Return/Enter, the name will be automatically accepted as "\n". Hence, I suggest the lines:
printf("\nwelcome to static stack menu");
printf("\n1.PUSH\n2.POP\n3.DISPLAY\n0.EXIT");
printf("\nplease enter your choice\n");
ch = fgetc(stdin);
/* Skip till the end of line is read. */
while ( fgetc(stdin) != '\n' );
Also, after you read the age of the object, you have to eat everything up to the newline. Otherwise, the newline character is read in as the choice for the next menu option.
scanf("%d", &s[top].age);
/* Skip till the end of line is read. */
while ( fgetc(stdin) != '\n' );
Here's the fully working file. I have replaced gets by fgets and getche by fgetc.
#include <stdio.h>
#include <string.h>
typedef struct student {
char name[20];
int roll;
int age;
} mystruct;
#define size 40
int top;
static mystruct s[size];
void push()
{
if (top == size) {
printf("\noverflow"); //
} else {
printf("\nenter the name of the student: ");
fgets(s[top].name, 20, stdin);//not taking name for d 2 time
// The newline character is part of s[top].name when fgets is
// finished. Remove that.
s[top].name[strlen(s[top].name)-1] = '\0';
printf("\nenter the roll number: ");
scanf("%d", &s[top].roll);
printf("\nenter the age of the student: ");
scanf("%d", &s[top].age);
/* Skip till the end of line is read. */
while ( fgetc(stdin) != '\n' );
++top;
}
}
void pop()
{
if (top == 0)
{
printf("\nunderflow");
} else {
printf("%s, ", s[top-1].name);
printf("%d, ", s[top-1].roll);
printf("%d", s[top-1].age);
printf("\npopped");
--top;
}
}
void display()
{
int i;
if (top == 0) {
printf("\nstack is empty");
} else {
for (i = top-1; i >= 0; i--) {
printf("\nthe name of the student is %s", s[i].name);
printf("\nthe roll no of the student is %d", s[i].roll);
printf("\nthe age of the student is %d", s[i].age);
}
}
}
main()
{
top = 0;
char ch;
while (1) {
printf("\nwelcome to static stack menu");
printf("\n1.PUSH\n2.POP\n3.DISPLAY\n0.EXIT");
printf("\nplease enter your choice\n");
ch = fgetc(stdin);
/* Skip till the end of line is read. */
while ( fgetc(stdin) != '\n' );
if (ch == '0') {
break;
}
switch (ch) {
case '1':
push();
break;
case '2':
pop();
break;
case '3':
display();
break;
default:
printf("choice, %c, not valid", ch);
break;
}
}
}
You need to change getche() to getchar()
Note: getche() is a non-standard function.
Maybe this will be useful http://www.delorie.com/djgpp/doc/libc/libc_385.html
Pay attention to implementation note:
"If you can detect the situation when one of the conio functions is called for the very first time since program start, you could work around this problem by calling the gppconio_init function manually"
or just replace it with getchar(). And there meaned conio included.

Resources