I have the following stack implementation using doubly linked list, and I want to use a second stack inside the reverse function but I get errors. how to do that, let's say I want to return s2.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
} Node;
//---------------------Stack---------------------
typedef struct Stack {
int size;
Node* head;
Node* tail;
int top;
} Stack;
const Stack stack_init = { .size = 0, .head = NULL, .tail = NULL, .top = -1 };
Node* create_node(int elm) {
Node* node = malloc(sizeof * node);
if (!node) return node;
node->data = elm;
node->prev = NULL;
node->next = NULL;
return node;
}
int is_empty_s(Stack *s) {
return s->tail == NULL;
}
void push(Stack *s, int elm) {
Node* updated_head = create_node(elm);
if (!s->head) {
s->head = updated_head;
s->tail = s->head;
} else {
updated_head->next = s->head;
s->head->prev = updated_head;
s->head = updated_head;
}
s->size++;
s->top = s->head->data;
}
int pop(Stack *s) {
if (!is_empty_s(s)) {
Node* node = s->head;
int elm = node->data;
s->head = s->head->next;
if (s->head) {
s->head->prev = NULL;
s->top = s->head->data;
}
else {
s->tail = NULL;
s->top = -1;
}
s->size--;
free(node);
return elm;
}
}
Stack* reverse_s(Stack *s) { // iterative: using another stack, queue
Stack *s2 = stack_init;
while (s->tail) {
push(s2, pop(s));
}
return s2;
}
int main() {
Stack s1 = stack_init;
// Queue queue1 = queue_init; { .size = 0, .head = NULL, .tail = NULL, .front = -1 };
push(&s1, 5);
push(&s1, 4);
return 0;
}
As you can see the reverse function is not yet completed, I am new to C and this syntax I don't know how to handle it.
In reverse_s, s2 is of type pointer-to-Stack. stack_init has the structure type Stack. The assignment of a Stack value to a Stack * variable is incompatible.
A few options for reverse_s:
Return a Stack structure.
Stack reverse_s(Stack *s) {
Stack s2 = stack_init;
while (s->tail)
push(&s2, pop(s));
return s2;
}
Return a pointer-to-Stack, dynamically allocating memory for the structure.
Stack *reverse_s(Stack *s) {
Stack *s2 = malloc(sizeof *s2);
*s2 = stack_init;
while (s->tail)
push(s2, pop(s));
return s2;
}
Modify the original structure.
void reverse_s(Stack *s) {
Stack s2 = stack_init;
while (s->tail)
push(&s2, pop(s));
memcpy(s, &s2, sizeof *s);
}
Related
I am attempting to create a queue using a linked list in C. I am using two structs to represent the queue and each node which are as follows.
#define DATA_MAX 100
struct QueueNode_ch
{
struct QueueNode_ch* next;
char data[(DATA_MAX + 1)];
};
typedef struct QueueNode_ch QueueNode_ch;
struct Queue_ch
{
struct QueueNode_ch* front;
struct QueueNode_ch* rear;
int count;
};
typedef struct Queue_ch Queue_ch;
I then use these the following functions to initialize the queue and the nodes.
int initQueue_ch(Queue_ch* q)
{
q = (Queue_ch*)malloc(sizeof(Queue_ch));
q->count = 0;
q->front = NULL;
q->rear = NULL;
return 0;
}
int initQueueNode_ch(QueueNode_ch* node)
{
node = (QueueNode_ch*)malloc(sizeof(QueueNode_ch));
node->next = NULL;
node->data[0] = '\0';
return 0;
}
Upon running my enqueue function I get a seg fault due to a strcpy function and when debugging gdb says it cannot access the memory of the node I am attempting to add. The enqueue code is as follows:
int enqueue_ch(Queue_ch* q, char* data)
{
if(strlen(data) > (DATA_MAX + 1))
return 1;
QueueNode_ch* tmp;
initQueueNode_ch(tmp);
strncpy(tmp->data, data, DATA_MAX);
if(isEmpty_queue_ch(q))
q->rear = q->front = tmp;
else
{
q->rear->next = tmp;
q->rear = tmp;
}
q->count++;
return 0;
}
I will also include my main function as additional information.
#include <stdio.h>
#include "Queue.h"
int main()
{
Queue_ch* queue;
initQueue_ch(queue);
enqueue_ch(queue, "hello");
return 0;
}
As far as I can tell there should be plenty of space to copy the given string to the node. Would anyone have any idea what is failing and possible fixes?
As others have mentioned, you're passing your structs by value. In C, the proper way to do this is with a pointer to a pointer. Note that I haven't tried compiling this, but hopefully the idea is clear.
int initQueue_ch(Queue_ch** q)
{
*q = (Queue_ch*)malloc(sizeof(Queue_ch));
(*q)->count = 0;
(*q)->front = NULL;
(*q)->rear = NULL;
return 0;
}
int initQueueNode_ch(QueueNode_ch** node)
{
*node = (QueueNode_ch*)malloc(sizeof(QueueNode_ch));
(*node)->next = NULL;
(*node)->data[0] = '\0';
return 0;
}
The function initQueue_ch does not make sense.
int initQueue_ch(Queue_ch* q)
{
q = (Queue_ch*)malloc(sizeof(Queue_ch));
q->count = 0;
q->front = NULL;
q->rear = NULL;
return 0;
}
The function parameter q is a local variable of the function. Changing the variable within the function does not have effect on the argument supplied to the function.
Moreover there is also no sense to allocate a queue dynamically. The function can look the following way
void initQueue_ch( Queue_ch *q )
{
q->count = 0;
q->front = NULL;
q->rear = NULL;
}
And in main you could write
Queue_ch queue;
initQueue_ch( &queue );
The same problem exists with the function initQueueNode_ch
int initQueueNode_ch(QueueNode_ch* node)
{
node = (QueueNode_ch*)malloc(sizeof(QueueNode_ch));
node->next = NULL;
node->data[0] = '\0';
return 0;
}
Again the function deals with a copy of the value of the passed argument. Changing the copy does not influence on the original argument.
The function is in whole does not make sense. What you need is a function that allocates a new node.
It can look for example the following way
QueueNode_ch * createQueueNode_ch( const char *data )
{
QueueNode_ch *node = malloc( sizeof( QueueNode_ch ) );
if ( node != NULL )
{
node->next = NULL;
strcpy( node->data, data );
}
return node;
}
The function enqueue_ch that has the same drawback of passing a pointer to a queue by value can look like
int enqueue_ch( Queue_ch *q, const char *data )
{
int success = strlen( data ) < DATA_MAX + 1;
if ( success )
{
QueueNode_ch *node = createQueueNode_ch( data );
success = node != NULL;
if ( success )
{
if ( q->rear == NULL )
{
q->front = q->rear = node;
}
else
{
q->rear = q->rear->next = node;
}
++q->count;
}
}
return success;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DATA_MAX 100
struct QueueNode_ch
{
struct QueueNode_ch* next;
char data[(DATA_MAX + 1)];
};
typedef struct QueueNode_ch QueueNode_ch;
struct Queue_ch
{
struct QueueNode_ch* front;
struct QueueNode_ch* rear;
int count;
};
typedef struct Queue_ch Queue_ch;
void initQueue_ch( Queue_ch *q )
{
q->count = 0;
q->front = NULL;
q->rear = NULL;
}
QueueNode_ch * createQueueNode_ch( const char *data )
{
QueueNode_ch *node = malloc( sizeof( QueueNode_ch ) );
if ( node != NULL )
{
node->next = NULL;
strcpy( node->data, data );
}
return node;
}
int enqueue_ch( Queue_ch *q, const char *data )
{
int success = strlen( data ) < DATA_MAX + 1;
if ( success )
{
QueueNode_ch *node = createQueueNode_ch( data );
success = node != NULL;
if ( success )
{
if ( q->rear == NULL )
{
q->front = q->rear = node;
}
else
{
q->rear = q->rear->next = node;
}
++q->count;
}
}
return success;
}
void deleteQueue_ch( Queue_ch *q )
{
while ( q->front != NULL )
{
QueueNode_ch *node = q->front;
q->front = q->front->next;
free( node );
}
q->rear = q->front;
q->count = 0;
}
int main(void)
{
Queue_ch queue;
initQueue_ch( &queue );
enqueue_ch( &queue, "hello" );
deleteQueue_ch( &queue );
return 0;
}
int initQueue_ch(Queue_ch* q)
{
q = (Queue_ch*)malloc(sizeof(Queue_ch));
q->count = 0;
q->front = NULL;
q->rear = NULL;
return 0;
}
This function is unusable. It ignores the value of q passed into it and does not return a pointer to the queue it initialized. C is strictly pass by value.
int main()
{
Queue_ch* queue;
initQueue_ch(queue);
enqueue_ch(queue, "hello");
return 0;
}
This code never gives queue any value and passes a garbage value to initQueue_ch (which it ignores) and then a garbage value to enqueue_ch.
If you are initializing using malloc() then return the pointer() instead of passing pointer to function like following.
struct wordlist* wordlist_create(void)
{
struct wordlist* wordListPtr = (struct wordlist*) malloc(sizeof(struct wordlist));
wordListPtr->count = 0;
wordListPtr->root = getTrieNode();
return wordListPtr;
}
I'm failing to see why the messageSize is printing 0 when calling removeNode, especially since it has no problem getting and printing the message. The printf in insertNode is printing the size correctly. This might just be a simple oversight. Not sure.
struct qnode {
char message[256];
int mesglen;
struct qnode * next;
};
struct qheader {
struct qnode * front;
struct qnode * last;
};
struct qheader queue;
void insertNode() {
struct qnode newnode;
char * buffer = "hello";
strcpy(newnode.message, buffer);
printf("insert size: %ld\n", strlen(buffer)); // 5
newnode.mesglen = (int)strlen(buffer);
struct qnode * curnode = queue.front;
if (curnode == NULL) {
queue.front = &newnode;
queue.last = &newnode;
} else {
while (curnode->next != NULL) {
curnode = curnode->next;
}
curnode->next = &newnode;
queue.last = &newnode;
}
}
void removeNode() {
char message[256] = {0};
int messageSize;
if (queue.front == NULL) {
printf("queue empty\n");
} else {
strcpy(message, queue.front->message);
messageSize = queue.front->mesglen;
queue.front = queue.front->next;
printf("MESSAGE: %s\n", message);
printf("MESSAGESIZE: %d\n", messageSize);
}
}
int main() {
insertNode();
removeNode();
return 0;
}
And the output:
insert size: 5
MESSAGE: hello
MESSAGESIZE: 0
I have to make linked lists that contain all the non zero values from an array and print it out. However, my code is printing out the same value for how many non zero elements there are in the array.
The creation of the linked list and printing of the linked list are two separate functions.
The addLink function creates the linked list
void addlink(DataPtr *start, int element, double value) {
Data last = *start;
Data newPtr;
newPtr = malloc(sizeof(Data));
newPtr->element = element;
newPtr->usage = value;
newPtr->next = NULL;
if(*start == NULL) {
*start = newPtr;
return;
newPtr->element = element;
newPtr->usage = value;
newPtr->next = NULL;
}
while(last->next != NULL) {
last = last->nextPtr;
last->next = newPtr;
return;
}
}
The print function prints the linked list
void print(Data *start) {
Data current = *start;
while(current != NULL) {
printf("%d ", current->element);
printf("%.3lf", current->value);
current = current->next;
}
printf("\n");
}
This is how i call it in my main
for(k = 0; k < 50; k++) {
if(values[k] != 0) {
value = values[k];
addlink(&start,k,value);
print(&start);
}
}
struct data{
int element;
double value;
struct data *next;
};
typedef struct data Data;
typedef Data *DataPtr;
DataPtr start = NULL;
Here is correct implementation of your list:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
typedef struct data {
int element;
double value;
struct data *next;
} data_t;
void print(data_t *start);
void addlink(data_t **start, int element, double value);
int main()
{
int values[50] = { 0 };
int value = 0;
int k;
data_t *start = NULL;
//Give values some value
values[0] = 100;
values[1] = 250;
for(k = 0; k < 50; k++)
{
if(values[k] != 0)
{
value = values[k];
addlink(&start,k,value);
print(start);
}
}
}
void addlink(data_t **start, int element, double value)
{
data_t *newPtr;
newPtr = malloc(sizeof(data_t));
newPtr->element = element;
newPtr->value = value;
*start = newPtr;
}
void print(data_t *start)
{
data_t *current = start;
while(current != NULL)
{
printf("%d ", current->element);
printf("%f", current->value);
current = current->next;
}
printf("\n");
}
Your DataPtr idea, is no good. The "data_t" implementation is generally what you will see when seeing linked lists. It is easiest implemented this way.
If you are trying to implement a list that adds the newest data_t to the end of the list...
Check out http://www.learn-c.org/en/Linked_lists for further explanation.
A correct function implementation can look the following way
int addlink( DataPtr *start, int element, double value )
{
DataPtr newPtr = malloc(sizeof(Data));
int success = newPtr != NULL;
if ( success )
{
newPtr->element = element;
newPtr->value = value;
newPtr->next = NULL;
while ( *start != NULL ) start = &( *start )->next;
*start = newPtr;
}
return success;
}
If you want to add new elements at the beginning of the list then the function can look like
int addlink( DataPtr *start, int element, double value )
{
DataPtr newPtr = malloc(sizeof(Data));
int success = newPtr != NULL;
if ( success )
{
newPtr->element = element;
newPtr->value = value;
newPtr->next = *start;
*start = newPtr;
}
return success;
}
As for showed by you the function implementation then it shall not even compile. For example in this code snippet
Data last = *start;
Data newPtr;
newPtr = malloc(sizeof(Data));
the expression *start has the type DataPtr while the initialized variable last has the type Data. The same problem exists for the variable newPtr.
The function print can look like
void print( DataPtr *start )
{
for ( DataPtr current = *start; current != NULL; current = current->next )
{
printf("%d ", current->element);
printf("%.3lf", current->value);
}
printf("\n");
}
And it is called like
print( &start );
Why my code is getting crushed when I'm running it. It says passing incompatible pointer type passing in Push() function. How to solve this problem?
Here is the code of my implementation in C. Here is a quick summery How I tried to solve the problem.
First I created a struct for Stack
Wrote Push and Pop function for stack
Wrote a struct for Queue
First Stack for EnQueue and Second Stack for DeQueue operation.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct Stack {
int data;
struct Stack *next;
};
struct Stack *CreateStack () {
return NULL;
}
int isEmptyStack(struct Stack *top) {
return (top == NULL);
}
void Push(struct Stack **top, int data) {
struct Stack *newNode = (struct Stack*) malloc(sizeof(struct Stack));
if(!newNode)
return;
newNode->data = data;
newNode->next = *top;
*top = newNode;
}
int Pop(struct Stack **top) {
struct Stack *temp;
int data;
if(isEmptyStack(*top)) {
printf("Empty Stack.\n");
return INT_MIN;
}
temp = *top;
data = (*top)->data;
*top = (*top)->next;
free(temp);
return data;
}
struct Queue {
struct Stack *S1;
struct Stack *S2;
};
struct Queue *CreateQueue() {
return NULL;
}
void EnQueue(struct Queue *Q, int data) {
Push(Q->S1, data);
}
int DeQueue(struct Queue *Q) {
if(!isEmptyStack(Q->S2)) {
return Pop(Q->S2);
}
else {
while(!isEmptyStack(Q->S1)) {
Push(Q->S2, Pop(Q->S1));
}
return Pop(Q->S2);
}
}
int main() {
struct Queue *Q = CreateQueue();
Q->S1 = Q->S2 = NULL;
EnQueue(Q, 1);
EnQueue(Q, 2);
EnQueue(Q, 3);
printf("%d ", DeQueue(Q));
printf("%d ", DeQueue(Q));
printf("%d ", DeQueue(Q));
return 0;
}
Three problems:
a) calling Push - wrong parameter type: struct Stack **top expected not astruct Stack *top
b) calling Pop - wrong parameter type: struct Stack **top expected not astruct Stack *top
c) Queue *CreateQueue - memory not allocated
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct Stack {
int data;
struct Stack *next;
};
struct Stack *CreateStack () {
return NULL;
}
int isEmptyStack(struct Stack *top) {
return (top == NULL);
}
void Push(struct Stack **top, int data) {
struct Stack *newNode = (struct Stack*) malloc(sizeof(struct Stack));
if(!newNode)
return;
newNode->data = data;
newNode->next = *top;
*top = newNode;
}
int Pop(struct Stack **top) {
struct Stack *temp;
int data;
if(isEmptyStack(*top)) {
printf("Empty Stack.\n");
return INT_MIN;
}
temp = *top;
data = (*top)->data;
*top = (*top)->next;
free(temp);
return data;
}
struct Queue {
struct Stack *S1;
struct Stack *S2;
};
struct Queue *CreateQueue() {
struct Queue *newNode = (struct Queue *) malloc(sizeof(struct Queue ));
return newNode;
}
void EnQueue(struct Queue *Q, int data) {
Push(&Q->S1, data);
}
int DeQueue(struct Queue *Q) {
if(!isEmptyStack(Q->S2)) {
return Pop(&Q->S2);
}
else {
while(!isEmptyStack(Q->S1)) {
Push(&Q->S2, Pop(&Q->S1));
}
return Pop(&Q->S2);
}
}
int main() {
struct Queue *Q = CreateQueue();
Q->S1 = Q->S2 = NULL;
EnQueue(Q, 1);
EnQueue(Q, 2);
EnQueue(Q, 3);
printf("%d ", DeQueue(Q));
printf("%d ", DeQueue(Q));
printf("%d ", DeQueue(Q));
return 0;
}
Output:
1 2 3
just revising C here. I just ran valgrind and it turns out i have memory leaks in my program, even though i free the memory i allocate. What am i missing?
stack.c:
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
struct node {
int element;
Node *next;
};
struct stack {
Node *tos;
};
Stack *stack_create() {
Stack *S;
if ((S = (Stack *)malloc(sizeof(Stack))) != NULL)
S->tos = NULL;
return S;
}
void stack_destroy(Stack *S) {
Node *temp = S->tos;
while (S->tos != NULL) {
temp = S->tos;
free(S->tos);
S->tos = temp->next;
}
free(S);
}
void push(Stack *S, int element) {
Node *N;
if ((N = (Node *)malloc(sizeof(Node))) != NULL) {
N->element = element;
N->next = (S->tos == NULL) ? NULL : S->tos;
S->tos = N;
}
}
int pop(Stack *S) {
Node *tos = S->tos;
S->tos = tos->next;
return (int) tos->element;
}
int peek(Stack *S) {
return (int) S->tos->element;
}
void to_string(Stack *S) {
Node *cursor = S->tos;
while (cursor != NULL) {
printf("[%d] ", cursor->element);
cursor = cursor->next;
}
printf("\n");
}
int main()
{
Stack *S;
S = stack_create();
push(S, 5);
push(S, 6);
push(S, 4);
push(S, -55);
to_string(S);
printf("Pop %d\n", pop(S));
printf("Pop %d\n", pop(S));
to_string(S);
stack_destroy(S);
return 0;
}
the actual problem is your Pop kills the node, but it doesn't free it
Node* node_destroy(Node* n)
Node* next;
if(n == NULL) return NULL;
next = n->next;
free(n);
return next;
}
int stack_pop(Stack *s) {
int element;
if(s == NULL || s->tos == NULL) return 0; // no really good result you can give
element = s->tos->element;
s->tos = node_destroy(s->tos);
return element;
}
then you can do
void stack_destroy(Stack *S) {
while (S->tos != NULL) {
s->tos = node_destroy(s->tos);
}
free(S);
}
The problem is in your destroy method. You free S->tos which temp refers to. Then you use temp->next.
set temp to S->tos->next.
The problem is with your destory:
void stack_destroy(Stack *S) {
Node *temp = S->tos;
while (S->tos != NULL) {
temp = S->tos;
free(S->tos);
S->tos = temp->next;
}
free(S);
}
Temp is pointing to S->tos from:
temp = S->tos;
But then you immediately free it after:
free(S->tos);
Then when you call the temp->next; temp is already freed.
Try this:
void stack_destroy(Stack *S) {
Node *temp; //Also, no need to assign here from the original (you assign to it immediately within the while)
while (S->tos != NULL) {
temp = S->tos->next; //You need to get the pointer to node "next" before you free S->tos
free(S->tos);
S->tos = temp;
}
free(S);
}
EDIT1: Per Keith Nicholas - See here for his elegant solution
Pop also does not free the node you extract the element from:
old:
int pop(Stack *S) {
Node *tos = S->tos;
S->tos = tos->next;
return (int) tos->element;
}
new:
int pop(Stack *S) {
Node *tos = S->tos;
int element = tos->element;
S->tos = tos->next;
free(tos);
return element;
}