I am learning stacks right now and I decided to try to make a little program involving the stack from Magic the Gathering rules, which also follows a LIFO order.
The user asked whether they would like to
play a spell (push)
resolve a spell (pop) or
exit.
Now the tricky part is that I am trying to allow the elements of the stack to be multiple words each. This has been causing A LOT of problems.
I can input a word and print it outside the while(1) loop but if I put it inside everything goes haywire. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct {
char item[SIZE];
int top;
} stack;
void init(stack*);
void push(stack*, char[]);
char pop(stack*);
void init(stack* st) {
st->top = -1;
}
void push(stack* st, char* value) {
if (st->top == SIZE - 1) {
printf("STACK OVERFLOW\n");
return;
}
st->top++;
strcpy(st->item[st->top], value);
}
char pop(stack* st) {
if (st->top == -1) {
printf("STACK UNDERFLOW\n");
return -1;
}
char value;
strcpy(value, st->item[st->top]);
st->top--;
return value;
}
int main() {
stack st1, st2;
int choice;
char val[20];
init(&st1);
init(&st2);
printf("You have priority. What would you like to do?\n\n");
printf("1. Cast a spell\n2. Resolve the next spell\n3. Pass priority\n\n");
while (1) {
scanf("%d", &choice);
switch (choice) {
case 1:
printf("What is the spell?\n\n");
scanf("%[^\n]s", val);
printf("%s", val);
push(&st1, val);
case 2:
strcpy(val, pop(&st1));
printf("%s resolves.\n\n", val);
case 3:
exit(0);
}
}
return 0;
}
The reason you would be getting errors is that because of the type conversions.
char pop(stack* st) {
if (st->top == -1) {
printf("STACK UNDERFLOW\n");
return -1;
}
char value;
strcpy(value, st->item[st->top]);
st->top--;
return value;
}
The first thing, you don't need to pass the address when dealing with the arrays. The another thing is that you are trying to copy a whole string into a single character variable. So, there are so much type conversion problems in your code.
I suggest you to make the functions of void data type and provide the functionality within the block of the function. Just call the pop function with top value as an argument, and print the string within the function that you are popping.
Stack is a zero order data structure so it doesn't require inputs for popping purpose.
Related
I have tried creating a program that uses simple stack functions like push to add the contents of the statement onto a stack from where I then print out each character and then reverse the statement. I have used the '.' and '->' member access variables to change the contents of the struct based stack. Upon compiling it prints out the original statement, but after that it gives a segmentation error, saying I am attempting to dereference an uninitialised pointer. Can someone guide me as to how I should solve this problem as it isn't stating the line I have made the problem either.
#include <stdio.h>
#define MAX 1000
#define FULL (MAX - 1)
#define EMPTY -1
typedef struct stack {char s[MAX]; int top;} stack;
int top = EMPTY;
int isFull()
{
if(top == FULL)
return 1;
else
return 0;
}
int isEmpty()
{
if(top == EMPTY)
return 1;
else
return 0;
}
void reset(stack *stk)
{
stk -> top = EMPTY;
}
void push(char c, stack *stk)
{
stk -> top++;
(*stk).s[(*stk).top] = c;
}
char pop(stack *stk)
{
return (*stk).s[(*stk).top--];
}
void print(stack *stk)
{
int i;
while(1)
{
if(isEmpty())
{
printf("Stack underflow\n");
break;
}
for(i = 0; i <= top; i++)
{
printf("%c\n", (*stk).s[i]);
}
printf("\n");
return;
}
}
void reverse(stack *stk)
{
int i;
while(1)
{
if(isEmpty())
{
printf("Stack underflow\n");
break;
}
for(i = top; i >= 0; i--)
{
printf("%c", (*stk).s[i]);
}
printf("\n");
return;
}
}
char peek(const stack *stk)
{
while(1)
{
if(isEmpty())
{
printf("Stack underflow\n");
break;
}
return (*stk).s[(*stk).top];
}
}
int main()
{
stack stack_of_char;
char *str = "i am otto am i";
int i;
reset(&stack_of_char);
printf("original is: %s\n", str);
while(str[i] != '\0')
{
push(str[i++], &stack_of_char);
}
print(&stack_of_char);
reverse(&stack_of_char);
return 0;
}
There are several issues with your program. Let's begin with the global variable top. This is causing problems because on the one hand you have a stack struct responsible for maintaining a stack, and that has its own top. But then you have this global which you're not even using anywhere. It's almost like you added it to get around compiler errors that you didn't understand ;)
So let's ditch that, and fix your stack functions. I'm rearranging the parameters of the push function so that the stack is the first argument. This is a bit more conventional.
typedef struct stack {
char s[MAX];
int top;
} stack;
int isFull(stack *stk)
{
return stk->top == FULL;
}
int isEmpty(stack *stk)
{
return stk->top == EMPTY;
}
void reset(stack *stk)
{
stk->top = EMPTY;
}
void push(stack *stk, char c)
{
if (isFull(stk))
return;
stk->s[++stk->top] = c;
}
char pop(stack *stk)
{
if (isEmpty(stk))
return '\0';
return stk->s[stk->top--];
}
For the pop function, I arbitrarily return a NUL character if the stack is empty, because something must be returned. But really, you should never call this function if the stack is empty.
Let's look at your display functions now. The first thing I notice is that these are really convoluted. There is no need for that complexity. Look here:
void print(stack *stk)
{
for(int i = 0; i <= stk->top; i++)
{
printf("%c\n", stk->s[i]);
}
printf("\n");
}
void reverse(stack *stk)
{
for(int i = stk->top; i >= 0; i--)
{
printf("%c", (*stk).s[i]);
}
printf("\n");
}
char peek(const stack *stk)
{
if (isEmpty(stk))
{
printf("Stack empty!\n");
return '\0';
}
return stk->s[stk->top];
}
And so all that remains is a little tidy-up of your main function, and adjust the parameter order for push.
int main()
{
const char *str = "i am otto am i";
printf("original is: %s\n", str);
stack stack_of_char;
reset(&stack_of_char);
for (int i = 0; str[i]; i++)
{
push(&stack_of_char, str[i]);
}
print(&stack_of_char);
reverse(&stack_of_char);
}
Note also that you shouldn't really be walking over your stack with those functions. The typical way you would use a stack to reverse something is to push values onto it and then pop them off. So, you can print the string in reverse like this:
// Pop characters from stack to print in reverse
while (!isEmpty(&stack_of_char))
{
char c = pop(&stack_of_char);
putc(c, stdout);
}
putc('\n', stdout);
Without initialization, the integer will be a random value. It is the root cause of the memory access error.
You will need to initialize the variable properly. In main function, instead of
int i;,
you should use
int i = 0;.
Assume that you plan to access the value starting from index 0.
Now I have an input consists of a random string with '(' and ')'. I want to push these parentheses into a stack called "balance". But after I input, the program would terminate, and there was nothing in the stack. How can I fix this?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 1000
struct stack
{
int top;
char items[STACKSIZE];
};
void push(struct stack *pb, char x)
{
if(pb->top==STACKSIZE)
printf("The stack is full\n");
else
pb->items[pb->top++]=x;
}
int main()
{
while(1)
{
struct stack balance; //the stack called "balance"
struct stack *b; //the pointer of stack
char line[STACKSIZE]; //input
scanf("%s", line);
if(!strcmp(line, "-1")) //program stops when only "-1"
break;
b->top=0; //initializing top value
for(int i=0;i<STACKSIZE-1;i++)
{
if(line[i]=='(' || line[i]==')') //push '(' and ')' in the input to the stack
push(b, line[i]);
}
printf("test"); //can't reach this line
printf("%s\n", b->items);
}
return 0;
}
For some reason, you're using b as a pointer to the stack, instead of &balance itself. This is not wrong, but you must initialize b so it really points to the struct. So, instead of:
struct stack *b;
You should have:
struct stack *b = &balance;
Another potential problem is that you're reading until i reaches STACKSIZE. This is wrong, since you don't know whether the input is going to reach that length, and if it does not, then you're reading ahead of the end of line.
So, instead of:
for(int i=0;i<STACKSIZE-1;i++)
{
You should have:
for(int i=0;line[i] != '\0';i++)
{
BTW, you don't need to define ("redefine for each iteration"), all your locals inside the loop. That's is actually not going to happen, since the optimizer will move them out, but anyway.
Talking of potential problems, it is always a bad idea to have and infinite loop. Define exactly what is the exit condition, and you'll be in the safe side. You can even define something exceptional to happen and call break in that case, but not as the common rule.
You're reading input, and in this case something really common is the read-ahead technique.
int input_status = scanf("%s", line);
while(input_status != EOF
&& strcmp(line, "-1"))
{
// more things...
input_status = scanf("%s", line);
}
This way, each time you're testing the exit condition, you've just read and check whether the end condition ("-1" at input) or there is simply not more input (scanf returns EOF).
Here comes the complete code:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 1000
struct stack
{
int top;
char items[STACKSIZE];
};
void push(struct stack *pb, char x)
{
if(pb->top==STACKSIZE)
printf("The stack is full\n");
else
pb->items[pb->top++]=x;
}
int main()
{
struct stack balance; //the stack called "balance"
struct stack *b = &balance; //the pointer of stack
char line[STACKSIZE]; //input
int input_status = scanf("%s", line);
while(input_status != EOF
&& strcmp(line, "-1"))
{
b->top=0; //initializing top value
for(int i=0;line[i] != '\0';i++)
{
if(line[i]=='(' || line[i]==')') //push '(' and ')' in the input to the stack
push(b, line[i]);
}
printf("test"); //can't reach this line
printf("%s\n", b->items);
input_status = scanf("%s", line);
}
return 0;
}
This is a simple program to implement stack using structure pointers. However on running the code my program exits without showing any error.
#include<stdio.h>
#include<stdlib.h>
#define maxsize 5
struct s
{
char array[maxsize];
int top;
};
typedef struct s stack;
int insert(stack *p)
{
char ch;
/*if(p->top==NULL)
{
p->top=-1;
}*/
if(p->top>=maxsize-1)
{
printf("Stack overflows on insertion\n");
}
else
{
printf("Enter the character to be inserted : ");
scanf("\n%c",&ch);
p->top++;
p->array[p->top]=ch;
}
}
int delete(stack *p)
{
if(p->top==-1)
{
printf("Stack underflows on deletion\n");
}
else
{
p->top--;
}
}
int display(stack *p)
{
int i;
if(p->top==-1)
{
printf("Stack is empty\n");
}
else
{
for(i=0;i<=p->top;i++)
{
printf("%c",p->array[i]);
}
printf("\n");
}
}
int main()
{
int c;
stack *p;
p->top=-1;
while(1)
{
printf("1--> INSERT 2--> DELETE 3--> DISPLAY\n");
scanf("%d",&c);
switch(c)
{
case 1:
insert(p);
break;
case 2:
delete(p);
break;
case 3:
display(p);
break;
default:
printf("ERROR : Invalid Choice");
}
}
}
This program contains three functions to push, pop and display the elements in the stack, and the last main function is from where the function call is executed.
The program gets compiled successfully with 0 errors, but while running it exits without displaying anything.
When you declare:
stack *p;
It is just declaring a pointer. You need to allocate memory if you want to use the pointer - as you do here (this will segfault):
p->top=-1;
Update the first line to the following:
stack *p = malloc(sizeof(stack));
malloc() will allocate the requested memory for use - anything dynamically allocated should also be free()'d
I have a program that gives me the error [Error] conflicting types for 'empty' and [Error] conflicting types for 'full'. I have a hunch that it has something to do with the enum bool use (this is the first time I have tried using it). I've looked at other similar questions, that do not help me, were the issue is forgetting to declare a prototype in the program. I have made sure to write my functions before of main.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char** data; // array of strings represnting the stack
int top; // -1 if empty
int size;
}Stack;
typedef enum { FALSE, TRUE } bool;
Stack* create(){
Stack *s;
s = (Stack*)malloc(sizeof(Stack));
s->top = -1;
s->size = 10;
s->data = (char**)malloc(s->size*sizeof(char*));
return s;
}
void deleteStack(Stack* ps){
while(ps->top = 0){
free(ps->data[ps->top]);
ps->top--;
}
free(ps->data);
}
void push(Stack* ps, char* str, int* size){ //may need to call realloc bfr completing push
if(full(ps)){
char **temp = realloc(ps->data, ps->size*sizeof(char*));
ps->data == temp;
printf("Stack capacity has grown from %d to %d elements\n", ps->size**size, ps->size**(++size));
}
ps->data[++ps->top] = str;
}
char* pop(Stack* s, int* i){ //returns the string that was removed from the stack
if(empty(s))
return NULL;
printf("#of elements after popping: %d\tstring popped: %s\n", --i, s->data[s->top]);
return s->data[s->top--];
}
bool empty(Stack s){ // returns true if stack has no elements else false
if(s.top == -1)
return TRUE;
return FALSE;
}
bool full(Stack s){ //returns true if no more room else false
if(s.top == s.size-1)
return TRUE;
return FALSE;
}
int main(int argc, char *argv[]){
printf("Assignment 2 Problem 1 by Jasmine Ramirez\n");
FILE * input = fopen("data_a2.txt", "r");
if(input == NULL){
printf("File %s not found.\n", "data_a2.txt");
return -1;
}
Stack *s;
s = create();
char str[255];
int i = 0, size = 1;
while(fscanf(input, "%[^\n]", str) == 1){
i++;
if(strcmp(str, "pop") == 0){
i--;
pop(s, &i);
//printf("#of elements after popping: %d\tstring popped: %s", i, temp);
}
else{
push(s, str, &size);
}
}
deleteStack(s);
fclose(input);
return 0;
}
This is the input: (just in case)
to
sure
Be
pop
pop
pop
you
stop
won't
that
feeling
a
have
I
but
on
go
to
much
Not
right
Brilliant
happens
drink
pop
something
and
both
them
Ring
Story
ovaltine
your
pop
pop
Christmas
A
--
pop
pop
pop
pop
Ideas? Or am I just completely off?
In function push() you have:
void push(Stack* ps, char* str, int* size){
if(full(ps)){
…
This implicitly declares full as a function with indeterminate argument list returning an int. You later define it as returning a bool — these are different types, and hence you get the error.
Declare or define full before you use it. Similar comments apply to empty, but there's an additional problem in that code pointed out by Vlad from Moscow in his answer.
If you use GCC, use options such as -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Wold-style-declaration (or as many of them as your version supports) to ensure that you don't run into this again.
The names empty and full are used before their declarations. For example
char* pop(Stack* s, int* i){ //returns the string that was removed from the stack
if(empty(s))
^^^^^^^^
return NULL;
printf("#of elements after popping: %d\tstring popped: %s\n", --i, s->data[s->top]);
return s->data[s->top--];
}
bool empty(Stack s){ // returns true if stack has no elements else false
if(s.top == -1)
return TRUE;
return FALSE;
}
You must to declare them before their usage.
And moreover for example the function empty has the parameter of the type Stack while is called with an argument of the type Stack *
Let's say that I have the following code in C that represents a stack :
#define MAX 1000
int arr[MAX];
static int counter = 0;
isstackempty()
{
return counter <= 0;
}
void push(int n)
{
if (counter >= MAX) {
printf("Stack is full. Couldn't push %d", n);
return;
}
arr[counter++] = n;
}
int pop(int* n)
{
if(isstackempty() || n == 0) {
printf("Stack is empty\n");
return 0;
}
*n = arr[--counter];
return 1;
}
The above code is in a stack.c file and the function prototypes are in a header.
Now, coming from a C# and OO background, if I would want to separate stacks to use in my application, in an OO language I would create two instances. But in C, how do you handle such a scenario?
Say I want to use two separate stacks in my C code...with the above code, how would I go about it?
Put the array arr inside a struct.
struct stack {
int arr[MAX];
...
}
This struct becomes your instance. You can then declare it on the stack:
struct stack mystack;
or on the heap using malloc:
struct stack *mystack = malloc(sizeof(struct stack));
You also need to pass a pointer to the instance as the first parameter to any function manipulating the instance.
The C way to do this is to wrap up all the state for your 'object' into a struct, and then explicitly pass it into all the functions that operate on stacks, so it should be:
typedef struct _stack {
int arr[MAX];
int counter;
} stack;
int isstackempty(stack *s)
{
return s->counter <= 0;
}
int push(stack *s, int n)
{
if (s->counter >= MAX) {
printf("Stack is full. Couldn't push %d", n);
return -1;
}
arr[s->counter++] = n;
return 0
}
int pop(stack *s, int *n)
{
if(isstackempty(s) || n == 0) {
printf("Stack is empty\n");
return -1;
}
*n = arr[--s->counter];
return 0;
}
The issue with your example is you're writing the function definitions like we have a class-based object structure, which C doesn't have. The easiest way to think about how it's done in C is that you're writing methods that require you to explicitly pass in the 'this' parameter.
Also you can have the equivalent of constructors and destructors, which can further abstract your 'object'.
stack* newStack() {
stack* s = malloc(sizeof(stack));
s->counter = 0;
return s;
}
void freeStack(stack* s) {
free(s);
}
One (extremely simplistic) way of going about it is to define a struct that represents a stack:
typedef struct {
int arr[MAX];
int counter = 0;
} myStack;
and then rewrite push() and pop() to operate on an instance of myStack:
int push(myStack *s, int n)
{
if (s->counter >= MAX) {
printf("Stack is full. Couldn't push %d", n);
return -1;
}
s->arr[(s->counter)++] = n;
return s->counter;
}
int pop(myStack *s, int* n)
{
if(0 == s->counter || 0 == n) {
printf("Stack is empty\n");
return -1;
}
*n = s->arr[--(s->counter)];
return 1;
}
(Also added a meaningful return value and error value to push(). YMMV.)
I hope you find this paper useful. It gives more than one answer to your question :)
Sixteen Ways to Stack a Cat
Simply make your 'this' pointer explicit:
struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);
My answer to this other question has a complete working example of an OO data buffer structure in C.
A dynamically allocated structre-per-instance is the right way to go. A point of detail - if you are writing a more generally used API it is probably a good idea to engage in data hiding for better abstraction.
The simplest way of doing this is keep the definition of the internal structure in the C file (or a private header file), and typedef a void pointer to (e.g.) 'stack_handle_t'. It is this type that is returned from your 'constructor' and is passed back in to each other function.
The implementation is aware that the value of the handle is in fact a pointer to a structure and at the beginning of each function simply does:
int pop(stack_handle_t handle, int* n)
{
stack *p_stack = (stack *)handle;
...
Even better than that is to use an internally allocated identifier instead, whether this is an index into an array of these structs or simply an identifier which can be matched against one of a (linked?) list of structs.
Obviously all this is irrelevant if its only for use internal to your project, in those circumstances it is just making unnecessary work and over-complication.