The main code itself works fine but I want to make use of character strings instead of the char, and it might be because I've overlooked something absurdly simple. Here is a small snippet of code:
struct Stack
{
char *SData;
int counter;
struct Stack *next;
};
struct Stack* StackNewNode(char SData)
{
struct Stack *stackNode = (struct Stack*)malloc(sizeof(struct Stack));
stackNode->SData = SData; //error here because of the difference of char, should i use []?
stackNode->next = NULL;
return stackNode;
}
void PUSH(struct Stack **root, char SData) //this part only pushes a character
{
struct Stack *stackNode = StackNewNode(SData);
stackNode->next = *root;
*root = stackNode;
printf("\n%c pushed to stack\n", SData);
}
void POP(struct Stack **root)
{
if (*root == NULL)
{
return;
}
struct Stack *temp = *root;
*root = (*root)->next;
char pop = temp->SData; //how should i pop a full string?
free(temp);
printf("%c popped from stack\n", pop);
}
I also want to implement a counter in the Stack. Should i use Stack->counter++ or is there some other more correct way to do it?
Sorry for the wall of text its my first time here
I don't see counter in struct Stack used anywhere in the code snippets you provided. Assuming you want some count of the number of elements in the stack, it wouldn't make sense for this value to be part of the struct. After all, you only need one count, not one attached to every element in the stack. You would want to make this its own variable, perhaps a global defined in the same place as you define root. Just make sure to initialize it to zero.
As for using character strings, you already have char *SData, which can point to a string. All you need to do is change PUSH and StackNewNode to use char* parameter rather than char and then pass it a string, something like this:
PUSH(&root, "My string");
To start with your current code have some type mismatch here: stackNode->SData = SData;
stackNode->SData is a char pointer and SData is a char. I assume your compiler warns you about that - never ignore warnings.
If you want to use C type string you need updates like:
Pass char pointer instead of char
Allocate memory for the string
Copy the passed string to the allocated memory
Free the memory when done
Something like:
struct Stack
{
char *SData;
int counter;
struct Stack *next;
};
struct Stack* StackNewNode(const char* str)
{
struct Stack *stackNode = malloc(sizeof(struct Stack));
if (stackNode == NULL) exit(1);
stackNode->SData = malloc(strlen(str) + 1);
if (stackNode->SData == NULL) exit(1);
strcpy(stackNode->SData, str);
stackNode->next = NULL;
return stackNode;
}
void PUSH(struct Stack **root, const char* str)
{
struct Stack *stackNode = StackNewNode(str);
stackNode->next = *root;
*root = stackNode;
printf("\n%s pushed to stack\n", str);
}
void POP(struct Stack **root)
{
if (*root == NULL)
{
return;
}
struct Stack *temp = *root;
*root = (*root)->next;
printf("%s popped from stack\n", temp->SData);
free(temp->SData);
free(temp);
}
Usage example:
struct Stack *root = NULL;
PUSH(&root, "Hello World");
Adding a counter
In your code you have placed int counter; inside every stack element. You can make that work but I would prefer two structs. One struct type holding information about the whole stack and another struct type for the elements.
Like:
struct StackNode
{
char *SData;
struct StackNode *next;
};
struct Stack
{
int counter;
struct StackNode *root;
};
The functions would need some updates like:
void PUSH(struct Stack *stack, const char* str)
{
struct StackNode *stackNode = StackNewNode(str);
stackNode->next = stack->root;
stack->root = stackNode;
++stack->counter; // Increment counter
printf("\n%s pushed to stack\n", str);
}
Usage example:
struct Stack stack = {0, NULL};
PUSH(&stack, "Hello World");
Related
I'm trying to implement stack using linked list implementation. Its giving me "Segmentation Error". Please help me finding the error. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct NODE {
char word;
struct NODE *next;
};
struct STACK {
struct NODE *head;
int size;
};
void pushStack(struct STACK *stack, char s);
void makeStack(struct STACK *stack, char *s);
void printStack(struct STACK *stack);
int main(){
char *s;
fgets(s,100,stdin);
struct STACK stack;
stack.head = NULL;
makeStack(&stack,s);
printStack(&stack);
return 0;
}
void pushStack(struct STACK *stack, char s){
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
strcpy(temp,s);
for(int i=0; i<MAX; i++){
if(temp[i]=='\0') break;
pushStack(stack,temp[i]);
}
}
void printStack(struct STACK *stack){
struct NODE *trav = stack->head;
while (trav != NULL){
printf("%c", trav->word);
trav = trav->next;
}
}
MAX=100 is the limit I'm taking for string input. I haven't also added increasing the size because I'm just ignoring the increment of size for now. Before I could perfect the implementation
In main the s pointer is not initialized and it points nowhere.
int main(){
char *s; // <<< this is wrong, you want 'char s[100]' instead
fgets(s,100,stdin);
...
However the safest option is this:
int main(){
char s[100]; // declare array of 100 chars
fgets(s, sizeof(s), stdin); // sizeof(s) is the actual size of s (100 here)
...
This is wrong too: you store the pointer to the local variable temp, but that variables ceases to exist once you return from the pushStask function.
void pushStack(struct STACK* stack, char s) {
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
Instead you need to create a new struct NODE like this:
void pushStack(struct STACK* stack, char s) {
struct NODE* temp = malloc(sizeof *temp);
temp->word = s;
temp->next = stack->head;
stack->head = temp;
}
Instead of malloc(sizeof *temp) you could write sizeof(struct NODE), it's the same, but it's less fool proof because you could mistakenly write sizeof(struct STACK) which would compile fine, but the size of the allocated memory would be wrong.
Another problem: you don't assign the size field of the struct STACK, this is not a problem now, but it might become a problem later.
There are several drawbacks in your implementation of a stack.
The first one is that you are using a pointer with an indeterminate value to read a string
char *s;
fgets(s,100,stdin);
So the call of fgets invokes undefined behavior.
Moreover there is used a magic number 100.
You need to allocate a character array and use it to read a string.
#define MAX 100
//...
char s[MAX];
fgets( s, MAX, stdin );
Pay attention to that the name word for an object of the type char is confusing
struct NODE {
char word;
struct NODE *next;
};
You could define the structure like for example
struct NODE {
char c;
struct NODE *next;
};
or
struct NODE {
char item;
struct NODE *next;
};
Instead of separating the declaration and the initialization as you did
struct STACK stack;
stack.head = NULL;
forgetting to initialize the data member size (that by the way should have an unsigned integer type as for example size_t) you could just write for example
struct STACK stack = { NULL, 0 };
or
struct STACK stack = { .head = NULL, .size = 0 };
In the declaration of the function makeStack the second parameter should have the qualifier const because the passed string is not being changed within the function. And as a memory allocation in general can fail the function should report whether all characters of the string were pushed successfully. So the function declaration should look like
int makeStack( struct STACK *stack, const char *s );
It does not make a sense to declare a local array temp within the function
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
//...
using the index variable i is redundant. Also the function fgets can append the new line character '\n' to the input string that you should not push on stack.
The function can be defined the following way
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
if ( *s != '\n' )
{
success = pushStack( stack, *s );
}
}
return success;
}
Another approach is to remove the new line character from the input string before passing it to the function makeStack.
For example
s[ strcspn( s, "\n" ) ] = '\0';
makeStack( &stack, s );
If it is the user that is responsible whether to push the new line character on stack or not then the function makeStack can be simplified
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
success = pushStack( stack, *s );
}
return success;
}
Correspondingly the function pushStack also should be redefined.
For starters it shall dynamically allocate a new node. Otherwise you will try to add nodes that are local to the function and will not be alive after exiting the function that again results in undefined behavior.
The function pushStack can be defined the following way.
int pushStack( struct STACK *stack, char c )
{
struct NODE *temp = malloc( sizeof( struct NODE ) );
int success = temp != NULL;
if ( success )
{
temp->word = c;
temp->next = stack->head;
stack->head = temp;
++stack->size;
}
return success;
}
The parameter of the function printStack should have the qualifier const because the stack itself within the function is not being changed.
The function can be defined at least the following way
void printStack( const struct STACK *stack )
{
for ( const struct NODE *trav = stack->head; trav != NULL; trav = trav->next )
{
printf( "%c", trav->word );
}
}
This is my first time creating stacks. I'm quite clear at what I must do, but am quite discouraged by the code not working.
It runs fine till I try to retrieve any data from the root, which immediately results in a segfault.
Here's my program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stackNode
{
char letter;
struct stackNode * next;
};
int size=0;
int capacity=10;
struct stackNode * root=NULL;
void push(char data, struct stackNode * root)
{
if(size==capacity)
{
printf("Error: Stack Overflow\n");
return;
}
struct stackNode * new=(struct stackNode *)malloc(sizeof(struct stackNode *));
new->letter=data;
new->next=root;
printf("%c,%u", new->letter, new->next);
root=new;
printf("%c,%u", new->letter, new->next);
size++;
}
char pop(struct stackNode ** root)
{
if(size==0)
{
printf("Error: Stack is Empty\n");
return '\0';
}
printf("\npop*\n");
char temp;
printf("\n*\n");
struct stackNode * tempad;
printf("\n*\n");
temp=(*root)->letter;
printf("\n*\n");
tempad=*root;
printf("\n*\n");
*root=(*root)->next;
printf("\n*\n");
free(tempad);
printf("\n*\n");
size--;
return temp;
}
int main()
{
push('c', root);
push('v', root);
push('n', root);
printf("%c %c %c", pop(&root), pop(&root), pop(&root));
}
Here's the output:
pop*
*
*
Segmentation fault
Could someone point out the mistake?
The main issue is usage of unnecessary global variables which seem to be causing confusion. In push, the parameter is of type struct stackNode * yet it's being manipulated as if it referred to the global root. But root = new is purely local and has no impact on the global root. However, size++ does impact the global scope. This corrupts the stack's logical state, and your error handler at the beginning of pop thinks that size == 3 and doesn't complain. The function then dutifully dereferences root, crashing the program.
A correct stack class should not use global data. It should encapsulate all necessary state in structs. This makes it reusable, enabling creation of multiple stacks (a property I'd want in most classes I'm using).
A few other suggestions:
Avoid side effects where possible. Prints are OK for temporary debugging purposes but should be completely separated from program logic otherwise.
If you are planning on writing error handlers, print to stderr and avoid magic values like return '\0'; that might be mistaken for actual node data.
Don't cast the result of malloc. This can suppress errors and is visually noisy.
Hardcoding capacity feels pretty arbitrary. I'm not sure there's any point to having this (but if there is, add it to the struct). If there's too much metadata about the stack inside each node (ideally, there should be none), create a Stack struct to contain this metadata and point it to the actual stackNode chain.
Another stack design point: malloc/free are slow. For character data, a simple array with a top pointer will be faster and simpler to implement. You can amortize allocation calls with periodic doubling the array when top >= capacity and contracting when top < capacity / 2.
Here's a quick re-write (without the suggestion for the Stack wrapper struct or the array):
#include <stdio.h>
#include <stdlib.h>
struct stackNode {
char letter;
struct stackNode *next;
int size;
};
void push(char data, struct stackNode **root) {
struct stackNode *new = malloc(sizeof(*new));
new->size = *root ? (*root)->size + 1 : 1;
new->letter = data;
new->next = *root;
*root = new;
}
char pop(struct stackNode **root) {
if (!*root || !(*root)->size) {
fprintf(stderr, "pop from empty stack\n");
exit(1);
}
char popped = (*root)->letter;
struct stackNode *cull = *root;
*root = (*root)->next;
free(cull);
return popped;
}
int main() {
struct stackNode *root = NULL;
push('c', &root);
push('v', &root);
push('n', &root);
while (root) {
printf("%c ", pop(&root));
}
puts("");
return 0;
}
This is really confusingly written code (i.e globals with the same name as variables in the local scope). I'm just going to rewrite it, untested and on mobile but should be fine. You can diff to see the issue(s). For one thing though you're setting local variable root to the newest allocation rather than global root.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stackNode
{
char letter;
struct stackNode* prev;
};
stackNode* kTailStack = NULL;
void push(char data)
{
stackNode* p=(stackNode *)malloc(sizeof(stackNode));
p->letter=data;
p->prev=kTailStack;
kTailStack = p;
}
char pop()
{
stackNode* prev_tail = kTailStack;
char n = 0;
if (prev_tail != NULL)
{
n = prev_tail->letter;
kTailStack = prev_tail->prev;
free(prev_tail);
}
return n;
}
int main()
{
push('c', kTailStack);
push('v', kTailStack);
push('n', kTailStack);
printf("%c %c %c", pop(kTailStack), pop(kTailStack), pop(kTailStack));
}
I am having some issues with my pop() function in this program. This is an implementation of stack as singly linked list, and as you can see the pop function has two arguments:
void pop(STACK *stack, char **name)
I am told to: allocate memory for name in the pop function and return the name or NULL using the **name argument. I have tried several things, yet I don't understand what this actually means, and also how to do that since the function doesn't return anything (void type). Generally I am having trouble understanding this **name argument, and why would be we even want to use that in the first place. Here is my code so far:
typedef struct _stack STACK;
typedef struct _sElem stackElement;
struct _stack{
stackElement *head;
};
struct _sElem{
char *name;
stackElement *next;
};
//solved:
void pop(STACK *stack, char **name){
if(stack == NULL || stack->head == NULL){
printf("Stack is empty. \n");
}else{
stackElement *temp = stack->head;
char **nodeName = malloc(sizeof(char*));
char *tempName = temp->name;
(*nodeName)=tempName;
(*name) = (*nodeName);
stack->head = temp->next;
free(temp);
}
}
int main(){
STACK *myStack = NULL;
char *tempName = NULL;
push(myStack, "One");
push(myStack, "Two");
push(myStack, "Three");
pop(myStack, &tempName);
pop(myStack, &tempName);
//free stack and tempName
return 0;
}
I appreciate any help. Thanks.
Generally I am having trouble understanding this **name argument, and
why would be we even want to use that in the first place.
Because in C all parameters are passed by value. So if you your function was defined as void pop(STACK *stack, char *name) instead and you assigned the value of name inside pop it would not be visible to the caller after pop returned.
Instead, if you define your function as: void pop(STACK *stack, char **name), then you can assign to *name so the caller has access to the new value.
For instance:
STACK *head = ...
char *name = NULL;
pop(head, &name);
if (name != NULL)
{
fprintf(stdout, "Popped name: %s\n", name);
free(name);
}
I have quite interesting problem, I guess. I am trying to implement Stack in C. Here is my header and implementation file(I have only implemented Push yet):
my.h:
typedef struct {
char type[3];
int nrOfOpr;
int num;
} BizarreNumber_t;
struct stackNode {
BizarreNumber_t data;
struct stackNode *nextPtr;
};
// stack related
extern void push(struct stackNode *topPtr, BizarreNumber_t info);
my.c:
void push(struct stackNode *topPtr, BizarreNumber_t info){
struct stackNode *newTop = malloc(sizeof(struct stackNode));
struct stackNode oldTop = *topPtr;
newTop->data=info;
newTop->nextPtr=&oldTop;
*topPtr=*newTop;
// printf("topPtr->next->data: %s\n", topPtr->nextPtr->data.type);
//
// printf("oldTop->data: %s\n", oldTop.data.type);
// printf("newTop->data: %s\n", newTop->data.type);
// printf("topPtr->data: %s\n", topPtr->data.type);
}
Lastly This is my main.c:
int main(int argc, char const *argv[]) {
struct stackNode* stackHead=malloc(sizeof(struct stackNode));
BizarreNumber_t a={"sa",1,1};
BizarreNumber_t b={"as",2,2};
stackHead->data=a;
stackHead->nextPtr=NULL;
printf("%s\n", stackHead->data.type);
push(stackHead,b);
printf("%s\n", stackHead->nextPtr->data.type);//HERE!!!
return 0;
}
In main, the line that I wrote "HERE!!!" is not correctly giving true output. Actually it does not give anything. Interesting thing is, whis gives correct output:
printf("%c\n", stackHead->nextPtr->data.type[0]);
I tried to print out every character in string, Results say that String comes main fine. But I cannot see. Why is it so?
stackHead is local variable created in main() function. Whatever modification or changes done with stackHead in push() method won't affect in main() method as it just call by value.
Instead of this pass the address of stackHead to push() method as
push(&stackHead,b); /* pass the address of stackhead */
And change the definition of push() accordingly.
void push(struct stackNode **topPtr, BizarreNumber_t info){
struct stackNode *newTop = malloc(sizeof(struct stackNode));
newTop->data = info;
newTop->nextPtr = *topPtr; /*new node next make it to head node */
*topPtr=newTop; /*update the head node */
}
For a prelab (meaning it's not for a grade), I'm supposed to implement my first ever stack using linked lists. I wrote it adding only one thing to the stack just as practice, as to why it's so short. Anyway, I have no compile errors, besides it saying that "new" is uninitialized in my create_stack function. This is also where I'm getting a segmentation fault, as it's not printing out my first printf function. I am also guessing that the problem is bigger than just me initializing the stack, but this is my problem's start. Please go easy on me if it's something simple, as, like I said, it's my first time doing stacks, and thanks for your help.
#include <stdio.h>
#include <stdlib.h>
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);
char top(stack* s);
void pop(stack*s);
int main(void) {
char value, val;
stack* new = create_stack();
printf("Enter a letter: ");
scanf("%c", &value);
push(new, value);
val = top(new);
printf("%c\n", val);
pop(new);
return 0;
}
stack* create_stack(){ //initializes the stack
stack* new;
new->size = 0;
new->stack = NULL;
return new;
}
void push(stack* s, char val) {
node* temp = (node*)malloc(sizeof(node)); //allocates
if ( temp == NULL ) {
printf("Unable to allocate memory\n");
}
else{
temp->next = s->stack;
temp->data = val;
s->stack = temp;
s->size = (s->size) + 1; //bumps the counter for how many elements are in the stack
}
}
void pop(stack* s) {
node* temp;
temp = s->stack;
s->stack = temp->next;
free(temp);
s->size = (s->size) - 1; //subtracts from counter
}
char top(stack* s) {
node* temp = s->stack;
char value = temp->data;
return value;
}
The reason it crashes is that you never allocate any memory when you create the stack. Do stack* new = malloc (sizeof(stack)); in the create_stack function.
For the future you might want to use better variable names. Using for instance using new as the name for the stack isn't that good - it isn't very descriptive plus it's a reserved keyword in several languages, C++ for example.
stack *new creates a local pointer, but it has nothing to point to yet. Since you want the stack to continue to exist after the function completes, you should allocate memory for it using malloc (and eventually free it using free).
So your create_stack function should start with:
stack* new = malloc(sizeof(stack));
An alternative would be to declare the stack as a local variable in your main function, and pass it as an argument into create_stack to initialize it:
stack new;
create_stack(&new);