Why is my static stack not working? - c

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.

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;
}

Missed scanf and function goes on without it. If I add a space still doesn't work

#include <stdio.h>
struct mychar {
char value;
struct mychar *nextPtr;
};
typedef struct mychar Mychar;
void instructions();
void append(Mychar **, char );
void printlist(Mychar *);
int main(){
instructions();
Mychar *startPtr = NULL;
unsigned int choice;
char newchar;
do {
scanf("%d",&choice);
switch (choice) {
case 1:
printf("\nWrite the character you want to add.");
printf("\n> ");
scanf(" %c", &newchar);
append(&startPtr, newchar);
printlist(startPtr);
break;
case 2:
break;
default:
printf("\nError, try again.\n");
//main();
instructions();
break;
}
} while (choice!=3);
printf("\n\nEnd of run.\n");
}
void instructions(){
printf("\nSelect operation. 1 to add, 2 to remove, 3 to exit.");
printf("\n> ");
}
void append(Mychar **sPtr, char newvalue){
Mychar *newlinkPtr = calloc (1, sizeof(Mychar));
newlinkPtr->value = newvalue;
newlinkPtr->nextPtr = NULL;
Mychar *previousPtr = NULL;
Mychar *currentPtr = *sPtr;
while(currentPtr!=NULL && newvalue > currentPtr->value){
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if (previousPtr){
previousPtr->nextPtr = newlinkPtr;
newlinkPtr->nextPtr = currentPtr;
} else {
*sPtr = newlinkPtr;
}
}
void printlist(Mychar *currentPtr){
printf("\n\nCurrent list:\n");
while (currentPtr!=NULL){
printf("%c", currentPtr->value);
currentPtr = currentPtr->nextPtr;
}
}
Why do I have this behaviour? If I run the program, after I enter 1, it prints the "current list" and leave the scanf input opened, so I can enter the value only after "current list" printed. Also, "current list" should be called only after I enter the character with scanf, since the function printlist is AFTER the scanf... but actually this is what happens:
Select operation. 1 to add, 2 to remove, 3 to exit.
> 1
Write the character you want to add.
> a
Current list:
ab
Write the character you want to add.
>
Current list:
abc
Write the character you want to add.
>
Current list:
abcd
Write the character you want to add.
>
Current list:
abcd
The lesson to take form this is to always check scanf for 0 return, at the very least, EOF check is also advised, and act accordingly, as for the order of events of your code, it's not quite there, with some tweaks you can have a nice, bad input proof, I/O sequence:
void clear_stdin() { //stdin buffer clearing function
int c;
while ((c = getchar()) != '\n' && c != EOF){}
}
do {
instructions(); //move inside the loop, user will be prompted in each cycle
while (scanf("%d", &choice) == 0) {
printf("\nError, try again.\n");
instructions();
clear_stdin(); // if input fails clear the buffer
}
clear_stdin(); // clear the buffer for 1hjh type input
switch (choice) {
case 1:
printf("\nWrite the character you want to add.");
printf("\n> ");
while (scanf(" %c", &newchar) == 0) { //this can be a pattern
clear_stdin(); //see #ismick comment
} //
clear_stdin(); //
append(&startPtr, newchar);
printlist(startPtr);
break;
case 2:
break;
case 3:
printf("\n\nEnd of run.\n"); //if you dont have a case default will catch 3
break;
default:
printf("\nError, try again.\n");
break;
}
} while (choice != 3);

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;
}

Bugs in C Switch Menu using a Char as Choice, Won't Read in fgets name

Im basically Writing a program that creates, reads, updates and
deletes records in a binary file.
Everything compiles correctly, no syntax errors, but I do have some
bugs.
KNOWN BUGS
1.) Imputing any strings does not work, using fgets
2.) Ctrl-D Does Work but outputs a 'default' error before it exits.
3.) Update does not work (Not my main issue at the moment as the others are more important for now.)
4?) I'm not sure if the menu is working how it's supposed to work. I
think the do while is correct, since in the menu if I select and hit
CTRL-D it does exit the program. Just wanna be sure.
Right now I just want to know why, It is skipping the courseName in
the inputs function.
Here is my code thus far
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
typedef struct{
char courseName [64];
char courseSched [4];
unsigned int courseHours;
unsigned int courseSize;} COURSE;
FILE *pfileCourse;
int courseNumber = 0;
//Prototypes
void inputDetails(COURSE *c);
void readCourseRecord();
void createCourseRecord();
void print_menu();
void modifyCourseInfo();
void deleteCourse();
void display(COURSE c);
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
char choice; // this is the choice
printf("Enter one of the following actions or press CTRL-D to exit\n");
printf("C - Create a new course record\n");
printf("R - Read an existing course record\n");
printf("U - Update an existing course record\n");
printf("D - Delete an existing course record\n");
do{
choice = getchar();
switch(choice) {
case 'c':
case 'C':
printf("YOU PICKED C for Create\n");
createCourseRecord();
break;
case 'r':
case 'R':
printf("This is Choice R\n");
readCourseRecord();
break;
case 'u':
case 'U':
printf("Here is where you update an existing course\n");
modifyCourseInfo();
break;
case 'd':
case 'D':
printf("here is where you Delete an existing course record\n");
deleteCourse();
break;
default:
printf("Wrong Choice!\n");
}
}while(choice != EOF);
return 0;
}
void createCourseRecord() {
COURSE data;
pfileCourse = fopen("courses.dat", "ab");
printf("Please Enter The Details of The Course\n");
inputDetails(&data);
fwrite(&data, sizeof(data), 1, pfileCourse);
fclose(pfileCourse);
printf("Course Has Been Created!\n");
}
void inputDetails(COURSE *c) {
printf("Enter a course number: \n");
scanf("%d", &courseNumber);
printf("Enter a Course Name: \n");
fgets(c->courseName, sizeof(courseName), stdin);
printf("Enter the course schedule (MWF or TR): \n");
fgets(c->courseSched, 4, stdin);
fflush(stdin);
printf("Enter the course credit hours: \n");
scanf("%d",&c->courseHours);
fflush(stdin);
printf("Enter Number of Students Enrolled: \n");
scanf("%d",&c->courseSize);
return;
}
void readCourseRecord(){
COURSE data;
int flag = 0;
int readCourseNumber = 0;
printf("Please Enter a Course Number to Display\n");
scanf("%d", &readCourseNumber);
fflush(stdin);
pfileCourse = fopen("courses.dat", "rb");
while((fread(&data, sizeof(data), 1, pfileCourse)) > 0) {
if(readCourseNumber == courseNumber)
{
display(data);
flag = 1;
}
}
fclose(pfileCourse);
if(flag == 0)
printf("Course not Found!\n");
}
void deleteCourse(){
int newCourseNum;
COURSE data;
FILE *file2;
printf("Please Enter The Course You Wish You Delete\n");
scanf("%d", &newCourseNum);
pfileCourse = fopen("courses.dat", "rb");
file2 = fopen("temp.dat", "wb");
rewind(pfileCourse);
while((fread(&data, sizeof(data), 1, pfileCourse)) > 0)
{
if(courseNumber != newCourseNum)
{
fwrite(&data, sizeof(data), 1, file2);
}
}
fclose(file2);
fclose(pfileCourse);
remove("courses.dat");
rename("temp.dat", "courses.dat");
printf("%d was Successfully deleted\n", newCourseNum);
}
void modifyCourseInfo()
{
COURSE data;
int newCourseNum, found = 0;
printf("Modify\n");
printf("Please Enter The Course You Wish You Modify\n");
scanf("%d", &newCourseNum);
pfileCourse = fopen("courses.dat", "rb+");
while ((fread(&data, sizeof(data), 1, pfileCourse)) > 0 && found == 0)
{
if (courseNumber == newCourseNum)
{
display(data);
printf("Please Enter New Details\n");
inputDetails(&data);
fseek(pfileCourse, - (long)sizeof(data), 1);
fwrite(&data, sizeof(data), 1, pfileCourse);
printf("Course Updated\n");
found == 1;
}
}
fclose(pfileCourse);
if(found == 0)
printf("ERROR: course not found\n");
}
void display(COURSE c){
printf("courseNumber:\t %d\n", courseNumber);
printf("courseName:\t %s\n",c.courseName);
printf("courseSched:\t %s\n",c.courseSched);
printf("courseName:\t %d\n",c.courseHours);
printf("courseSize:\t %d\n",c.courseSize);
}
It doesn't skip courseName, courseName just gets value '\n' because scanf function stops reading your input BEFORE white space. Scanf ignores any whitespace characters encountered before the next non-whitespace character. So you can just add
scanf("%d[^\n]", &courseNumber);
getchar();
after every scanf you have but I'd recommend you to use fgets function for every interactive input.

C program switch statement

I'm new to programming in C. I have a quick question about Switch Statements.
I have a menu that presents a list of options like so:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct Video {
char name[1024]; // Yvideo name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct Video Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void savequit();
void load();
void branching(char);
void menu();
int main()
{
char ch;
load(); // load save data from file
printf("\n\nWelcome\n");
do {
menu();
fflush(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
savequit();
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
so far entering 'i' (for inserting a new entry) and q (for save and quit) work perfectly. However every time I enter 'p' I get the default case. (Error: Invalid Input. Please try again...). What is it that I am doing wrong? I believe the syntax for the switch is correct? I've tried changing the 'p' to a different letter and I still got the the default case. Here is my printall() method if that helps...
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nName: %s", Collection[i].name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
What about something like:
char b[5];
do {
menu();
if(fgets(b,5,stdin)==NULL)
return -1;
ch = tolower(b[0]); // read a char, convert to lower case
while(strlen(b)>=4&&b[3]!='\n'){
check=fgets(b,5,stdin);
if(check==NULL)
return -1;
}
branching(ch);
} while (ch != 'q');
You can output the invalid char in your default case. That may help you understand how your input are handled.
default:
printf("\nError: Invalid Input ('%c'). Please try again...", option);
break;
fflush(stdin) is undefined as fflush is define only for output streams. To clear the newline char, you can simply use another getchar().
Try this for the loop part:
do {
menu();
ch = tolower((unsigned char)getchar());
getchar();
branching(ch);
} while (ch != 'q');

Resources