Implement a stack by using a pointer to pointer - c

I am implementing a small program to exercise with double pointers
This is the main program:
#include <stdio.h>
#include "serial.h"
#include "stack.h"
int main(void) {
serial_init();
/* Array to hold stack entries */
int stack[10]={0};
/* Stack pointer */
int *stack_p = stack;
/* Code to call the functions */
push(&stack_p, 1);
push(&stack_p, 2);
push(&stack_p, 3);
push(&stack_p, 4);
printf("popped value: %d\r\n", pop(&stack_p));
printf("popped value: %d\r\n", pop(&stack_p));
printf("popped value: %d\r\n", pop(&stack_p));
printf("popped value: %d\r\n", pop(&stack_p));
}
void push(int **sp, int value) {
/* Implement it */
}
int pop(int **sp) {
/* Implement it */
}
I have implemented the push function it seems ok. However, the pop return back just the last element and then 10
void push(int **sp, int value) {
/* implemented it*/
int *pt;
pt=&value; // Store the value to the pointer
printf("Push value is is %d\r\n", *pt);
sp = &pt; // associate the pointer to the pointer of pointer
++(*pt);
}
int pop(int **sp) {
/* implemented it */
int value;
int *pt;
pt=&value;
sp = &pt;
*pt--;
return value;
}

Your push and pop functions are overly complicated and totally wrong:
You want this:
void push(int **sp, int value) {
**sp = value; // put value onto top of the stack
(*sp)++; // increment stack pointer
}
int pop(int **sp) {
(*sp)--; // decrement stack pointer
return **sp; // return value which is on nthe op of the stack
}
Your wrong code for push with explanations in comments:
void push(int **sp, int value) {
int *pt;
pt=&value; // here you put the pointer to the local variable value
// into pt, but local variables disappear as soon
// as the function has finished
// the printf is the only thing one more or less correct
// but you could just print directly 'value' like this:
// printf("Pushed value is %d\r\n", value);
//
printf("Push value is is %d\r\n", *pt);
sp = &pt; // this only assigns the pointer to the local variable pt to
// the local variable sp
++(*pt); // here you increment actually the local variable
// value which is pointless
}
By the way: the initialisation to zero of the whole stack is not necessary, although it might help during the debugging process. So you can write the declaration of the stack like this:
int stack[10]; // no initialisation necessary
Exercise for you:
Explain the exact reason why it is not necessary to initialize all elements of the stack to zero.

Related

Why am I getting an error when I try to use push and pop function?

The question asks us to "Write the program by completing the main function that calls the push function at least three times, then prints out the updated stack, then calls the pop function and prints out the updated stack again."
The code tells me that the compilation failed due to the following reasons:
Line 10 | {
Which to me does not make sense. I tried removing it but it gives other errors
Additionally, the code gives a warning saying " warning: array ‘stack’ assumed to have one element" Which I have no idea what that means.
This is the code:
#include <stdio.h>
#define STACK_EMPTY '0'
#define STACK_SIZE 20
char stack[], item;
int *top, max_size;
void
push(char stack[], char item, int *top, int max_size),
{
if (*top < max_size-1)
{
--(*top);
stack[*top] = item;
}
}
char
pop (char stack[], /* input/output - the stack */
int *top) /* input/output - pointer to top of stack */
{
char item; /* value popped off the stack */
if (*top >= 0)
{
item = stack[*top];
--(*top);
}
else
{
item = STACK_EMPTY;
}
return (item);
}
int
main (void)
{
char s [STACK_SIZE];
int s_top = -1; // stack is empty
if (*top <= -1)
{
item = STACK_EMPTY;
}
return (0);
}
Issue is in how you are handling the top pointer.
you decrement the pointer i.e., --top, NOT the value pointed by it.
Also push should increment it i.e., ++top.
---Here is the corrected code ----
#include <stdio.h>
#define STACK_SIZE 20
#define STACK_EMPTY '0'
char item;
int top_idx = 0;
void
push(char *stack, char item)
{
if (top_idx < STACK_SIZE)
{
stack[top_idx] = item;
top_idx++;
}
}
char
pop (char *stack) /* input/output - pointer to top of stack */
{
char item; /* value popped off the stack */
if (top_idx >= 0)
{
top_idx--;
item = stack[top_idx];
}
else
{
item = STACK_EMPTY;
}
return (item);
}
int
main (void)
{
char s [STACK_SIZE];
push(s,'a');
push(s,'b');
printf("Pop = %c \n",pop(s));
printf("Pop = %c \n",pop(s));
return 0;
}
The error regarding "stack assumed to have one element" is because you put no number between the square brackets char stack[];. I suspect you meant
char stack[STACK_SIZE];

I'm trying to create a stack in c using structures but my push function doesn't work

I'm trying to create a stack in C using structures but the push() function I wrote is acting strangely. I'm sure it is something obvious that I'm missing but I just couldn't figure out what.
#include <stdio.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
void push(STACK* st, int newitem)
{
st->top++;
st->items[st->top] = newitem;
printf("%d", st->items[st->top]);
}
int main()
{
int n = 1;
STACK* st;
printf("test 1\n");
st->top = -1;
push(st, n);
printf("test 2\n");
return 0;
}
DevCpp only compiles but doesn't execute the code. OnlineGDB runs it but only prints the first test.
This is because your variable STACK* st; was never initialized properly.
Some Important Points:
Don't assign -1 to the length (top), 0 would be better
STACK* st; should be just STACK st;
Your function void push(STACK* st, int newitem) should be declared with static linkage.
Write st->top++
Pass st variable by address to the push() function
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
As your total STACK_SIZE is only 50 so, int will be sufficient. But as your STACK_SIZE grows use size_t for your length(top).
use int main(void) { }, instead of int main() { }
NOTE: If STACK_SIZE and top becomes equal means your array is filled completely then further addition of data will lead to Undefined Behavior.
Final Code
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
static void push(STACK* st, int newitem)
{
if(st->top == STACK_SIZE)
{
fprintf(stderr, "stack size reached maximum length\n");
exit(EXIT_FAILURE);
}
st->items[st->top++] = newitem;
printf("%d\n", st->items[st->top - 1]); // we added +1 to `top` in the above line
}
int main(void)
{
int n = 1;
STACK st;
printf("test 1\n");
st.top = 0;
push(&st, n); //pass by address
return EXIT_SUCCESS;
}

C doesn't put data in arrays or varibles

I'm the beginner in C programming< for now I'm using linux and tried both gcc and clang compilers. However, I'm facing the one problem, sometimes C doesn't put data in the array or variable. For example, there is one of my simple codes, that doesn't work completely:
#include <stdio.h>
#define size 10
struct stack{
int structTop;
int elemNum[size];
};
int create (struct stack s);
int full (struct stack s);
void push (int elem, struct stack s);
void main() {
struct stack s1;
struct stack s2;
struct stack s3;
int a = 545;
create(s1);
push(a, s1);
push(5, s1);
push(a, s1);
push(1, s1);
push(6, s1);
push(4, s1);
push(7, s1);
push(8, s1);
int i = 0;
while (i<4){
printf("%d\n", s1.elemNum[i]);
i++;
}
}
int create (struct stack s){
s.structTop = -1;
return 0;
}
int full(struct stack s){
if(s.structTop == size-1) {
return 1;
}
else {
return 0;
}
}
void push(int elem, struct stack s){
if(full(s)){
printf("Stack is full");
}
else {
s.structTop++;
s.elemNum[s.structTop]=elem;
}
}
As output I'm getting data, wich was inside array from the beginning (zeros or random numbers). Also it was only one of the codes, i have couple of larger ones, that have the same problem. Variables and arrays inside them are working 50/50, sometimes yes, sometimes no, even if declarations and functions are the same. Someone told me, that it could be the matter of compiler, but i tried different ones and also have a friend with the same Kali linux as me facing this problem on a different PC.
You need to pass pointers to the struct, i.e. int create (struct stack *s) instead of int create (struct stack s). The same for push. Otherwise, you pass a copy and in the function, you will alter a copy and not the originally passed object from main.
The thing why it sometimes worked, at least partially, is that when passing objects by value, these values will be put temporarily on a stack; It seems that the same object from main had several time been pushed right on the same position on the stack, such that it seemed as if it was always the same object. But - as you recognised - this really occasional.
The signatures of your methods should look as follows:
int create (struct stack *s);
int full (const struct stack *s);
void push (int elem, struct stack *s);
Note that - since passing now pointers - you have to access the elements of s using -> (and not .), e.g. s->structTop = -1 instead of s.structTop = -1; and that you have to pass the address of a stack (not the stack itself, e.g. push(a, &s1) instead of push(a, s1).
Note further that in int full (const struct stack *s), I declared s as const, as the function does not intend to alter any value of the members of s.
#include <stdio.h>
#define size 10
struct stack{
int structTop;
int elemNum[size];
};
int create (struct stack *s);
int full (const struct stack *s);
void push (int elem, struct stack *s);
int main() {
struct stack s1;
int a = 545;
create(&s1);
push(a, &s1);
push(5, &s1);
push(a, &s1);
push(1, &s1);
push(6, &s1);
push(4, &s1);
push(7, &s1);
push(8, &s1);
int i = 0;
while (i<4){
printf("%d\n", s1.elemNum[i]);
i++;
}
}
int create (struct stack *s){
s->structTop = -1;
return 0;
}
int full(const struct stack *s){
if(s->structTop == size-1) {
return 1;
}
else {
return 0;
}
}
void push(int elem, struct stack *s){
if(full(s)){
printf("Stack is full");
}
else {
s->structTop++;
s->elemNum[s->structTop]=elem;
}
}

C array struct function pointer

How do you create a function pointer with struct table such as
static struct {
int pid;
int queue[MAXPROCS];
} semtab[MAXSEMS];
I think I understand how to make OO equivalent in C using function pointer with this post, but how can I do with when my struct is an array. I'm still a little iffy with the syntax.
Would it be something like
static struct {
int pid;
int queue[MAXPROCS];
void (*fncPtr_enqueue)(int) = enqueue;
// or is it void(*enqueue)(semtable[]*) ?
int (*fcnPtr_dequeue)() = dequeue;
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue() { /* code */ }
// then to use it, it would be like this?
void foo() {
semtab[5].enqueue(6);
}
Use
static struct {
int pid;
int queue[MAXPROCS];
void (*fncPtr_enqueue)(int); // This defines a member fncPtr_enqueue
int (*fncPtr_dequeue)(); // Note that you had fcnPtr_ in your post.
// I have fncPtr_ here.
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue() { /* code */ }
Each object in semtab that needs to have valid function pointers needs to be updated.
semtab[0].fncPtr_enqueue = enqueue;
semtab[0].fncPtr_dequeue = dequeue;
You could use:
static struct
{
int pid;
int queue[MAXPROCS];
void (*enqueue)(int);
int (*dequeue)(void);
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue(void) { /* code */ }
void foo(void)
{
semtab[5].enqueue(6);
}
Changes include:
Systematic names for structure member pointers (instead of mixed fncPtr and fcnPtr prefixes).
No attempt to initialize in the structure definition.
Add void to function prototypes to indicate no arguments. In C (and in contrast to C++), an empty pair of brackets (parentheses) means "a function taking an undefined number of arguments, but not one which has a variable argument list with ... ellipsis".
Because of (1), the original invocation is OK. (With the original code, you'd have needed semtab[5].fncPtr_enqueue(6); — or even (*semtab[5].fncPtr_enqueue)(6);)
You would still have to ensure that the function pointers in the table are all initialized.
With GCC and C99 or C11 compilation, you could initialize the array using:
static struct
{
int pid;
int queue[MAXPROCS];
void (*enqueue)(int);
int (*dequeue)(void);
} semtab[MAXSEMS] =
{
[0 ... MAXSEMS-1] = { .enqueue = enqueue, .dequeue = dequeue }
};
The [0 ... MAXSEMS-1] part is a GCC extension. Observe that a space is required after the 0 to avoid problems with the 'maximal munch' rule.
As JS1 mentioned in the comments, it's actually pretty pointless to do this with the example you have, as you're not achieving anything with the indirection if you're not going to vary the value of those pointers.
That being said, here's an example using a stack (because the logic is easier than a queue, and this is a simple example). Note that you must pass a pointer to the stack to each of your member functions, because while C++ member functions have an implicit this argument, C functions never do. You also need to give your struct a name, otherwise you won't be able to refer to it in the abstract, which you need to do.
This program uses the same struct to implement two variations of a stack, one normal one, and one which unnecessarily shouts at you when you push or pop:
#include <stdio.h>
#include <stdlib.h>
enum {
STACKSIZE = 1024
};
struct stack {
int stack[STACKSIZE];
size_t top;
void (*push)(struct stack *, int);
int (*pop)(struct stack *);
void (*destroy)(struct stack *);
};
void stack_push(struct stack * this, int i)
{
if ( this->top == STACKSIZE ) {
fprintf(stderr, "Queue full!\n");
exit(EXIT_FAILURE);
}
this->stack[this->top++] = i;
}
void stack_push_verbose(struct stack * this, int i)
{
stack_push(this, i);
printf("** PUSHING %d ONTO STACK! **\n", i);
}
int stack_pop(struct stack * this)
{
if ( this->top == 0 ) {
fprintf(stderr, "Stack empty!\n");
exit(EXIT_FAILURE);
}
return this->stack[--this->top];
}
int stack_pop_verbose(struct stack * this)
{
const int n = stack_pop(this);
printf("** POPPING %d FROM STACK! **\n", n);
return n;
}
void stack_destroy(struct stack * this)
{
free(this);
}
struct stack * stack_create(void)
{
struct stack * new_stack = malloc(sizeof * new_stack);
if ( !new_stack ) {
perror("Couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
new_stack->push = stack_push;
new_stack->pop = stack_pop;
new_stack->destroy = stack_destroy;
return new_stack;
}
struct stack * stack_verbose_create(void)
{
struct stack * new_stack = stack_create();
new_stack->push = stack_push_verbose;
new_stack->pop = stack_pop_verbose;
return new_stack;
}
int main(void)
{
struct stack * stack1 = stack_create();
struct stack * stack2 = stack_verbose_create();
stack1->push(stack1, 4);
stack1->push(stack1, 3);
stack1->push(stack1, 2);
printf("Popped from stack1: %d\n", stack1->pop(stack1));
stack2->push(stack2, 5);
stack2->push(stack2, 6);
printf("Popped from stack2: %d\n", stack2->pop(stack2));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack2: %d\n", stack2->pop(stack2));
stack1->destroy(stack1);
stack2->destroy(stack2);
return 0;
}
with output:
paul#horus:~/src/sandbox$ ./stack
Popped from stack1: 2
** PUSHING 5 ONTO STACK! **
** PUSHING 6 ONTO STACK! **
** POPPING 6 FROM STACK! **
Popped from stack2: 6
Popped from stack1: 3
Popped from stack1: 4
** POPPING 5 FROM STACK! **
Popped from stack2: 5
paul#horus:~/src/sandbox$
Note that we use the exact same struct stack for both types of stack - the differences between them are implemented by having the function pointers point to different functions in each case. The only visible difference to the user is that one is created with stack_create(), and the other is created with stack_create_verbose(). In all other respects, they're used identically, so you can see the polymorphism at work.

Using double pointer in a stack program in reference to array index location

I have a stack program I completed using single pointers. Now I have to use double pointers of type double to reference the index to an element in an array of type double. I made a random number generator and I am trying to satisfy these 4 conditions.
The stack is going to be in the form of an array of doubles.
The third argument to push() and the second argument to pop() are going to be in the form of
double **top, i.e. a pointer to pointer which stores the address of the current top element on the stack. Hint: in these functions, modify *top as the stack is updated.
A global integer variable myerror is created for you. Its value could be STACK_FULL, STACK_EMPTY, and NORMAL. Use this variable in your push() and pop() functions to inform the main() function the status of the operations.
Test your functions in main(). See details in the skeleton code stack.c.
I am lost on how to pass double pointer to the push function. That is type double.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define STACK_SIZE 10
#define STACK_FULL -2
#define STACK_EMPTY -1
#define NORMAL 0
int myerror = NORMAL;
void push(double [], // input/ouput - the stack
double, // input - data being pushed onto the stack
double **, // input/output - pointer to pointer to the top of stack
int); // constant - maximum capacity of stack
double // output - data being popped out from the stack
pop(double [], // input/output - the stack
double **); // input/output - pointer to pointer to top of stack
void push(double stack[], double item, double **top, int max_size)
{
if(**top==(max_size-1))
{
printf("Stack is Full\n");
return;
}
else
{
}
return;
}
double pop(double stack[],
double **top){
}
int main(){
double s[STACK_SIZE];
double *s_top = NULL;
int max_size=STACK_SIZE;
double **top;
top=&s_top;
srand(time(NULL));
int i;
double randNum=0.0;
for(i=0; i<STACK_SIZE; i++)
{
randNum = 94.0*(rand()/(RAND_MAX + 1.0));
randNum = randNum + 33.0;
printf("\nRandom double : %f\n ",randNum);
// push(s, randNum, top, max_size);
}
printf("-----------\n");
// Keep pushing doubles equivalent to chars randomly picked between '!'(33) and '~'(126)
// to the stack until it is full.
// Print each double before each pushing.
// Keep popping out doubles from the stack until it is empty
// Print each double after each popping.
// Repeat above until the user says 'no'.
return 0;
}
When calling push, pass the address of the top-of-stack pointer. It looks like s_top is the pointer to the top-of-stack, so when calling push you'd use:
push(s, /* the entire stack */
randNum, /* the number being added to the stack */
&s_top, /* pass the ADDRESS of the pointer which points to the top-of-stack */
max_size); /* the maximum size of the stack - could also just pass STACK_SIZE */
+1 on the question, as this is a good way to ask for help with a homework problem. You're not asking to have the whole problem solved, just asking for assistance with something that you don't understand.
Share and enjoy.
sample code
void push(double stack[], double item, double **top, int max_size){
if(*top == stack + max_size){
printf("Stack is Full\n");
myerror = STACK_FULL;
return;
}
**top = item;
++*top;
myerror = NORMAL;
}
int main(){
double s[STACK_SIZE];
double *s_top = s;
double randNum=0.0;
srand(time(NULL));
while(myerror != STACK_FULL){
randNum = 94.0*(rand()/(RAND_MAX + 1.0));
randNum = randNum + 33.0;
printf("\nRandom double : %f\n ",randNum);
push(s, randNum, &s_top, STACK_SIZE);
//printf("%p, <%f>\n", (void*)s_top, s_top[-1]);
}
printf("-----------\n");
return 0;
}

Resources