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);
}
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 );
}
}
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");
This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 7 years ago.
In the following program I need to pass an argument to a function using the &-operator although I expect it to be a pointer and the function is expecting a pointer. Why do I need to do this?
The program implements a simple stack using linked lists and incomplete types in C. Here are the three necessary files:
stack.h
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
struct Stack {
int number;
struct Stack *next;
};
/*
* We declare a pointer to a Stack structure thereby making use of incomplete
* types. Clients that pull in stack.h will be able to declare variables of type
* pstack which are pointers to Stack structures. */
typedef struct Stack *pstack;
bool is_empty(pstack *s);
void make_empty(pstack *s);
void push(pstack *s, int new_num);
int pop(pstack *s);
#endif /* STACK_H */
stack.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
bool is_empty(pstack *s)
{
return !s;
}
void make_empty(pstack *s)
{
if (!is_empty(s))
pop(s);
}
int pop(pstack *s)
{
struct Stack *tmp;
int i;
if (is_empty(s)) {
exit(EXIT_FAILURE);
}
tmp = *s;
i = (*s)->number;
*s = (*s)->next;
free(tmp);
return i;
}
void push(pstack *s, int new_num)
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;
}
stackclient.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main(void)
{
pstack s1;
int n;
push(&s1, 1);
push(&s1, 2);
n = pop(&s1);
printf("Popped %d from s1\n", n);
n = pop(&s1);
printf("Popped %d from s1\n", n);
exit(EXIT_SUCCESS);
}
Again, I thought that by using
typedef struct Stack *pstack;
and later on in main()
pstack s1;
I'm declaring a pointer to the linked list Stack and hence it would be fine to simply pass s1 to say push() by just using
push(s1, 1);
but I actually need to use
push (&s1, 1);
Why?
Your functions are all declared to take pstack* as an argument, which is actually a pointer to a pointer to a Stack struct. Just use pstack. You'll also need to replace the instances of (*s) with just s in the implementations of those functions.
Edit: As was pointed out in the comments, you actually write to (*s) in the function implementations and rely on this behavior for correctness, so you need to keep the argument as pstack*. Conceptually, this is because the stack variable (s1) is literally the top of the stack itself, and so must be modified by push and pop.
You need to use pstack *s ( pointer to pstack ) in void push(pstack *s, int new_num), according to your implementation code,
if to use pstack s( pstack ), the new_node will not be returned correctly.
Two possible ways to insert a Node in push():
if insert to head, it should be *s = new_node
if insert to tail, it could be s->next = new_node
Back to the code, if to use push(s1, 1); such as,
//If only use pstack s, the new_node can not be pushed.
void push(pstack s, int new_num) //it is a wrong implementation for demo
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = s;
s = new_node;// WRONG! here, the new_node cannot be kept by s
// two typical node insert ways:
// 1)if insert to head, it should be *s = new_node
// 2)if insert to tail, it could be s->next = new_node
//Now, Your code applied the #1 way, so need *s
}
So, it should be inputed pstack *s, and call with push (&s1, 1);
void push(pstack *s, int new_num)//it is the correct version the same as your post
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;//here, the new_node could be kept by *s
}
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);
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.