Creating a stack of strings in C - c

I want to have a stack that takes strings. I want to be able to push and pop strings off, as well as clear the whole stack. I think C++ has some methods for this. What about C?

Quick-and-dirty untested example. Uses a singly-linked list structure; elements are pushed onto and popped from the head of the list.
#include <stdlib.h>
#include <string.h>
/**
* Type for individual stack entry
*/
struct stack_entry {
char *data;
struct stack_entry *next;
}
/**
* Type for stack instance
*/
struct stack_t
{
struct stack_entry *head;
size_t stackSize; // not strictly necessary, but
// useful for logging
}
/**
* Create a new stack instance
*/
struct stack_t *newStack(void)
{
struct stack_t *stack = malloc(sizeof *stack);
if (stack)
{
stack->head = NULL;
stack->stackSize = 0;
}
return stack;
}
/**
* Make a copy of the string to be stored (assumes
* strdup() or similar functionality is not
* available
*/
char *copyString(char *str)
{
char *tmp = malloc(strlen(str) + 1);
if (tmp)
strcpy(tmp, str);
return tmp;
}
/**
* Push a value onto the stack
*/
void push(struct stack_t *theStack, char *value)
{
struct stack_entry *entry = malloc(sizeof *entry);
if (entry)
{
entry->data = copyString(value);
entry->next = theStack->head;
theStack->head = entry;
theStack->stackSize++;
}
else
{
// handle error here
}
}
/**
* Get the value at the top of the stack
*/
char *top(struct stack_t *theStack)
{
if (theStack && theStack->head)
return theStack->head->data;
else
return NULL;
}
/**
* Pop the top element from the stack; this deletes both
* the stack entry and the string it points to
*/
void pop(struct stack_t *theStack)
{
if (theStack->head != NULL)
{
struct stack_entry *tmp = theStack->head;
theStack->head = theStack->head->next;
free(tmp->data);
free(tmp);
theStack->stackSize--;
}
}
/**
* Clear all elements from the stack
*/
void clear (struct stack_t *theStack)
{
while (theStack->head != NULL)
pop(theStack);
}
/**
* Destroy a stack instance
*/
void destroyStack(struct stack_t **theStack)
{
clear(*theStack);
free(*theStack);
*theStack = NULL;
}
Edit
It would help to have an example of how to use it:
int main(void)
{
struct stack_t *theStack = newStack();
char *data;
push(theStack, "foo");
push(theStack, "bar");
...
data = top(theStack);
pop(theStack);
...
clear(theStack);
destroyStack(&theStack);
...
}
You can declare stacks as auto variables, rather than using newStack() and destroyStack(), you just need to make sure they're initialzed properly, as in
int main(void)
{
struct stack_t myStack = {NULL, 0};
push (&myStack, "this is a test");
push (&myStack, "this is another test");
...
clear(&myStack);
}
I'm just in the habit of creating pseudo constructors/destructors for everything.

Try GNU Obstacks.
From Wikipedia:
In the C programming language, Obstack is a memory-management GNU extension to the C standard library. An "obstack" is a "stack" of "objects" (data items) which is dynamically managed.
Code example from Wikipedia:
char *x;
void *(*funcp)();
x = (char *) obstack_alloc(obptr, size); /* Use the macro. */
x = (char *) (obstack_alloc) (obptr, size); /* Call the function. */
funcp = obstack_alloc; /* Take the address of the function. */
IMO what makes Obstacks special: It does not need malloc() nor free(), but the memory still can be allocated «dynamically». It is like alloca() on steroids. It is also available on many platforms, since it is a part of the GNU C Library. Especially on embedded systems it might make more sense to use Obstacks instead of malloc().

See Wikipedia's article about stacks.

Related

Memory corruption cause by free()

I'm trying to understand how does dynamic memory allocation in C work. So I coded this:
typedef struct person{
int id;
int credit;
}person_t;
typedef struct list{
int id;
person_t * people;
}list_t;
int main(){
list_t * list;
list = malloc(sizeof(list_t));
list->people = malloc(10 * sizeof(person_t)); //list for 10 people
free(list->people);
free(list);
}
, which appears to be correct. However, when I decided to create functions for allocation\deallocation, double free or corruption error started to appear:
void init_list(list_t * listptr, int size){
listptr = malloc(sizeof(list_t));
listptr->people = malloc(size * sizeof(person_t));
}
void clear_list(list_t * listptr){
free(listptr->people);
free(listptr);
}
int main(){
list_t list;
init_list(&list, 10); //list for 10 people
clear_list(&list);
}
Output:
Error in ./list: double free or corruption (out) : 0x00007ffc1b3fba70
Why could that be? Thanks in advance.
void init_list(list_t * listptr, int size){
listptr = malloc(sizeof(list_t));
listptr->people = malloc(size * sizeof(person_t));
}
is not correct. You are modifying listptr in the function. That does not change anything of list in main. You need to remove the line fhat changes listptr in that function. Use:
// listptr is already a valid pointer.
// There is no need to allocate memory for it.
void init_list(list_t * listptr, int size){
listptr->people = malloc(size * sizeof(person_t));
}
You have a worse mistake in clear_list.
void clear_list(list_t * listptr){
free(listptr->people);
free(listptr);
}
You are calling free on a pointer that was not allocated by a call to malloc. listptr is a pointer to the object that was created in stack in main. Remove the second call to free. Use:
// listptr is a pointer to an object on the stack in main.
// Trying to call free on it is an error.
void clear_list(list_t * listptr){
free(listptr->people);
}

Complex generic stack

I have been assigned to program a generic stack in ANSI C. It is meant to be for primitive datatypes. Until here there was no big problem whatsoever.
Afterwards I was asked to reprogram my application so that even complex data types can be used on my stack. I have searched and researched for the last week and I found nothing that could be helpful enough.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stddef.h>
#include "genstacklib.h"
void (*freefn) (void*);
/*
* ToDo
*/
void GenStackNew(genStack *s, int elemSize, void (*freefunk) (void*))
{
s->elems = malloc (elemSize * GenStackInitialAllocationSize);
freefn = freefunk;
assert (s->elems != NULL);
s->elemSize = elemSize;
s->logLength = 0;
s->allocLength = GenStackInitialAllocationSize;
}
/*
* ULStackPush adds an element to the stack and allocates new memory if
* needed. If there is not enough memory, ULStackPush does nothing.
*/
void GenStackPush (genStack *s, const void *elemAddr)
{
/*assert (sizeof(*elemAddr) == s->elemSize);*/
assert (s->elems != NULL);
if (s->logLength == s->allocLength)
{
void *temp = NULL;
temp = realloc (s->elems, 2 * s->allocLength * s->elemSize);
assert (temp != NULL);
s->allocLength = 2 * s->allocLength;
s->elems = temp;
}
memcpy(currentval(s), elemAddr, s->elemSize);
s->logLength = s->logLength + 1;
}
void GenStackPop (genStack *s, const void *elemAddr)
{
assert (s->elems != NULL);
assert (s->logLength != 0);
(s->logLength)--;
memcpy((void *)elemAddr, currentval(s), s->elemSize);
}
void *currentval(genStack *s)
{
assert (s->elems != NULL);
return ((size_t*)s->elems + s->logLength * s->elemSize);
}
bool GenStackEmpty (const genStack *s)
{
assert (s->elems != NULL);
return s->logLength == 0;
}
void GenStackDispose (genStack *s)
{
assert (s->elems != NULL);
s->logLength = 0;
free (s->elems);
freefn();
}
/*
* ToDO
*/
void *freefn (void *) {
free
And my header data is:
#ifndef GENSTACKLIB_H
#define GENSTACKLIB_H
#include <stdbool.h>
#define GenStackInitialAllocationSize 4
typedef struct
{
void *elems;
int elemSize;
int logLength;
int allocLength;
} genStack;
void GenStackNew (genStack * s, int elemSize);
bool GenStackEmpty (const genStack * s);
void GenStackPush (genStack * s, const void *elemAddr);
void GenStackPop (genStack * s, const void *elemAddr);
void GenStackDispose (genStack * s);
void *currentval(genStack *s);
#endif
In the first block of code, I believe that what has to be done is in the ToDo markings.
How can I make it to use my stack for complex data types?
Thanks in advance
I dont see any problem with "complex" types like strings... there is no real difference bewteen pointer to string and pointer to int. So just store pointers (or pointers to pointers) and that should work.
So instead of element to be "int".. element is pointer to pointer.
Basic idea in form of very "pseudo" C code
typedef struct Wrapper
{
void * primitiveData;
} Wrapper;
void PrimitivePush(void * data)
{
Wrapper * w = malloc();
w->primitiveData = malloc();
memcpy(w->primitiveData, data);
ClassicComplexTypePush(&w)
}
ClassicComplexTypePush(void ** data)
{
push data to stack
}
Consider using a singularly linked list for implementation, since when
using a stack, we don't know how many items may be needed.
Use a byte* or (char*) to store the contents of memory, instead of a void* (which would also work, but we may need to pad the allocation, to include structs)
Copy memory into a new allocation, which is pushed onto the stack,
then delete that used upon pop.
each node has to be of the same type, or at-least the same size,
errors using wrong type though may be undesired
pop can be either used to check if the stack is empty by passing (NULL)
or to actually pop the stack, by referencing the memory you want to set.
typedef unsigned char byte;
Create the structures which will be used to keep track of the stack
struct gStackNode {
byte *data;
struct gStackNode *next;
};
struct gStack {
unsigned size;
struct gStackNode *head;
};
Initialize the stack, including the size of the type we will be using
void stack_initalize(struct gStack *stk, unsigned size) {
if (!stk)
return;
stk->size = size;
stk->head = (void*)0;
}
Always, we need to manually free the stack, in-case not all were popped
void stack_free(struct gStack *stk) {
if (!stk)
return;
struct gStackNode *temp;
/* step through the remaining stack, deleting each item */
while(stk->head) {
temp = stk->head->next;
free((byte*)stk->head->data);
free((struct gStackNode *)stk->head);
stk->head = temp;
}
}
push an item onto the stack
void stack_push(struct gStack *stk, void *data) {
struct gStackNode *node = (struct gStackNode*)malloc(sizeof(struct gStackNode));
struct gStackNode *temp = stk->head;
node->next = temp;
node->data = (byte*)malloc(sizeof(byte)*(stk->size));
byte * src = (char*)(data);
byte * dest = (char*)(node->data);
unsigned n = stk->size;
/* fill the new allocation with source data */
for(;n;n--)
*(dest++) = *(src++);
/* the node becomes the new head */
stk->head = node;
}
Sometimes we don't want to use a local variable ie: stack_pop_(stack, &type) we can use stack_push_arg_no_ref(stack, 10).
void stack_push_arg_no_ref(struct gStack *stk, void *data) {
stack_push(stk, &data);
}
Now we can pop, and use the same to peek, passing (NULL) to data will result in a peek,
returning (1) if there is an item in the stack, and a (0) if its empty
int stack_pop(struct gStack *stk, void * data) {
if (!stk)
return 0;
if (!stk->head)
return 0;
if (data == (void*)0) {
/*
simply check to see if the stack is empty or not
don't actually pop the stack
*/
return ((!stk->head == (void*)0));
} else {
struct gStackNode *next = stk->head->next;
struct gStackNode *node = stk->head;
unsigned i;
byte *c_temp = (byte*)data;
for(i=0;i<stk->size;i++)
*c_temp++ = node->data[i];
free((byte*)node->data);
free((struct gStackNode*)node);
stk->head = next;
}
}
Finally we can implement the stack
using any ANSI C data types
the size of a character string needs to be fixed
structs can also be used
Using a character string
CAUTION, for this example, the strings need to be NULL terminated, though
it is possible to use non-NULL terminated strings
char ta[32] = "ta: text 1";
char tb[32] = "tb: text 2";
char tc[32];
struct gStack stack_char; stack_initalize(&stack_char, sizeof(ta));
stack_push(&stack_char, ta);
stack_push(&stack_char, tb);
while (stack_pop(&stack_char, &tc))
printf("%s\n", tc);
be sure to free the stack
stack_free(&stack_char);
Using integers
int a = 120, b = -32, c;
struct gStack stack_int; stack_initalize(&stack_int, sizeof(int));
stack_push(&stack_int, &a);
stack_push(&stack_int, &b);
/* or we can use */
stack_push_arg_no_ref(&stack_int, 1776);
/* we can now see the contents of the stack */
while (stack_pop(&stack_int, &c))
printf("%d\n", c);
stack_free(&stack_int);

C Programming Stack

I am currently working on stacks right now. I am supposed to use the following structures and function prototypes:
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
Here is my actual code for create_stack() and push():
stack* create_stack()
{
stack *stack;
stack = malloc(sizeof(stack));
stack->size = 0;
stack->stack = NULL;
return stack;
}
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack();
newStack->stack->data = val;
newStack->stack = s->stack;
s = newStack;
}
I am getting a segmentation fault when I try to store char val into newStack->stack->data. How does this not work? What do I need to do to make this stack on top???
The push function is wrong.
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack(); /* new stack created, why not work on the existing one ? */
newStack->stack->data = val; /* you're writing to a NULL pointer */
newStack->stack = s->stack;
s = newStack; /* this will not be visible from outside the function */
}
First of all, you are trying to recreate a new stack for each call of this function, which is certainly not what is intended.
If you try to modify the value of s, it will not be visible from outside the function, and you will still have your original stack.
Then, you are accessing the stack->data member even though stack has no space allocated to it yet (because you set it to NULL). You actually set it right after, which is why it crashes, most probably.
You probably want to do something like this:
void push(stack* s, char val)
{
node * n;
/* go to the end of the "stack" */
n = s->stack;
while (n != NULL) {
n = n->next;
}
/* allocate memory for a new node */
n = malloc(sizeof(node));
/* initialize node */
n->data = val;
n->next = NULL;
/* increment stack size */
s->size++;
}
And as mentionned before, this is merely a singly-linked list which is not the best fit for a stack, because as it exists now, you have to follow the node pointers to reach the last element, which makes push and pop operations O(N).
A faster implementation would look like this:
void push(stack* s, char val)
{
node * first_node, * new_node;
first_node = s->stack;
/* allocate memory for a new node */
new_node = malloc(sizeof(node));
/* initialize node */
new_node->data = val;
new_node->next = first_node;
/* increment stack size */
s->stack = new_node;
s->size++;
}
The top of the stack is always the first node, and the performance is O(1).
Follow your code....
stack *newStack = create_stack(); // in push()
newStack = malloc(sizeof(stack)); // in create_stack()
newStack->stack = NULL; // in create_stack()
newStack->stack->data = val; // in push()... this is where you crash.
Because newStack->stack is a NULL pointer. Your create_stack() function sets it to NULL, and you then dereference it. You have to allocate a struct node somewhere.
This code also has some readability issues which might be contributing to the problem. You are naming variables the same names as their types, which is very confusing. Consider using some other naming pattern like stack_t for types and stack for variable names.

data is still in memory after removing from stack in C

I'm trying to improve my knowledge of C.
As an exercise I wrote a stack data structure. Everything works fine if I push N items and then pop N items. The problem occurs when I try to push an item again as the last removed item is still in memory (I think this is a problem).
When I allocate memory for the new path struct, the last removed string is still at the address which was freed after popping a data.
So when a new string is pushed, the last removed and new string are joined.
Can someone please check the following code and tell me what I'm doing wrong. Other comments are also welcome. Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 1000
struct path {
char curPath[N];
struct path *Next;
};
struct MyStack {
struct path *head;
int size;
};
int push(struct MyStack *, char *);
char * pop(struct MyStack *, char *);
int main() {
char path[N];
struct MyStack stack;
stack.head = NULL;
stack.size = 0;
push(&stack, "aaaaaaaaaaaa");
push(&stack, "bbbbbbbbbbbb");
pop(&stack, path);
printf("%s\n", path);
// output is:
// bbbbbbbbbbbb
path[0] = '\0';
push(&stack, "cccccccccccc");
pop(&stack, path);
printf("%s\n", path);
// output should be:
// cccccccccccc
// but it is not
// it is:
// bbbbbbbbbbbbcccccccccccc
return 0;
}
int push(struct MyStack *stack, char *path) {
if (strlen(path) > N) {
return -1;
}
struct path *p = (struct path*)malloc(sizeof(struct path));
if (p == NULL) {
return -1;
}
strcat((*p).curPath, path);
(*p).Next = (*stack).head;
(*stack).head = p;
(*stack).size++;
return 0;
}
char * pop(struct MyStack *stack, char *path) {
if ((*stack).size == 0) {
printf("can't pop from empty stack");
return NULL;
}
struct path *p;
p = (*stack).head;
(*stack).head = (*p).Next;
strcat(path, (*p).curPath);
free(p);
p = NULL;
(*stack).size--;
return path;
}
You are using strcat() in your pop() function. That appends the string that is at stack->head to your char path[]. If you want to replace the string, use strcpy() rather than strcat().
Besides that, though, there are other oddities in your code. You are returning an int from push() and a char* from pop() but you're not assigning those variables to anything in main(), so why are they not void functions?
malloc() does not fill the allocated memory with zeros, so here
struct path *p = (struct path*)malloc(sizeof(struct path));
// ...
strcat((*p).curPath, path);
you append the given string to whatever happens to be in (*p).curPath.
(This could cause a segmentation violation easily.)
Using strcpy() or (perhaps better strlcpy()) should solve the problem.

Initialize a stack in C by setting pointer to NULL

I'm trying to implement stack in C according to the following header (stack.h):
#ifndef STACK_H
#define STACK_H
/* An element from which stack is consisting */
typedef struct stack_node_ss {
struct stack_node_ss *next; /* pointer to next element in stack */
void *value; /* value of this element */
} stack_node_s;
/* typedef so that stack user doesn't have to worry about the actual type of
* parameter stack when using this stack implementation.
*/
typedef stack_node_s* stack_s;
/* Initializes a stack pointed by parameter stack. User calls this after he
* has created a stack_t variable but before he uses the stack.
*/
void stack_init(stack_s *stack);
/* Pushes item to a stack pointed by parameter stack. Returns 0 if succesful,
* -1 otherwise.
*/
int stack_push(void *p, stack_s *stack);
/* Pops item from a stack pointed by parameter stack. Returns pointer to
* element removed from stack if succesful, null if there is an error or
* the stack is empty.
*/
void *stack_pop(stack_s *stack);
#endif
However, being new with C, I'm stuck at the stack_init function, I have written in stack.c:
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
void stack_init(stack_s *stack) {
(*stack)->value = NULL;
(*stack)->next = NULL;
}
The main program begins with:
int *tmp;
stack_s stack;
stack_init(&stack);
And this crashes my program with:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000abf in stack_init (stack=0x7fff5fbffb30) at stack.c:6
6 (*stack)->value = NULL;
Can you hint me to the right track? Many thanks.
You have to allocate memory for **stack itself:
*stack = malloc(sizeof(**stack));
But please don't typedef pointer types. That's really confusing and hard to read. Better to pass the pointer by value and leave it to the caller to store the pointer, like this:
typedef struct stack_node_t
{
struct stack_node_t * next;
/* ... */
} stack_node;
stack_node * create_stack()
{
stack_node * res = calloc(1, sizeof(stack_node));
return res;
}
void destroy_stack(stack_node * s)
{
if (!next) return;
stack_node * next = s->next;
free(s);
destroy_stack(next);
}
// etc.
Then you can just say:
stack_node * s = create_stack();
// use s
destroy_stack(s);
s = NULL; // some people like this
You are dereferencing an uninitialised pointer, causing undefined behaviour.
Because this function is creating a new stack, you need to allocate some dynamic memory for the stack and then set the pointer to point to that newly allocated memory:
void stack_init(stack_s *stack) {
*stack = malloc(sizeof(**stack)); // create memory for the stack
(*stack)->value = NULL;
(*stack)->next = NULL;
}
stack_s stack;
stack_init(&stack);
Then you should have a function called stack_destroy that will free the dynamic memory and set the pointer to NULL:
void stack_destroy(stack_s *stack) {
free(*stack);
*stack = NULL;
}
You should initialize the stack to NULL - not to push a NULL value to it:
void stack_init(stack_s *stack) {
*stack=NULL;
}

Resources