My program is supposed to read a postfix expression and convert it to infix and prefix using a tree implementation.
the pop() method always give the first element without errasing it and i can't figure out why. Any help will be apreciate.
//tree structur
typedef struct asa {
enum { number_exp,sous_exp_op } type;
union {
int child;
struct {
struct asa* left;
struct asa* right;
char oper; } tree;
} op;
} asa;
//stack
typedef struct stack {
int size;
struct {
asa * element;
struct stack* link;
}e;
} stack;
struct stack *top;
(...)
asa * pop(){
asa* e ;
stack * temp;
if(top->size == 0 ){
printf("ERR0R : empty stack\n");
exit (EXIT_FAILURE);
}
else if (top->size >= 1){
temp = top->e.link;
e= top->e.element;
top = temp;
}
return e;
}
void push(asa* node ){
if(top->size == 0 ){
top->e.element = node;
top->e.link = NULL;
top->size++;
}
else if (top->size > 0){
pile * next = (pile*) malloc(sizeof(top));
next = top;
top->e.element = node;
top->e.link = next;
top->size++;
}
}
Logs snapshot:
Your immediate problems are that you are discarding next as soon as you allocate it when top->size > 0 and that you are allocating the size for a pointer rather than for the whole struct. To fix them, replace next = top with top = next at the end of the function and fix the sizeof invocation:
else if (top->size > 0){
pile * next = (pile*) malloc(sizeof(*top));
next->e.element = node;
next->e.link = top;
next->size = top->size + 1;
top = next;
}
Also, this implementation of stack feels needlessly complex and error-prone. If you need the stack size, you should maintain the size independently of the nodes of the linked list, not in every individual node. The standard linked list idiom is to represent the empty list (stack) as NULL, so neither push nor pop need any extra code to check for empty stack:
typedef struct stack {
asa *element;
struct stack *next;
} stack;
void push(stack **head, asa *elem)
{
stack *new_head = malloc(sizeof(stack));
new_head->next = head;
new_head->elem = elem;
*head = new_head;
}
asa *pop(stack **head)
{
stack *old_head = *head;
asa *top_elem = old_head->elem;
*head = old_head->next;
free(old_head);
return top_elem;
}
Related
I have a list defined as
typedef struct node {
Voo *voo;
ListaReservas nodeReservas; /* Ignore this */
struct node *next;
} *Node;
I created some functions to help me add or remove nodes from the list like:
/* creates a node */
Node criaNode(Voo v) {
Node new = (Node)malloc(sizeof(struct node));
new->voo = &v;
/* I had new->voo = v; but vscode told me it was wrong so i changed it to &v */
new->next = NULL;
return new;
}
Voo is defined as:
typedef struct {
int dia;
int mes;
int ano;
} Data;
typedef struct {
int horas;
int minutos;
} Tempo;
typedef struct {
char codigo[LEN_CODIGO + 1];
char partidaID[LEN_ID + 1];
char chegadaID[LEN_ID + 1];
Data datapartida;
Tempo horapartida;
Tempo duracao;
Data datachegada;
Tempo horachegada;
int capacidade;
} Voo;
Now I wanted to iterate through the list and print its values as such
Voo *v;
for (n = headVoos; n != NULL; n = n->next) {
v = n->voo;
printf("%s %s %s %.2d-%.2d-%d %.2d:%.2d\n",
v->codigo, v->partidaID, v->chegadaID,
v->datapartida.dia, v->datapartida.mes, v->datapartida.ano,
v->horapartida.horas, v->horapartida.minutos);
}
The program is not printing correctly. For example where it should appear
AA1 AAA AAD 16-03-2022 14:50
its appearing instead
� 146187376-32765--1940381952 40355300:50
What's causing this and how can I avoid it in the future?
EDIT
After replacing in the struct node the Voo *voo definition by Voo voo, I am now getting an error in one of the auxiliary functions:
/* deletes node */
Node eliminaNode(Node head, Voo v)
{
Node n, prev;
for (n = head, prev = NULL; n != NULL; prev = n, n = n->next)
{
if (n->voo == v) /* expression must have arithmetic or pointer error */
{
if (n == head)
head = n->next;
else
prev->next = n->next;
free(n->next);
free(n);
break;
}
}
return head;
}
In criaNode you're taking the address of the parameter v and returning it from the function via a pointer to dynamic memory. That address is no longer valid after the function returns. Subsequently dereferencing that invalid address then triggers undefined behavior.
It probably makes more sense for struct node to contain a Voo directly instead of a pointer to one. So change the member to a non-pointer:
Voo voo;
And assign the parameter directly:
new->voo = v;
There are multiple problems here:
there seems to be a confusion between structures and pointers to structures. In C, you must understand the difference between manipulating objects (allocating as local objects or from the head, passing as arguments or returning as values) and pointers to objects, which are a more idiomatic as arguments to functions and allow functions to modify the object they point to.
the confusion is amplified by a very error prone construction: hiding pointers behind typedefs. Do not do that, define object types for the actual structure, using the same or a different name as the struct tag, and make all pointers explicit with the * syntax.
you pass an actual Voo object as an argument and allocate a list node using the address of this argument. This is incorrect because the argument will be discarded as soon as the function returns, makeing the list point to invalid memory and explaining the weird output you observe.
Node eliminaNode(Node head, Voo v) should take a pointer to the head node and return a success indicator. It should take a Voo * argument and it should not free(n->next) because the next node is still in use after the removal.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#define LEN_CODIGO 30
#define LEN_ID 30
typedef struct Data {
int dia;
int mes;
int ano;
} Data;
typedef struct Tempo {
int horas;
int minutos;
} Tempo;
typedef struct Voo {
char codigo[LEN_CODIGO+ 1];
char partidaID[LEN_ID + 1];
char chegadaID[LEN_ID + 1];
Data datapartida;
Tempo horapartida;
Tempo duracao;
Data datachegada;
Tempo horachegada;
int capacidade;
} Voo;
typedef struct Node {
struct Voo *voo;
//ListaReservas nodeReservas; /* Ignore this */
struct Node *next;
} Node;
/* creates a node */
Node *criaNode(Voo *v) {
/* allocation with calloc is safer as the object will be initialized to 0 */
Node *nodep = calloc(1, sizeof(*new));
if (nodep) {
nodep->voo = v;
nodep->next = NULL;
}
return nodep;
}
/* deletes node */
int eliminaNode(Node **head, Voo *v) {
for (Node *n = *head, *prev = NULL; n != NULL; prev = n, n = n->next) {
if (n->voo == v) {
if (n == *head)
*head = n->next;
else
prev->next = n->next;
free(n);
return 1; /* article was found and freed */
}
}
return 0; /* article was not found */
}
void printList(const Node *head) {
for (const Node *n = head; n != NULL; n = n->next) {
const Voo *v = n->voo;
printf("%s %s %s %.2d-%.2d-%.2d %.2d:%.2d\n",
v->codigo, v->partidaID, v->chegadaID,
v->datapartida.dia, v->datapartida.mes, v->datapartida.ano,
v->horapartida.horas, v->horapartida.minutos);
}
}
I am implementing a stack using linked list in C, and I stumbled upon two issues:
I need the stack_pop function to return a valid value temp, that is the temporary node/cell, and therefore, I can't free it. So, 1) Do you think freeing each node for every pop function call is better than until the end using the stack_destroy() 2) How can I achieve both, free(temp) and return it at the same time in stack_pop?
How bad my implementation becomes not using exit(1) in both stack_push and stack_pop functions?
This is the implementation:
//// Stack
// Linked list
typedef struct {
int data;
Cell* next;
} Cell;
struct stack_l {
size_t count;
Cell *top;
};
typedef struct stack_l *Stack;
You've got stack_pop declared to return an int, but you're attempting to return a Cell * which doesn't make sense.
Copy the value in the popped cell to a local variable, free the popped cell, then return the value.
temp = stack->top;
stack->top = stack->top->next;
temp->next = NULL;
stack->count--;
int val = temp.data;
free(temp)
return val;
Also, it makes no sense to call exit in either stack_push or stack_pop as that ends the program.
I think it is a bit overcomplicated. You only need to remember the previous stack pointer. Nothing else
typedef struct stack
{
int data;
struct stack *prev;
}stack;
stack *push(stack **sp, int data)
{
stack *new = malloc(sizeof(*new));
if(new)
{
new -> prev = *sp;
new -> data = data;
*sp = new;
}
return new;
}
int isempty(stack *sp)
{
return !stack_pointer;
}
int pop(stack **sp)
{
stack *new;
int result = 0;
if(sp && *sp)
{
result = (*sp) -> data;
new = (*sp) -> prev;
free(*sp);
*sp = new;
}
return result;
}
int main(void)
{
stack *stack_pointer = NULL;
int result;
push(&stack_pointer, 1);
push(&stack_pointer, 2);
push(&stack_pointer, 3);
do
{
result = pop(&stack_pointer);
printf("%d\n", result);
}while(stack_pointer) ;
printf("Stack was empty so the loop has exited\n");
}
This is the first time I learn programming. I'm a first year unversity student. My major is software engineering. This is my third assignment for software class.
The teacher wants this program reads in an infix expression from the command line and outputs a postfix expression. We should use "the Shunting Yard algorithm".We should have 2 linked list queue and 1 linked list stack. 2 queues for holding input and output and a stack for holding operators. We also should write general enqueue,dequeue, pop,push function that I already did.
The Shunting Yard algorithm:
put arguments into input queue
dequeue token from input queue
if oprand(number),add to output queue
if operator, the pop operators off stack and add to output queue as long as top operator on stack has higher or equal precedence, then push new operator onto stack
return to step 1 as long as tokens remain in input
pop remaining operators from stack and add to output queue
The program should operate as follows:
programename 34 / 5 + 16 * 2
postfix: 34 5 / 16 2 * +
We also should space between each output
This is so hard for me as a beginner. I already spend more than thirty hour in this program. But the program doesn't work. The program continues run in the "while" loop in main function and never stop. I would be very aprciate if someone can help me.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct listnode {
//Define structure of the node
char *element;
struct listnode* pnext;
};
struct Stack {
//Define structure of the stack
struct listnode* ptop;
};
struct Queue {
//Define structure of the queue
struct listnode* pfront;
struct listnode* prear;
};
void push (struct Stack* stack,char* element);
char* pop (struct Stack* stack);
void enqueue(struct Queue* queue,char* element);
char* dequeue(struct Queue* queue);
void s_travel(struct Stack* stack);
void q_travel(struct Queue* stack);
int precedence(char* x);
int empty(struct Stack* stack);
char* peek(struct Stack* stack);
int main (int argc,char *argv[]) {
struct Stack stack;
struct Queue input_queue;
struct Queue output_queue;
stack.ptop = NULL;
input_queue.pfront = NULL;
input_queue.prear = NULL;
output_queue.pfront = NULL;
output_queue.prear = NULL;
if (argc<3) {
//If the arguments is less then 3, unavailable input
printf("Input error");
return -1;
}
int i=0;
//Put all the arguments into the input_queue
for (i=1;i<argc;i++) {
enqueue(&input_queue,argv[i]);
}
printf("infix expression is : ");
q_travel(&input_queue);
printf("at the beginning, the peek of the stack is %s \n",peek(&stack));
for (i=1;i<argc;i++) {
//Token from input_queue
char *token;
char *x;
token = dequeue(&input_queue);
if(atof(token)) {
//If the element is a number,put it into output_queue
enqueue(&output_queue,token);
}
else {
/*If the element is a operator, c
* ompare the precedence of the top element of the stack and the precedence of token element
*/
char *peek1;
peek1=peek(&stack);
while ((precedence(peek1) >= precedence(token)) && (peek1 != NULL)){
/*while the precedence of the top element of the stack is greater
and equal to the precedence of token element*/
printf("inside,the top of the stack is %s \n",peek1);
//Pop element out of the stack and put it into output_queue
x = pop(&stack);
printf("after pop,x is %s,the top of the stack is %s \n",x,peek1);
enqueue(&output_queue,x);
}
//Then, push the new operator(token) into the stack
push(&stack,token);
}
}
while(peek(&stack)!=NULL) {
//Enqueue remaining operator from stack into output_queue
char *elem = pop(&stack);
enqueue(&output_queue,elem);
}
printf("Postifx expression is :\n");
q_travel(&output_queue);
return 0;
}
void push (struct Stack* stack,char* element) {
//Allocate a new node
struct listnode* new_node = (struct listnode *)malloc(sizeof(struct listnode));
new_node->element = element;
//Add new node at the top of the stack
new_node->pnext = stack->ptop;
stack->ptop = new_node;
}
char* pop (struct Stack* stack_buffer) {
//If the stack is not empty
if (stack_buffer->ptop) {
//Create a temporary node to replace top(removed) node
struct listnode *pelem = stack_buffer->ptop;
//The top pointer points to the next node
stack_buffer->ptop = pelem->pnext;
//Store the element of the removed node
char *elem = pelem->element;
//Remove node from memory
free(pelem);
//Return the element of the node that we removed
return elem;
}
//If the stack is empty, removing element fails,return -1
else {
return NULL;
}
}
void enqueue(struct Queue* queue,char *element) {
//Allocate a new node
struct listnode *new_node = (struct listnode *)malloc(sizeof(struct listnode));
new_node->element = element;
new_node->pnext = NULL;
//If the queue is not empty,add new node at the end of the queue
if (queue->prear) {
queue->prear->pnext = new_node;
}
//If the queue is empty,add new node at front of the queue
else {
queue->pfront = new_node;
}
//Added node becomes new rear node
queue->prear = new_node;
}
char* dequeue(struct Queue* queue) {
/*Create a temporary node to replace the front node of the queue
struct listnode *pelem = queue->pfront;*/
//If the queue is not empty
if (queue->pfront) {
//Store the element of the front node
char *elem = queue->pfront->element;
//The front pointer points to the next node
queue->pfront = queue->pfront->pnext;
//If the queue only has one node
if(pelem == queue->prear) {
//After removing the only node, the queue becomes empty
queue->prear = NULL;
}
//Remove node from memory
free(pelem);
//Return the element of the node that we removed
return elem;
}
//If the queue is empty, removing node fails,return NULL
else {
return NULL;
}
}
void s_travel(struct Stack* buffer) {
//Function to print out the element in the stack
//Create a temporary node to replace the top node of the stack
struct listnode* elem = buffer->ptop;
while(elem != NULL) {
printf("%s ", elem->element);
elem = elem->pnext;
}
printf("\n");
}
void q_travel(struct Queue* buffer) {
//Function to print out the element in the queue
//Create a temporary node to replace the front node of the stack
struct listnode* elem = buffer->pfront;
while(elem != NULL) {
printf("%s ", elem->element);
elem = elem->pnext;
}
printf("\n");
}
int precedence(char* operator) {
/*Function to determine the precedence of the operator,prior operator has greater return value*/
printf("entering precedence with %s \n",operator);
if (operator == NULL) {
return -1;
}
else if (strcmp(operator,"(")==0){
printf("Pr: %s 0\n",operator);
return 0;
}
else if (strcmp(operator,"+")==0||strcmp(operator,"-")==0) {
printf("Pr: %s 1\n",operator);
return 1;
}
else if ( (strcmp(operator,"*")==0) || (strcmp(operator,"/")==0) || (strcmp(operator,"%")==0) || (strcmp(operator,"x")==0) ) {
printf("Pr: %s 2\n",operator);
return 2;
}
else {
return -2;
}
return -3;
}
int empty(struct Stack* stack) {
//Function to check if the stack is empty
//If the stack is empty, the return value would be 1;otherwise, it would be 0
return NULL == stack->ptop;
}
char* peek(struct Stack* stack) {
//Function to find out the top element of the stack
//If the stack is empty, return NULL
if (empty(stack)) {
return NULL;
}
//If the stack is not empty, return the top element of the stack
char* elem = stack->ptop->element;
return elem;
}
I use nested structure to define the linked-list queue:
queue.h:
#define QUEUE_MAX_SIZE 4096
struct QUEUE_NODE {
char *string;
struct QUEUE_NODE *next;
}queue_node;
struct COMMON_QUEUE {
struct QUEUE_NODE *q_node;
}common_queue;
=================================
queue.c:
/* here I define the operations */
struct COMMON_QUEUE *C_init_queue() {
struct QUEUE_NODE *head;
head = malloc(sizeof(struct QUEUE_NODE));
if (head==NULL) {
fprintf(stderr, "Insufficient memory!!!");
return NULL;
}
struct COMMON_QUEUE *new_queue;
new_queue = malloc(sizeof(struct COMMON_QUEUE));
if (new_queue==NULL) {
fprintf(stderr, "Insufficient memory!!!");
return NULL;
}
head->next = NULL;
head->string = NULL;
new_queue->q_node = head;
return new_queue;
}
int C_get_queue_length(struct COMMON_QUEUE *q) {
int count;
count = 0;
while (q->q_node->next!=NULL) {
count += 1;
q->q_node = q->q_node->next;
}
return count;
}
int C_enqueue(struct COMMON_QUEUE *q, char *in) {
if (C_get_queue_length(q)>=QUEUE_MAX_SIZE) {
fprintf(stderr, "Linked queue is full!!!");
return ERROR;
}
struct QUEUE_NODE *new_node;
new_node = malloc(sizeof(struct QUEUE_NODE));
if (new_node==NULL) {
return ERROR;
}
new_node->next = NULL;
new_node->string = NULL;
while (q->q_node->next!=NULL) {
q->q_node = q->q_node->next;
}
new_node->next = q->q_node->next;
q->q_node->next = q->q_node;
new_node->string = in;
return OK;
}
but when I use it in the main program, then it jumps into a endless loop, after backtracing, and I knew the problem is at:
while (q->q_node->next!=NULL) {
count += 1;
q->q_node = q->q_node->next;
}
but it seems correct, but I may make some mistake on my initialization of the two nested struct!
P.S. the I did not list the "free()".
This loop modifies the list while it traverses it. Specifically, it replaces q->q_node with q->q_node->next, which if nothing else will discard your entire loop.
while (q->q_node->next!=NULL) {
count += 1;
q->q_node = q->q_node->next;
}
If you want to correctly traverse the list, you need to declare a separate pointer that you use for traversal. Something like this:
int C_get_queue_length(struct COMMON_QUEUE *q) {
int count;
struct COMMON_QUEUE *p = q->q_node;
count = 0;
while (p->next != NULL) {
count += 1;
p = p->next;
}
return count;
}
The pointer p will step along the list without modifying the q_node pointers along the way.
You have a similar error in C_enqueue. You really want to use a separate pointer to walk the list, and not assign q->q_node during traversal. You can fix your C_enqueue similarly:
p = q->q_node;
while (p->next != NULL) {
p = p->next;
}
p->next = new_node; /* append the new node after where the list traversal stopped */
new_node->next = NULL; /* always NULL, because you always insert at the end */
One problem with your code is that your iterations through the queue are destructive: rather than using a temporary variable to iterate your linked list, you perform the iteration using the q_node itself. This leads to C_get_queue_length calls effectively destroying the queue, without freeing its nodes (a memory leak).
Here is an example of how to iterate a list non-destructively, using your "get length" method:
int C_get_queue_length(struct COMMON_QUEUE *q) {
int count;
count = 0;
struct QUEUE_NODE node = q->q_node;
while (node->next != NULL) {
count++;
node = node->next;
}
return count;
}
Your decision to pre-allocate one node when creating a queue is also questionable: it appears that the head node is unused, and also excluded from the count. This makes it easier to write the code to insert and delete nodes, but the same could be done with an extra level of indirection (i.e. a pointer to a pointer).
Disclaimer: This is for an assignment. I am not asking for explicit code answers, only help understanding why my code isn't working.
I am trying to implement a basic Binary Search Tree, but I am having problems with my _addNode(...) function.
Here's the problem. When I walk through my code with the debugger, I notice that leaf nodes are created infinitely on both sides (left and right) so aside from the creation of the root, there is never any point when a leaf node is NULL. The problem is that I am asking my program to create a new node whenever it finds a NULL value where a leaf would be. Therefore, if there are never any NULL values, there will never be any new leaves created, right?
The other issue I'm running into is with my compare(...) function. Stepping through it in the debugger shows it to iterate through the function several times, never actually returning a value. When it returns to the calling function, it drops back into the compare(...) function and loops infinitely. Again, I don't know why this is happening considering I have valid return statements in each if statement.
Here is all the code you'll probably need. If I left something out, let me know and I'll post it.
struct Node {
TYPE val;
struct Node *left;
struct Node *right;
};
struct BSTree {
struct Node *root;
int cnt;
};
struct data {
int number;
char *name;
};
int compare(TYPE left, TYPE right)
{
assert(left != 0);
assert(right != 0);
struct data *leftData = (struct data *) left;
struct data *rightData = (struct data *) right;
if (leftData->number < rightData->number) {
return -1;
}
if (leftData->number > rightData->number) {
return 1;
} else return 0;
}
void addBSTree(struct BSTree *tree, TYPE val)
{
tree->root = _addNode(tree->root, val);
tree->cnt++;
}
struct Node *_addNode(struct Node *cur, TYPE val)
{
assert(val != 0);
if(cur == NULL) {
struct Node * newNode = malloc(sizeof(struct Node));
newNode->val = val;
return newNode;
}
if (compare(val, cur->val) == -1) {
//(val < cur->val)
cur->left = _addNode(cur->left, val);
} else cur->right = _addNode(cur->right, val);
return cur;
}
Edit: Adding the below function(s)
int main(int argc, char *argv[])
{
struct BSTree *tree = newBSTree();
/*Create value of the type of data that you want to store*/
struct data myData1;
struct data myData2;
struct data myData3;
struct data myData4;
myData1.number = 5;
myData1.name = "rooty";
myData2.number = 1;
myData2.name = "lefty";
myData3.number = 10;
myData3.name = "righty";
myData4.number = 3;
myData4.name = "righty";
/*add the values to BST*/
addBSTree(tree, &myData1);
addBSTree(tree, &myData2);
addBSTree(tree, &myData3);
addBSTree(tree, &myData4);
/*Print the entire tree*/
printTree(tree);
/*(( 1 ( 3 ) ) 5 ( 10 ))*/
return 1;
}
Maybe you could try setting right and left to NULL right after malloc:
struct Node * newNode = malloc(sizeof(struct Node));
newNode->left = NULL;
newNode->right = NULL;
Check this line here (or the corresponding for left):
cur->right = _addNode(cur->right, val);
If cur->right == 0, it's fine. But if cur->right != 0, the node that was sitting there will be replaced by the return value of _addNode, which ultimately is not a whole branch, but just one node.
I like to explicitly 0-out values in a struct after a malloc using memset(newNode, 0, sizeof(struct Node)). Others might disagree.