C — How would I make my stack completely dynamic? [duplicate] - c

This question already exists:
C- How can I push Strings to stack one element at a time?
Closed 7 years ago.
Currently my code uses a stack and pushes a user entered string into the stack one by one. However I would like to make it dynamic, what would I malloc/realloc, I know I'm missing something completely obvious but I guess I have tunnel vision... help?
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
char a [MAXSIZE];
char * p = a;
int top = -1;
void push ( char n )
{
if ( top == 99)
{
printf( "stack overflow");
return;
}
top+=1;
a[top] = n;
}
/* Function to delete an element from the stack */
void pop(){
if(top == -1)
printf("Stack is Empty");
else
top-=1;
}
char *inputString(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
char *str;
int ch;
size_t len = 0;
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return str;
while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return str;
}
}
str[len++]='\0';
return realloc(str, sizeof(char)*len);
}
int balanced (char * m){
int size = sizeof(m);
int i, j;
for (i=0; i<=size; ++i){
push(m[i]);
}
}
int main(void){
char *m;
printf("input string : ");
m = inputString(stdin, 10);
printf("%s\n", m);
balanced(m);
int i;
for (i=0;i<=sizeof(a);++i){
printf("\n%c", a[i]);
}
free(m);
return 0;
}

If I understand your question properly, this is what you are supposed to do.
struct Stack
{
char c;
struct Stack *next;
}*stack = NULL;
char pop()
{
if(stack == NULL)
{
printf("Stack Underflow\n");
return NULL;
}
c = stack -> c;
struct Stack * temp = stack;
stack = stack -> next;
free(temp);
return c;
}
void push(char c)
{
struct Stack * temp = malloc(sizeof(struct Stack));
temp -> next = NULL;
temp -> c = c;
if (stack == NULL)
stack = temp;
else
{
temp -> next = stack;
stack = temp;
}
}

Related

Segmentation fault while implementing stack as an array

This is a menu-driven program that carries out basic stack operations using arrays in the C programming language. The functions that are performed are push, pop, peep,isempty and isfull.
#include<stdio.h>
#include<stdlib.h>
struct stack
{
long int top;
long int size;
char* key;
};
int is_empty(struct stack *s) //check if its empty
{
if(s->top==-1)
{
return -1;
}
else
{
return 1;
}
}
int is_full(struct stack *s) //check if its full
{
if (s->top ==s->size-1)
{
return -1;
}
else
{
return 1;
}
}
void push(struct stack *s, char x) //pushes into stack
{
int check;
check = is_full(s);
if(check==-1)
{
printf("-1\n");
}
else
{
s->top = s->top+1;
s->key[s->top]=x;
}
}
void pop(struct stack *s) //deletes the last element
{
int check;
check = is_empty(s);
if(check==-1)
{
printf("-1\n");
}
else
{
char k;
k = s->key[s->top];
printf("%c\n",k);
s->top--;
}
}
void peep(struct stack *s) //prints the last element without deleting
{ int check;
char k;
check = is_empty(s);
if (check == -1)
{
printf("-1\n");
}
else
{
k = s->key[s->top];
printf("%c \n",k);
}
}
int main()
{
char ch;
char x;
long int n;
struct stack *s;
scanf("%ld ", &n);
s->size = n; //initialise the size
s->top = -1; //setting as -1 base case
s->key= (char *)malloc(n*sizeof(char)); //dynamic allocation of keys
while(1)
{
scanf("%c ",&ch);
switch(ch)
{
case 'i':
scanf("%c ",&x);
push(s,x);
break;
case 'd':pop(s);
break;
case 'p':peep(s);
break;
case 't':exit(0); //termination case
}
}
return 0;
}
This is a C program that is working for me in some online compilers but in VScode and other compilers, it's showing a segmentation fault without any output. This is an implementation of stack using arrays. Is it a problem with any of the scanf functions?
You have created a pointer variable s and then access the size field on that struct.
struct stack *s;
scanf("%ld ", &n);
s->size = n; //initialise the size
Except s doesn't actually point to anything at this point. You need to either statically or dynamically allocate memory for that struct.
struct stack s;
Or:
struct stack *s = malloc(sizeof(struct stack));

Reversing order of strings

This is a c program to reverse the order of words in a sentence(using stacks) read as input, but all I can get is the reverse of the each word in the sentence. How can I reverse the sentence(separated with ' ' or ',')?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
// A structure to represent a stack
struct Stack
{
int top;
unsigned capacity;
char* array;
};
struct Stack* createStack(unsigned capacity)
{
struct Stack* stack = (struct Stack*) malloc(sizeof(struct Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (char*) malloc(stack->capacity * sizeof(char));
return stack;
}
int isFull(struct Stack* stack)
{ return stack->top == stack->capacity - 1; }
// Stack is empty when top is equal to -1
int isEmpty(struct Stack* stack)
{ return stack->top == -1; }
// Function to add an item to stack. It increases top by 1
void push(struct Stack* stack, char item)
{
if (isFull(stack))
return;
stack->array[++stack->top] = item;
}
char pop(struct Stack* stack)
{
if (isEmpty(stack))
return 0;
return stack->array[stack->top--];
}
// A stack based function to reverese a string
void reverse(char str[])
{
int n = strlen(str);
struct Stack* stack = createStack(n);
// Push all characters of string to stack
int i;
for (i = 0; i < n; i++)
push(stack, str[i]);
for (i = 0; i < n; i++)
str[i] = pop(stack);
}
int main()
{
char str[50];
fgets(str, sizeof(str), stdin);
str[strlen(str)-1]='\0';
reverse(str);
printf("Reversed string is %s", str);
return 0;
}
Try this code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
// A structure to represent a stack
struct Stack
{
int top;
unsigned capacity;
//char* array;
char** array;
};
struct Stack* createStack(unsigned capacity)
{
if( capacity < 1 )
{
capacity = 1;
}
struct Stack* stack = (struct Stack*) malloc(sizeof(struct Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (char**) malloc(stack->capacity * sizeof(char*));
return stack;
}
void resizeStack( struct Stack* stack , int new_size )
{
if( NULL != stack && new_size > stack->capacity ) // Only support expansion
{
char ** old_array = stack->array ;
stack->array = (char**) malloc(new_size * sizeof(char*));
memcpy(stack->array,old_array,stack->capacity * sizeof(char*));
free(old_array);
stack->capacity = new_size ;
}
}
int isFull(struct Stack* stack)
{ return stack->top == stack->capacity - 1; }
// Stack is empty when top is equal to -1
int isEmpty(struct Stack* stack)
{ return stack->top == -1; }
// Function to add an item to stack. It increases top by 1
void push(struct Stack* stack, char *item)
{
if ( isFull(stack) )
{
resizeStack(stack, stack->capacity * 2 );
}
stack->array[++stack->top] =(char *) malloc(sizeof(char)*(strlen(item) +1));
strcpy(stack->array[stack->top] , item);
}
char * pop(struct Stack* stack)
{
char * ret = NULL;
if(! isEmpty(stack) )
{
ret = stack->array[stack->top];
stack->array[stack->top] = NULL ;
stack->top --;
}
return ret;
}
void freeStack(struct Stack* stack)
{
if( NULL != stack && NULL != stack->array )
{
while( ! isEmpty(stack) )
{
free(pop(stack));
}
free(stack->array);
}
else
{
printf(" freeStack try to free NULL ");
}
}
#define SEPARATER ' '
// A stack based function to reverese a string
void reverse(char str[])
{
int n = strlen(str);
struct Stack* stack = createStack(4);
char sep[2];
sep[0] = SEPARATER;
sep[1] = 0 ;
char * pch = strtok(str,sep);
while( NULL != pch )
{
push(stack,pch);
pch = strtok(NULL,sep);
}
char * swap_buff = (char*)malloc((n+1) * sizeof(char));
char * cp_buff = swap_buff;
do
{
char * top = pop(stack);
strcpy(cp_buff , top);
cp_buff += strlen(top);
*cp_buff++ = SEPARATER;
}while( ! isEmpty(stack) );
swap_buff[n] = 0;
strcpy(str,swap_buff);
freeStack(stack);
}
int main()
{
char str[50];
fgets(str, sizeof(str), stdin);
str[strlen(str)-1]='\0';
reverse(str);
printf("Reversed string is %s\n", str);
return 0;
}

Create and print a tree in C

I am trying to create a program that creates a tree from all the words in a file and the same words sorted.
Here is the code I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 30
typedef struct node *tree;
typedef struct node {
tree left;
tree right;
struct dictionary {
char *word;
char *sortedWord;
} value;
} node;
void swap(char *a,char *b){
char tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
char * bubble_sort(char *word){
char *ptr = word;
int n = strlen(word);
int i,j;
for(i=0;i<n-1;i++)
for(j=0;j<n-i-1;j++)
if(*(ptr+j)>*(ptr+j+1))
swap((ptr+j),(ptr+j+1));
return word;
}
char *RemoveNewLines(char *word){
char *newString = malloc(SIZE * sizeof(char));
char ch;
int currentLetter = 0;
int len = strlen(word);
while (currentLetter < len){
ch = word[currentLetter];
if (ch != '\n'){
newString[currentLetter] = ch;
}
else {
newString[currentLetter] = '\0';
}
currentLetter++;
}
return newString;
}
void createTree(tree memory){
// FILE *fp = fopen("words.txt","r");
// FILE *fp = fopen("words_no_duplicates1.txt","r");
FILE *fp = fopen("words_no_duplicates2.txt","r");
char *word = (char *)malloc(SIZE * sizeof(char));
if(fp == NULL)
{
perror("Error opening file");
exit(1);
}
// create the top node of the tree
node seedNode;
memory = &seedNode;
// initially just store the seed in the tree
memory->left = NULL;
memory->right = NULL;
fgets (word,SIZE,fp);
memory->value.word = (char *)malloc(SIZE * sizeof(char));
memory->value.word = strcpy(memory->value.word,RemoveNewLines(word));
// printf("%s\n",memory->value.word);
memory->value.sortedWord = (char *)malloc(SIZE * sizeof(char));
memory->value.sortedWord = strcpy(memory->value.sortedWord,bubble_sort(RemoveNewLines(word)));
// printf("%s\n",memory->value.sortedWord);
// printf("\n");
while ( fgets (word,SIZE,fp) != NULL){
memory->left = NULL;
memory->right = NULL;
memory->value.word = (char *)malloc(SIZE * sizeof(char));
memory->value.word = strcpy(memory->value.word,RemoveNewLines(word));
memory->value.sortedWord = (char *)malloc(SIZE * sizeof(char));
memory->value.sortedWord = strcpy(memory->value.sortedWord,bubble_sort(RemoveNewLines(word)));
// printf("%s\t %s\n",memory->value.word,memory->value.sortedWord);
// printf("%s\n",memory->value.word);
// printf("%s\n",memory->value.sortedWord);
// printf("\n");
}
fclose(fp);
}
void printTree(tree memory){
if (memory != NULL){
printTree(memory->left);
printf("%s",memory->value.word);
printf("%s",memory->value.sortedWord);
printf("\n");
printTree(memory->right);
}
}
int main(){
node seedNode;
tree memory = &seedNode;
createTree(memory);
printTree(memory);
return 0;
}
If I uncomment the print statements in createTree function, it all looks ok and prints what I want. But if I try to use printTree function then it ends with "Segmentation fault".
Where do I go wrong?
You can test with random file which contains one word per line.
#
After Joachim Pileborg reply, I changed my code as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 30
typedef struct node *tree;
typedef struct node {
tree left;
tree right;
struct dictionary {
char *word;
char *sortedWord;
} value;
} node;
node seedNode;
tree memory = &seedNode;
void swap(char *a,char *b){
char tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
char * bubble_sort(char *word){
char *ptr = word;
int n = strlen(word);
int i,j;
for(i=0;i<n-1;i++)
for(j=0;j<n-i-1;j++)
if(*(ptr+j)>*(ptr+j+1))
swap((ptr+j),(ptr+j+1));
return word;
}
char *RemoveNewLines(char *word){
char *newString = malloc(SIZE * sizeof(char));
char ch;
int currentLetter = 0;
int len = strlen(word);
while (currentLetter < len){
ch = word[currentLetter];
if (ch != '\n'){
newString[currentLetter] = ch;
}
else {
newString[currentLetter] = '\0';
}
currentLetter++;
}
return newString;
}
tree * createTree(tree *memory){
// FILE *fp = fopen("words.txt","r");
FILE *fp = fopen("words_no_duplicates1.txt","r");
char *word = (char *)malloc(SIZE * sizeof(char));
if(fp == NULL)
{
perror("Error opening file");
exit(1);
}
// create the top node of the tree
//node seedNode;
// initially just store the seed in the tree
(*memory)->left = NULL;
(*memory)->right = NULL;
fgets (word,SIZE,fp);
(*memory)->value.word = (char *)malloc(SIZE * sizeof(char));
(*memory)->value.word = strcpy((*memory)->value.word,RemoveNewLines(word));
// printf("%s\n",memory->value.word);
(*memory)->value.sortedWord = (char *)malloc(SIZE * sizeof(char));
(*memory)->value.sortedWord = strcpy((*memory)->value.sortedWord,bubble_sort(RemoveNewLines(word)));
// printf("%s\n",memory->value.sortedWord);
// printf("\n");
while ( fgets (word,SIZE,fp) != NULL){
(*memory)->left = NULL;
(*memory)->right = NULL;
(*memory)->value.word = (char *)malloc(SIZE * sizeof(char));
(*memory)->value.word = strcpy((*memory)->value.word,RemoveNewLines(word));
(*memory)->value.sortedWord = (char *)malloc(SIZE * sizeof(char));
(*memory)->value.sortedWord = strcpy((*memory)->value.sortedWord,bubble_sort(RemoveNewLines(word)));
// printf("%s\t %s\n",memory->value.word,memory->value.sortedWord);
// printf("%s\n",memory->value.word);
// printf("%s\n",memory->value.sortedWord);
// printf("\n");
}
fclose(fp);
return memory;
}
void printTree(tree memory){
if (memory != NULL){
printTree(memory->left);
printf("%s\n",memory->value.word);
printf("%s\n",memory->value.sortedWord);
printf("\n");
printTree(memory->right);
}
}
int main(){
createTree(&memory);
printTree(memory);
return 0;
}
Although now createTree function looks strange to me, after executing the code I have printed the last word, and it sorted, from file words_no_duplicates1.txt (these are the values memory->value.word, and memory->value.sortedWord) The trees memory->left and memory->right remains empty.
Can you please help?
There are many problems with your code, I will point out a couple that stood out to me.
In the createTree function you have these two lines
node seedNode;
memory = &seedNode;
Those are troublesome because first the argument memory is passed by value meaning the value passed when calling the function is copied and all you have inside the function is your local variable with its copy of the value. Changing the variable will not change the original variable you used when calling the function. You can solve this by either returning the pointer or by emulating passing by reference.
The second problem with this assignment is that you make it point to a local variable. Local variables go out of scope once the function returns, and will not exist any more. Keeping and then dereferencing a pointer to this (non-existent) variable will lead to undefined behavior, and most likely crashes. This can be solved either by not doing the assignment at all, and just rely on the pointer you pass a argument, or by dynamically allocating memory for the node.

Linked lists, operations with parameter

I'm trying to implement program in with i can create ~arbitrary number of singly linked lists dynamically and perform operations on particular one (defined by parameter). I create dynamic array of head pointers so that i can refer to the certain head node defined by paramater(index of an array + 1). Parameter is just (1,2,3..number of lists). So far I have managed to implement only initialise and push function but the program after complilation doesn't work as expected. Where is the problem?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define CHUNK 10
typedef struct
{
char *str;
struct node *next;
} node;
node *initialise(node **array, int *amount_of_lists);
void push(node **array, int *amount_of_lists);
char *getString(void);
int main()
{
node **heads = NULL; //initially null, pointer to the dynamic array of head pointers
int amount_of_lists = 0;
int *no_of_heads = &amount_of_lists;
initialise(heads, no_of_heads);
initialise(heads, no_of_heads);
push(heads, no_of_heads);
push(heads, no_of_heads);
return 0;
}
node *initialise( node **array, int *amount_of_lists ) /*reallocate memory for another head pointer ans return the pointer to node*/
{
++(*amount_of_lists);
printf("\n%d", *amount_of_lists);
array = (node**)realloc(array, sizeof(node*)*(*amount_of_lists));
return array[(*amount_of_lists) - 1] = malloc(sizeof(node));
}
int readParameter(int *amount_of_lists)
{
int parameter = 0, control = 0;
bool repeat = 0;
do
{
if(repeat)
{
printf("\nWrong parameter, try again.");
}
printf("\n Enter list parameter: ");
control = scanf("%d", &parameter);
fflush(stdin);
repeat = 1;
}
while( control != 1 || parameter < 1 || parameter > (*amount_of_lists) );
return parameter;
}
void push(node **array, int *amount_of_lists)
{
int parameter = readParameter(amount_of_lists) - 1;
node *temp = array[parameter];
array[parameter] = malloc(sizeof(node));
array[parameter] -> next = temp;
array[parameter] -> str = getString();
}
char *getString(void)
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = EOF;
while (ch)
{
ch = getc(stdin);
/* Check if we need to stop. */
if (ch == EOF || ch == '\n')
ch = 0;
/* Check if we need to expand. */
if (size <= index)
{
size += CHUNK;
tmp = realloc(line, size);
if (!tmp)
{
free(line);
line = NULL;
break;
}
line = tmp;
}
/* Actually store the thing. */
line[index++] = ch;
}
return line;
}
As BLUEPIXY somewhat crypticly hinted at in his comment 1), in order to modify main()'s heads in initialise(), you have to pass heads by reference to initialise(), i. e. change
initialise(heads, no_of_heads);
initialise(heads, no_of_heads);
to
initialise(&heads, no_of_heads);
initialise(&heads, no_of_heads);
consequently
node *initialise( node **array, int *amount_of_lists )
changes to
node *initialise(node ***array, int *amount_of_lists)
and inside array changes to *array, i. e.
*array = realloc(*array, sizeof(node *) * *amount_of_lists);
return (*array)[*amount_of_lists - 1] = malloc(sizeof(node));

Segmentation (core dumped)

I have been working on a post fix calculator for standard input and after working on it I ended up getting a saying segmentation fault (core dumped) it doesn't say where it occurs or what caused it and after looking for an explanation of what it means I couldn't really find anything that would help me fix it. So I decided I might as well ask here this is all of the stuff I have so far.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct stack
{
int data;
struct stack *up;
};
void push( struct stack * ptr, int value)
{
struct stack * tmp;
tmp = malloc(sizeof(value));
tmp -> data = value;
tmp -> up = NULL;
}
int pop(struct stack * ptr)
{
int value;
struct stack * tmp;
tmp = ptr;
value = tmp-> data;
ptr = tmp -> up;
free(tmp);
return value;
}
int evaluate(int argc,const char * argv[],struct stack * ptr)
{
int h;
int i;
for (i = 0; i <= argc - 1; i++)
{
if (strcmp(argv[i], "M") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b*a;
push(ptr,h);
}
else if (strcmp(argv[i], "A") == 0)
{
printf("%s\n", "error \0");
int a = pop(ptr);
int b = pop(ptr);
h = b+a;
push(ptr,h);
}
else if (strcmp(argv[i], "D") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b/a;
push(ptr,h);
}
else if (strcmp(argv[i], "S") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b-a;
push(ptr,h);
}
else
{
printf("%s", "Not an operator");
}
}
return pop(ptr);
}
int main(int argc, const char *argv[])
{
struct stack s;
struct stack *ptr = s.up;
evaluate(argc,argv,ptr);
return EXIT_SUCCESS;
}
In main you create struct stack s; and don't initialize it.
Then you pass s.up as the third argument of evaluate.
And evaluate eventually calls pop on s.up, which calls free on s.up. But s.up is still uninitialized, so it crashes.
It's because you are allocating the structs wrong, here
tmp = malloc(sizeof(value));
you are allocating enough space for a int value, so the code that follows invokes undefined behavior leading in your case to a segmentation fault, try it this way
tmp = malloc(sizeof(struct stack));
or
tmp = malloc(sizeof(*tmp));
also, always check the success of malloc() before dereferencing the pointer, like this
void push(struct stack *ptr, int value)
{
struct stack *tmp;
tmp = malloc(sizeof(*tmp));
if (tmp == NULL)
return;
tmp->data = value;
tmp->up = NULL;
}

Resources