Conflicting types for enum bool? - c

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 *

Related

How to reduce amount of memory taken by function pointers in structs? [duplicate]

I'm trying to do a "class model" in C in which I define a struct that represents the class and inside it I define function pointers to represent methods, like this:
//ClassName.h
typedef struct struct_ClassName ClassName;
struct ClassName
{
char a;
char b;
char c;
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
};
void initClassName(ClassName*);
//ClassName.c
#include "ClassName.h"
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
void initClassName(ClassName *this_c)
{
this_c->method1 = &method1;
this_c->method2 = &method2;
...
this_c->methodN = &methodN;
}
void method1(ClassName *this_c, char c)
{
//do something
}
void method2(ClassName *this_c, char c)
{
//do something
}
...
void methodN(ClassName *this_c, char c)
{
//do something
}
Everything works fine but, somewhere in the code, I define an array:
...
ClassName objects[200];
for(i = 0; i < 200; i++)
{
initClassName(&objects[i]);
}
...
Because of the function pointers, the memory usage associated to this array is quite high (I have several "methods" in this "class").
Considering that this is a code that will run in an embedded system, is there a better way to do it?
Defining functions outside the structure could be a possibility but in my opinion it does not respect what I'm trying to emulate.
I have to use only C, not C++.
What you have created is a very dynamic system where each object instance can have its own set of method implementations. That's why it uses so much memory.
Another approach is an implementation closer to early C++ (before multiple inheritance) where all instance of the same class share the same vtable. The vtable contains the function pointers.
typedef struct struct_ClassName ClassName;
typedef struct struct_ClassName_vtable ClassName_vtable;
struct ClassName_vtable
{
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
}
struct ClassName
{
ClassName_vtable* _vtable;
char a;
char b;
char c;
};
void initClassName(ClassName*);
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
ClassName_vtable _ClassName_vtable = {
method1,
method2,
...,
methodN
};
void initClassName(ClassName *this_c)
{
this_c->_vtable = _ClassName_vtable;
}
That way, the OO overhead per instance is only the size of a pointer. It's also easier to create subclasses.
A method call looks like this:
ClassName* obj = ...;
obj->vtable->method2(obj, 'a');
ClassName objects[200];
for(i = 0; i < 200; i++)
initClassName(&objects[i]);
I will show you a stripped-off version of something I use here
for similar effect. It is hard to say when a certain size is huge in terms of pointers or whatever. Each environment has their truth and this can be useless or useful...
Anyway, the ideia is encapsulation. And in C we have no this pointer. C is not C++ or java or javascript. Each class instance must have a table of function pointers for the methods. We need to build these tables. This is how virtual classes are implemented in others languages anyway. And if each class element can allocate memory code is needed to allocate and free memory.
TL;DR
Below is a C example of a program that builds and uses an array of classes. In this case an array of stacks. It shows a mechanism of building stacks of mixed things. Each array item has all that is needed to manage his own stack instance, be it of a trivial type or a complex structure. It can be easily changed to implement other tyoes of classes in C.
Please do not bother warning me that I cast the return of malloc(). I , as many others, do not like implicit things. And I know that C-FAQ is a never-updated thing from the end of the '90s so no need to reference this either.
An example: a static STACK container
typedef struct
{
int data[SIZE];
int limit; // capacity
int size; // actual
} Stack;
This is it: a simple stack of int values. Let us say we want to declare a vector of stacks of different things, but in C. And use methods on them. If we use trivial types --- in C++ we say the struct is trivialy constructible --- things can get easier, but if we are about to use structs we need to know about how to manipulate stack elements, since they can allocate memory.
We are writing a container so the methods of the class must work for any underlying data. And we have no iterators like C++ STL. Here we are implementing the POP TOP and PUSH methods for stacks, and a toString() method like in java to print values on the screen.
For each possible content in the container we need to have a constructor, a
destructor, a copy constructor and a display method. In this example we have just 2 types of stacks: a stack of int and a stack of struct Sample:
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
We can add others just by writing the required 4 functions.
main.c example
int main(void)
{
srand(220804); // for the factory functions
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}
Each instance of Stack has pointers to the stack methods and to the functions that manipulate the stack data, so we can have a single class_test() function that does the following:
builds a stack of the required size, 4 or 3 in the example
fills the stack with data generated by factory functions (in production the logic builds the data)
shows the stack contents
removes all stack elements, one by one
At the end the destructor is called for eack stack.
The class.h file
typedef void* (PVFV)(void*);
typedef int (PIFV)(void*);
typedef struct
{
size_t size_;
size_t lim_;
void** data_;
PVFV* copy;
PVFV* destroy;
int (*show)(void*,const char*); // for testing
// constructor and destructor for container elements
PVFV* create_1;
PVFV* copy_1;
PVFV* destroy_1;
PIFV* show_1;
// member functions
PIFV* POP;
int (*PUSH)(void*,void*);
PVFV* TOP;
PIFV* empty;
size_t (*size)(void*);
} Stack;
Stack* create(
size_t,
void* (*)(void*),
void* (*)(void*),
void* (*)(void*),
int (*)(void*));
int class_test(Stack*, void* (*)());
the example output
=====> Testing with STACK of int
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 42
Value inserted: 41
Value inserted: 40
Value inserted: 39
Stack now has 4 elements
Stack has 4 of 4 elements:
42
41
40
39
Calls POP() until error
Stack size: 3
Stack size: 2
Stack size: 1
Stack size: 0
=====> Testing with STACK of struct Sample
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 0195 Sample id#0195 +76(203)6840-195
Value inserted: 0943 Sample id#0943 +35(686)9368-943
Value inserted: 0152 Sample id#0152 +16(051)8816-152
Stack now has 3 elements
Stack has 3 of 3 elements:
0096 Sample id#0096 +24(477)0418-096
0037 Sample id#0037 +27(214)3509-037
0836 Sample id#0836 +68(857)4634-836
Calls POP() until error
Stack size: 2
Stack size: 1
Stack size: 0
the logic
For each tye of element we need to write the 4 functions: they can alocate memory and be very complex or they can be trivial, but the class methods need to handle any case.
code for struct Sample in stack_struct.h###
#pragma once
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
void* copy_st(void*);
void* create_st(void*);
void* destroy_st(void*);
void* factory_st();
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
void* create_st(void* el)
{
return factory_st();
}
void* copy_st(void* el)
{
if (el == NULL) return NULL;
Sample* e = (Sample*)malloc(sizeof(Sample));
*e = *((Sample*)el);
return e;
}
void* destroy_st(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_st(void* el)
{
if (el == NULL) return 0;
Sample* e = (Sample*)el;
printf(
" %04d %15s %20s\n",
(int) e->_id, e->name, e->phone);
return 0;
}
void* factory_st()
{
Sample* e = (Sample*)malloc(sizeof(Sample));
e->_id = rand() % 1000;
sprintf(e->name, "Sample id#%04d", (int)e->_id);
memset(e->phone, 0, sizeof(e->phone));
e->phone[0] = '+';
for (int i = 1; i <= 17; i += 1)
e->phone[i] = '0' + rand() % 10;
e->phone[3] = '(';
e->phone[7] = ')';
e->phone[12] = '-';
e->phone[13] = e->name[11];
e->phone[14] = e->name[12];
e->phone[15] = e->name[13];
e->phone[16] = e->name[14];
e->phone[17] = 0;
return (void*)e;
}
code for int elements stack_int.h_###
#pragma once
#include <stdio.h>
#include <stdlib.h>
void* create_i(void* el)
{
int* e = (int*)malloc(sizeof(int));
*e = *((int*)el);
return (void*)e;
}
void* copy_i(void* el)
{
if (el == NULL) return NULL;
int* e = (int*)malloc(sizeof(int));
*e = *( (int*)el );
return e;
}
void* destroy_i(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_i(void* el)
{
if (el == NULL) return 0;
int v = *((int*)el);
printf(" %d\n", v);
return 0;
}
void* factory_i()
{
static int i = 42;
int* new_int = (int*)malloc(sizeof(int));
*new_int = i;
i -= 1;
return (void*)new_int;
}
The class implementation class.c
#include "class.h"
#include <stdio.h>
#include <stdlib.h>
void* Copy__(void*);
void* Destroy__(void*);
int POP__(void*);
int PUSH__(void*, void*);
int Show__(void*, const char*);
void* TOP__(void*);
int empty__(void*);
size_t size__(void*);
Stack* create(
size_t sz, void* (*create)(void*), void* (*copy)(void*),
void* (*destroy)(void*), int (*show)(void*))
{
Stack* stack = (Stack*)malloc(sizeof(Stack));
if (stack == NULL) return NULL;
stack->size_ = 0;
stack->lim_ = sz;
stack->data_ = (void*)malloc(sz * sizeof(void*));
stack->copy = Copy__;
stack->destroy = Destroy__;
stack->show = Show__;
stack->create_1 = create;
stack->copy_1 = copy;
stack->destroy_1 = destroy;
stack->show_1 = show;
stack->POP = POP__;
stack->PUSH = PUSH__;
stack->TOP = TOP__;
stack->empty = empty__;
stack->size = size__;
return stack;
}
void* Copy__(void* one) { return NULL; };
void* Destroy__(void* stack)
{ // before destructing a stack we need to
// destroy all elements
if (stack == NULL) return NULL;
Stack* st = (Stack*)stack;
for (size_t ix = 0; ix < st->size_; ix += 1)
(st->destroy_1)(st->data_[ix]);
free(st->data_);
free(st);
return NULL;
};
int POP__(void* stack)
{
if (stack == NULL) return -1; // no stack
Stack* st = stack;
if (st->size_ == 0) return -2; // empty
st->size_ -= 1; // one less
return 0; // ok
}
int PUSH__(void* el, void* stack)
{
if (el == NULL) return -1; // no element
if (stack == NULL) return -2; // no stack
Stack* st = (Stack*)stack;
if (st->size_ == st->lim_) return -3; // full
void* new_el = st->create_1(el); // copy construct
st->data_[st->size_] = new_el;
st->size_ += 1; // one up
return 0; // ok
}
int Show__(void* stack, const char* title)
{
if (stack == NULL) return -1;
Stack* st = stack;
if (title != NULL) printf("%s\n", title);
if (st->size_ == 0)
{
printf("Stack is empty\n");
return 0;
}
for (size_t ix = 0; ix < st->size_; ix += 1)
st->show_1(st->data_[ix]);
printf("\n");
return 0;
}
void* TOP__(void* stack)
{
if (stack == NULL) return NULL; // no stack
Stack* st = stack;
if (st->size_ == 0) return NULL; // empty
return st->data_[st->size_ - 1]; // ok
}
int empty__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_ == 0;
}
size_t size__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_;
}
///////////// TEST FUNCTION ///////////////
int class_test(Stack* tst, void* (*factory)())
{
if (tst == NULL) return -1;
// is stack empty?
if (tst->empty(tst))
printf("Stack is empty\n");
else
printf("Stack: %zd elements\n", tst->size(tst));
int res = tst->POP(tst);
printf("POP() on empty stack returned %d\n", res);
void* top = tst->TOP(tst);
if (top == NULL)
printf("TOP() on empty stack returned NULL\n");
else
{
printf(
"\nTOP() on empty stack returned NOT NULL!\n");
return -2;
}
printf("Calls PUSH until error\n\n");
void* one = factory();
int value = *(int*)one;
while (tst->PUSH(one, tst) == 0)
{
printf("Value inserted:");
tst->show_1(one);
free(one);
one = factory();
}
free(one); // last one, not inserted
printf("Stack now has %zd elements\n", tst->size(tst));
char title[80] = {" "};
sprintf(
title, "\nStack has %zd of %zd elements:\n",
tst->size_, tst->lim_);
tst->show(tst, title);
// agora esvazia a pilha ate dar erro
printf("\nCalls POP() until error\n");
while (tst->POP(tst) == 0)
printf("Stack size: %I32d\n", (int)tst->size(tst));
return 0;
};
The complete main.c program
#include <stdio.h>
#include "class.h"
#include "stack_int.h"
#include "stack_struct.h"
int main(void)
{
srand(220804);
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}

Class model in C

I'm trying to do a "class model" in C in which I define a struct that represents the class and inside it I define function pointers to represent methods, like this:
//ClassName.h
typedef struct struct_ClassName ClassName;
struct ClassName
{
char a;
char b;
char c;
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
};
void initClassName(ClassName*);
//ClassName.c
#include "ClassName.h"
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
void initClassName(ClassName *this_c)
{
this_c->method1 = &method1;
this_c->method2 = &method2;
...
this_c->methodN = &methodN;
}
void method1(ClassName *this_c, char c)
{
//do something
}
void method2(ClassName *this_c, char c)
{
//do something
}
...
void methodN(ClassName *this_c, char c)
{
//do something
}
Everything works fine but, somewhere in the code, I define an array:
...
ClassName objects[200];
for(i = 0; i < 200; i++)
{
initClassName(&objects[i]);
}
...
Because of the function pointers, the memory usage associated to this array is quite high (I have several "methods" in this "class").
Considering that this is a code that will run in an embedded system, is there a better way to do it?
Defining functions outside the structure could be a possibility but in my opinion it does not respect what I'm trying to emulate.
I have to use only C, not C++.
What you have created is a very dynamic system where each object instance can have its own set of method implementations. That's why it uses so much memory.
Another approach is an implementation closer to early C++ (before multiple inheritance) where all instance of the same class share the same vtable. The vtable contains the function pointers.
typedef struct struct_ClassName ClassName;
typedef struct struct_ClassName_vtable ClassName_vtable;
struct ClassName_vtable
{
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
}
struct ClassName
{
ClassName_vtable* _vtable;
char a;
char b;
char c;
};
void initClassName(ClassName*);
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
ClassName_vtable _ClassName_vtable = {
method1,
method2,
...,
methodN
};
void initClassName(ClassName *this_c)
{
this_c->_vtable = _ClassName_vtable;
}
That way, the OO overhead per instance is only the size of a pointer. It's also easier to create subclasses.
A method call looks like this:
ClassName* obj = ...;
obj->vtable->method2(obj, 'a');
ClassName objects[200];
for(i = 0; i < 200; i++)
initClassName(&objects[i]);
I will show you a stripped-off version of something I use here
for similar effect. It is hard to say when a certain size is huge in terms of pointers or whatever. Each environment has their truth and this can be useless or useful...
Anyway, the ideia is encapsulation. And in C we have no this pointer. C is not C++ or java or javascript. Each class instance must have a table of function pointers for the methods. We need to build these tables. This is how virtual classes are implemented in others languages anyway. And if each class element can allocate memory code is needed to allocate and free memory.
TL;DR
Below is a C example of a program that builds and uses an array of classes. In this case an array of stacks. It shows a mechanism of building stacks of mixed things. Each array item has all that is needed to manage his own stack instance, be it of a trivial type or a complex structure. It can be easily changed to implement other tyoes of classes in C.
Please do not bother warning me that I cast the return of malloc(). I , as many others, do not like implicit things. And I know that C-FAQ is a never-updated thing from the end of the '90s so no need to reference this either.
An example: a static STACK container
typedef struct
{
int data[SIZE];
int limit; // capacity
int size; // actual
} Stack;
This is it: a simple stack of int values. Let us say we want to declare a vector of stacks of different things, but in C. And use methods on them. If we use trivial types --- in C++ we say the struct is trivialy constructible --- things can get easier, but if we are about to use structs we need to know about how to manipulate stack elements, since they can allocate memory.
We are writing a container so the methods of the class must work for any underlying data. And we have no iterators like C++ STL. Here we are implementing the POP TOP and PUSH methods for stacks, and a toString() method like in java to print values on the screen.
For each possible content in the container we need to have a constructor, a
destructor, a copy constructor and a display method. In this example we have just 2 types of stacks: a stack of int and a stack of struct Sample:
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
We can add others just by writing the required 4 functions.
main.c example
int main(void)
{
srand(220804); // for the factory functions
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}
Each instance of Stack has pointers to the stack methods and to the functions that manipulate the stack data, so we can have a single class_test() function that does the following:
builds a stack of the required size, 4 or 3 in the example
fills the stack with data generated by factory functions (in production the logic builds the data)
shows the stack contents
removes all stack elements, one by one
At the end the destructor is called for eack stack.
The class.h file
typedef void* (PVFV)(void*);
typedef int (PIFV)(void*);
typedef struct
{
size_t size_;
size_t lim_;
void** data_;
PVFV* copy;
PVFV* destroy;
int (*show)(void*,const char*); // for testing
// constructor and destructor for container elements
PVFV* create_1;
PVFV* copy_1;
PVFV* destroy_1;
PIFV* show_1;
// member functions
PIFV* POP;
int (*PUSH)(void*,void*);
PVFV* TOP;
PIFV* empty;
size_t (*size)(void*);
} Stack;
Stack* create(
size_t,
void* (*)(void*),
void* (*)(void*),
void* (*)(void*),
int (*)(void*));
int class_test(Stack*, void* (*)());
the example output
=====> Testing with STACK of int
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 42
Value inserted: 41
Value inserted: 40
Value inserted: 39
Stack now has 4 elements
Stack has 4 of 4 elements:
42
41
40
39
Calls POP() until error
Stack size: 3
Stack size: 2
Stack size: 1
Stack size: 0
=====> Testing with STACK of struct Sample
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 0195 Sample id#0195 +76(203)6840-195
Value inserted: 0943 Sample id#0943 +35(686)9368-943
Value inserted: 0152 Sample id#0152 +16(051)8816-152
Stack now has 3 elements
Stack has 3 of 3 elements:
0096 Sample id#0096 +24(477)0418-096
0037 Sample id#0037 +27(214)3509-037
0836 Sample id#0836 +68(857)4634-836
Calls POP() until error
Stack size: 2
Stack size: 1
Stack size: 0
the logic
For each tye of element we need to write the 4 functions: they can alocate memory and be very complex or they can be trivial, but the class methods need to handle any case.
code for struct Sample in stack_struct.h###
#pragma once
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
void* copy_st(void*);
void* create_st(void*);
void* destroy_st(void*);
void* factory_st();
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
void* create_st(void* el)
{
return factory_st();
}
void* copy_st(void* el)
{
if (el == NULL) return NULL;
Sample* e = (Sample*)malloc(sizeof(Sample));
*e = *((Sample*)el);
return e;
}
void* destroy_st(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_st(void* el)
{
if (el == NULL) return 0;
Sample* e = (Sample*)el;
printf(
" %04d %15s %20s\n",
(int) e->_id, e->name, e->phone);
return 0;
}
void* factory_st()
{
Sample* e = (Sample*)malloc(sizeof(Sample));
e->_id = rand() % 1000;
sprintf(e->name, "Sample id#%04d", (int)e->_id);
memset(e->phone, 0, sizeof(e->phone));
e->phone[0] = '+';
for (int i = 1; i <= 17; i += 1)
e->phone[i] = '0' + rand() % 10;
e->phone[3] = '(';
e->phone[7] = ')';
e->phone[12] = '-';
e->phone[13] = e->name[11];
e->phone[14] = e->name[12];
e->phone[15] = e->name[13];
e->phone[16] = e->name[14];
e->phone[17] = 0;
return (void*)e;
}
code for int elements stack_int.h_###
#pragma once
#include <stdio.h>
#include <stdlib.h>
void* create_i(void* el)
{
int* e = (int*)malloc(sizeof(int));
*e = *((int*)el);
return (void*)e;
}
void* copy_i(void* el)
{
if (el == NULL) return NULL;
int* e = (int*)malloc(sizeof(int));
*e = *( (int*)el );
return e;
}
void* destroy_i(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_i(void* el)
{
if (el == NULL) return 0;
int v = *((int*)el);
printf(" %d\n", v);
return 0;
}
void* factory_i()
{
static int i = 42;
int* new_int = (int*)malloc(sizeof(int));
*new_int = i;
i -= 1;
return (void*)new_int;
}
The class implementation class.c
#include "class.h"
#include <stdio.h>
#include <stdlib.h>
void* Copy__(void*);
void* Destroy__(void*);
int POP__(void*);
int PUSH__(void*, void*);
int Show__(void*, const char*);
void* TOP__(void*);
int empty__(void*);
size_t size__(void*);
Stack* create(
size_t sz, void* (*create)(void*), void* (*copy)(void*),
void* (*destroy)(void*), int (*show)(void*))
{
Stack* stack = (Stack*)malloc(sizeof(Stack));
if (stack == NULL) return NULL;
stack->size_ = 0;
stack->lim_ = sz;
stack->data_ = (void*)malloc(sz * sizeof(void*));
stack->copy = Copy__;
stack->destroy = Destroy__;
stack->show = Show__;
stack->create_1 = create;
stack->copy_1 = copy;
stack->destroy_1 = destroy;
stack->show_1 = show;
stack->POP = POP__;
stack->PUSH = PUSH__;
stack->TOP = TOP__;
stack->empty = empty__;
stack->size = size__;
return stack;
}
void* Copy__(void* one) { return NULL; };
void* Destroy__(void* stack)
{ // before destructing a stack we need to
// destroy all elements
if (stack == NULL) return NULL;
Stack* st = (Stack*)stack;
for (size_t ix = 0; ix < st->size_; ix += 1)
(st->destroy_1)(st->data_[ix]);
free(st->data_);
free(st);
return NULL;
};
int POP__(void* stack)
{
if (stack == NULL) return -1; // no stack
Stack* st = stack;
if (st->size_ == 0) return -2; // empty
st->size_ -= 1; // one less
return 0; // ok
}
int PUSH__(void* el, void* stack)
{
if (el == NULL) return -1; // no element
if (stack == NULL) return -2; // no stack
Stack* st = (Stack*)stack;
if (st->size_ == st->lim_) return -3; // full
void* new_el = st->create_1(el); // copy construct
st->data_[st->size_] = new_el;
st->size_ += 1; // one up
return 0; // ok
}
int Show__(void* stack, const char* title)
{
if (stack == NULL) return -1;
Stack* st = stack;
if (title != NULL) printf("%s\n", title);
if (st->size_ == 0)
{
printf("Stack is empty\n");
return 0;
}
for (size_t ix = 0; ix < st->size_; ix += 1)
st->show_1(st->data_[ix]);
printf("\n");
return 0;
}
void* TOP__(void* stack)
{
if (stack == NULL) return NULL; // no stack
Stack* st = stack;
if (st->size_ == 0) return NULL; // empty
return st->data_[st->size_ - 1]; // ok
}
int empty__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_ == 0;
}
size_t size__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_;
}
///////////// TEST FUNCTION ///////////////
int class_test(Stack* tst, void* (*factory)())
{
if (tst == NULL) return -1;
// is stack empty?
if (tst->empty(tst))
printf("Stack is empty\n");
else
printf("Stack: %zd elements\n", tst->size(tst));
int res = tst->POP(tst);
printf("POP() on empty stack returned %d\n", res);
void* top = tst->TOP(tst);
if (top == NULL)
printf("TOP() on empty stack returned NULL\n");
else
{
printf(
"\nTOP() on empty stack returned NOT NULL!\n");
return -2;
}
printf("Calls PUSH until error\n\n");
void* one = factory();
int value = *(int*)one;
while (tst->PUSH(one, tst) == 0)
{
printf("Value inserted:");
tst->show_1(one);
free(one);
one = factory();
}
free(one); // last one, not inserted
printf("Stack now has %zd elements\n", tst->size(tst));
char title[80] = {" "};
sprintf(
title, "\nStack has %zd of %zd elements:\n",
tst->size_, tst->lim_);
tst->show(tst, title);
// agora esvazia a pilha ate dar erro
printf("\nCalls POP() until error\n");
while (tst->POP(tst) == 0)
printf("Stack size: %I32d\n", (int)tst->size(tst));
return 0;
};
The complete main.c program
#include <stdio.h>
#include "class.h"
#include "stack_int.h"
#include "stack_struct.h"
int main(void)
{
srand(220804);
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}

Can't identify memory access error in code, keeps giving segmentation faults

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.

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

Simple stack program not accepting input and crashing

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.

Resources