Generic variable tree Error infinity loop - c

I am creating a variable tree, but I've got an error, seemingly in the insert or print_wevr function.
When I run the program I get an infinite loop.
How can I go about this?
/*5 - VarTrees*/
/*var_trees.c*/
#include <stdio.h>
#include <stdlib.h>
#include "var_trees.h"
/*Defining the struture of variable tree.
* The nodes has tree fields:
info: an generic information
first: the first child-node
next: the next sibling-node
*/
struct var_tree{
void* info;
Var_Tree* first;
Var_Tree* next;
};
/*Create the tree*/
Var_Tree* create(void* info)
{
Var_Tree* t = (Var_Tree*) malloc(sizeof(Var_Tree));
t->info = info;
t->first = NULL;
t->next = NULL;
return t;
}
/*Insert a node*/
void insert(Var_Tree* t,Var_Tree* st)
{
st->next = t->first;
t->first = st;
}
/*go_through the tree*/
void go(Var_Tree* t, void (*cb)(void*))
{
Var_Tree* p;
cb(t->info);
for(p = t->first; p != NULL; p = p->next)
go(t,cb);
printf(">");
}
/*Remove a node*/
//void remov(Var_Tree* t, void* info);
/*5 - VarTrees*/
/*main.c*/
#include <stdio.h>
#include <stdlib.h>
#include "var_trees.h"
Var_Tree* create_int(int info)
{
return create(&info);
}
void print_int(void* info)
{
int* t = (int*) info;
printf("<%d",*t);
}
int main(void)
{
Var_Tree* a = create_int(4);
Var_Tree* b = create_int(3);
Var_Tree* c = create_int(23);
Var_Tree* d = create_int(1);
Var_Tree* e = create_int(2);
insert(a,b);
go(a,print_tree);
}
The function create_int is a function for creating a node with the field info as int.
print_int is a callback function that prints an integer (the '<' creates a type of textual notation for trees).

Here in go function, you are making a recursive call without changing the parameters that eventually lead to infinite recursion.
void go(Var_Tree* t, void (*cb)(void*))
{
Var_Tree* p;
cb(t->info);
for(p = t->first; p != NULL; p = p->next)
go(t,cb); //<-----here you are calling the same
function with the same parameter that leads to an infinite loop
printf(">");
}
You should pass the value of p in place of t.
void go(Var_Tree* t, void (*cb)(void*))
{
Var_Tree* p;
cb(t->info);
for(p = t->first; p != NULL; p = p->next)
go(p,cb); //<----change t to p
printf(">");
}

Related

Why does pointer to custom struct doesn't work here?

Why pointer to custom struct doesn't work in that code?
Why I'm getting warning in that line with p->x = x?
Why I'm getting second warning in line with strcpy_s?
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct sptr {
int x;
char* s;
struct sptr* next;
} ptr;
void add(ptr* p, int x, const char* s) {
ptr* o = p;
p = (ptr*) malloc(sizeof(ptr));
p->x = x; // warning
p->s = (char*)malloc(20 * sizeof(char));
strcpy_s(p->s, 20, (char*)s); // warning
p->next = o;
}
void show(ptr* p) {
ptr* o = p;
while (o != NULL) {
printf("%d %s\n", o -> x, o -> s);
o = o->next;
}
}
int main() {
ptr* p = NULL;
add(p, 5, "xcvxvxv");
add(p, 7, "adadad");
show(p);
return 0;
}
Pointers are values.
add is receiving a copy of the NULL pointer value. Changing the local variable p, in add, to a new pointer value returned by malloc does not change the separate, local variable p in main.
Just as if you wanted to change the value of an int in the caller's scope, you'd use an int * argument:
void change(int *val)
{
*val = 10;
}
int main(void)
{
int a = 5;
change(&a);
}
Changing the value of an int * in the caller's scope would require an int ** argument.
#include <stdlib.h>
void change(int **val)
{
*val = malloc(sizeof **val);
}
int main(void)
{
int *a;
change(&a);
}
This extends to any type.
malloc can fail, and return NULL. Performing indirection on a NULL pointer value is Undefined Behaviour.
You must guard against this happening by checking the return value of malloc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node {
int x;
char *s;
struct node *next;
} Node;
void add(Node **p, int x, const char *s) {
Node *new_node = malloc(sizeof *new_node);
if (!new_node) {
perror("allocating node");
exit(EXIT_FAILURE);
}
new_node->s = malloc(1 + strlen(s));
if (!new_node->s) {
perror("allocating node string");
exit(EXIT_FAILURE);
}
new_node->x = x;
strcpy(new_node->s, s);
new_node->next = *p;
*p = new_node;
}
void show(Node *p) {
while (p) {
printf("%d %s\n", p->x, p->s);
p = p->next;
}
}
int main(void) {
Node *list = NULL;
add(&list, 5, "xcvxvxv");
add(&list, 7, "adadad");
show(list);
}
Why pointer to custom struct doesn't work in that code?
TBD
Why I'm getting warning in that line with p->x = x?
Why I'm getting second warning in line with strcpy_s?
2 warnings occur because code de-referenced the pointer from malloc() without first checking if the pointer might be NULL.

What is wrong with my linked list, and why won't it properly set my head to NULL in C?

This is my program I have written in C, I created a structure and a head and I am trying to make a linked list, but I keep getting read access violations and it seems I am not passing in my head pointer properly and it keeps having problems when it is trying to add to my list.
#define _CRT_SECURE_NO_WARNINGS // Since I want to strictly use ANSI C and not Microsoft C without getting the warning message, I'm adding this line of code before I include header files.
#include <stdio.h> // "#include" includes the contents of another file, commonly called header file, into the source code file.
#include <string.h> // This library contains a variety of functions to manipulate strings.
#include <stdlib.h> // Header file which has the necessary information to include the input/output related functions in our program.
#define MAX 100
typedef struct node {
char model[MAX];
float price;
int miles;
struct node *next;
} *NODEPTR;
NODEPTR getNode();
void freeNode(NODEPTR p);
void printTotalMiles(NODEPTR);
void addLast(NODEPTR *list, char c[], float pri, int num);
int main(void) { //It is the first function of every C program that is responsible for starting the execution and termination of the program.
int i = 0;
NODEPTR head = NULL;
if (head == NULL) {
printf("NULL");
}
//head = (NODEPTR) malloc(sizeof(struct node));
//head->next = NULL;
//addFront(head, 2600.00, 48000);
//addFront(head, 1400.00, 22000);
//printf("first, %d", head->price);
addLast(head, "64 Impala", 1800.00, 12000);
addLast(head, "56 Ford", 500.00, 23000);
//printTotalMiles(head);
//printArray(p);
return 0; // This statement indicates "main()" is returning the value 0 upon completion.
} // Curly brace marks the end of the function.
NODEPTR getNode(void) {
NODEPTR p;
p = (NODEPTR)malloc(sizeof(struct node));
if (p == NULL) {
printf("List Overflow.");
}
return (p);
}
void freeNode(NODEPTR p) {
free(p);
}
void addFront(NODEPTR *list, float pri, int num) {
NODEPTR p, q;
p = getNode();
//strcpy(p->model, c);
// memset(p->model, '\0', sizeof(c))
//printf("%s\n", p->model);
p->price = pri;
p->miles = num;
p->next = *list;
*list = p;
q = *list;
printf("hey %.2f hey\n", q->price);
}
void printTotalMiles(NODEPTR *list) {
int total = 0;
NODEPTR p;
while (*list) {
p = *list;
printf(" Car: \tPrice: %.2f\tI drove it: %d\n", p->price, p->miles);
total += p->miles;
list = p->next;
}
printf("The Total Miles: %d", total);
}
void addLast(NODEPTR *list, char c[], float pri, int num) {
NODEPTR p, q;
p = getNode();
memset(p->model, '\0', sizeof(c));
strcpy(p->model, c);
p->price = pri;
p->miles = num;
p->next = NULL;
if (*list == NULL) {
*list = p;
} else {
q = *list;
while (q->next) {
q = q->next;
}
q->next = p;
}
}
//void printArray(struct node cars[]) { //function definition
// break;
//}
How can I get it so I can properly add nodes to this list?
I just want it to add nodes to the list with the character, float and int. I tried messing with the pointers, I tried setting head first and setting head->next to null as well but nothing seems to work. It keeps having errors every time it tries to deal with the null.
void addLast(NODEPTR* list, char c[], float pri, int num);
addLast wants a pointer to pointer (read Is it a good idea to typedef pointers?), but you pass a single pointer here:
addLast(head, "64 Impala", 1800.00, 12000);
addLast(head, "56 Ford", 500.00, 23000);
switch to
addLast(&head, "64 Impala", 1800.00, 12000);
addLast(&head, "56 Ford", 500.00, 23000);
And here:
void addLast(NODEPTR* list, char c[], float pri, int num) {
NODEPTR p, q;
p = getNode();
memset(p->model, '\0', sizeof(c));
strcpy(p->model, c);
sizeof(c) is the size of a pointer (read What is ‘array decaying’ in C?).
Use the size of the member, in this case MAX:
memset(p->model, '\0', MAX);
or better yet: delete the whole line, you don't need it if you call strcpy on the next line.
One more:
void printTotalMiles(NODEPTR* list) {
differs from the propotype:
void printTotalMiles(NODEPTR);
Compile with warnings.

Inserting nodes in a linked list in decreasing order - C

I have to make a list that arrange the people in decreasing order of their number('no' for my program). I tryed to make it by modifying the addNode function but I got no result(peoples do not arrange by their number). This is my code:
Header code:
#ifndef __EX__
#define __EX__
typedef struct Person{
char name[10];
float no;
struct Person *pNext;
} NODE, *pNODE, **ppNODE;
void addNode(ppNODE, pNODE);
void travers(pNODE, unsigned int*);
#endif
Functions folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
void addNode (ppNODE ppPrim, pNODE p){
pNODE q = (pNODE)malloc(sizeof(NODE));
assert(q!=NULL);
printf("Add name: \n");
scanf("%s", &q->name);
printf("\nAdd no: ");
scanf("%f", &q->no);
if (p == NULL || q->no < p->no) {
q->pNext = *ppPrim;
*ppPrim = q;
} else {
q->pNext = p->pNext;
p->pNext = q;
}
return;
}
void travers(pNODE pPrim, unsigned int *pLen){
*pLen = 0;
pNODE tmp = pPrim;
while (tmp != NULL){
puts (tmp->name);
fprintf(stdout, " no %.2f\n", tmp->no);
tmp = tmp->pNext;
(*pLen)++;
}
return;
}
Main folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
int main(){
unsigned int len;
pNODE prim = NULL;
int i;
for (i=0; i<=1; i++){
addNode(&prim, prim);
addNode(&prim, prim->pNext);
}
travers(prim, &len);
return 0;
}
When you insert a new node to the list, you must traverse the list until you find a suitable place to insert it. Your code takes a second argument, which isn't really needed and causes confusion, and only looks at that.
The code to insert a code q at the end of a list that is defined by its head is:
Node *prev = NULL;
Node *p = *head;
while (p) {
prev = p;
p = p->pNext;
}
q->pNext = p;
if (prev == NULL) {
*head = q;
} else {
prev->pNext = q;
}
You can get rid of keeping track of the previous node and the distinction between inserting at the head and inserting after that by traversing the list with a pointer to node pointer:
Node **p = &head;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
In this concise code, p holds the address of the head at first and the address of the pNext pointer of the previous node. Both can be updated via *p.
You can now use this code to traverse only as far as the numbers associated with each node are smaller than the one of the node to insert. here's a complete program:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Node Node;
void addNode(Node **p, const char *name, float no);
void travers(Node *pPrim, unsigned int *pLen);
struct Node {
char name[10];
float no;
Node *pNext;
};
void addNode(Node **p, const char *name, float no)
{
Node *q = malloc(sizeof(*q));
assert(q != NULL);
snprintf(q->name, sizeof(q->name), "%s", name);
q->no = no;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
}
void traverse(const Node *pPrim, unsigned int *pLen)
{
*pLen = 0;
while (pPrim != NULL) {
fprintf(stdout, "%-12s%.2f\n", pPrim->name, pPrim->no);
pPrim = pPrim->pNext;
(*pLen)++;
}
}
int main()
{
unsigned int len;
Node *prim = NULL;
addNode(&prim, "Alice", 0.23);
addNode(&prim, "Bob", 0.08);
addNode(&prim, "Charlie", 0.64);
addNode(&prim, "Dora", 0.82);
traverse(prim, &len);
printf("\n%u entries.\n", len);
return 0;
}
Things to node:
I've used Node * and Node ** instead of the typedeffed pNODE and ppNODE. In my opinion using the C pointer syntax is clearer.
You should separate taking user input from adding a node.
In your code you shouldn't pass the address of the char array when scanning a string, just the char array. (It happens to work, but it isn't correct. The compiler should warn you about that.)

Issue when printing Linked List

I am trying to create a linked list of 5 nodes and print them. I don't know why I cannot see the result when printing the linked list even though I do not get errors and I am sure my structure is fine. I only see blank screen. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct msg *M;
struct msg{
double id;
M next;
};
M queue;
void new_msg(double id);
void printList();
void main()
{
double r;
srand(0);
for(int i=0;i<5;i++){
r = rand() % 100;
new_msg(r);
}
printList(); // PRINT DOES NOT SHOW RESULTS :(
}
void printList()
{
M temp;
while (temp->next != NULL){
temp = temp->next;
printf("MSG ID:%6.3f \n", temp->id);
}
}
void new_msg(double id)
{
M m;
if(queue == NULL)
{
m = malloc(sizeof(struct msg));
}
else
{
m= queue;
queue = queue->next;
}
m->id = id;
m->next = NULL;
}
The both functions are invalid and have undefined behaviour at least because in the both functions there is an attempt to write to or read from a non-allocated memory.
Try the following
void printList()
{
for ( M temp = queue; temp != NULL; temp = temp->next; )
{
printf("MSG ID:%6.3f \n", temp->id);
}
}
void new_msg(double id)
{
M m = malloc( sizeof( struct msg ) );
if ( m != NULL)
{
m->id = id;
m->next = queue;
queue = m;
}
}
Take into account that though some compilers allow to use the main declaration with the return type void nevertheless such a declaration is not C compliant.
You should write
int main( void )
The problem is, inside new_msg() function, you define a local variable m, which is never stored and the global queue never gets updated. In every call, queue gets equal to NULL.
Next, in your printList() function,
temp is unitialized
while (temp->next != NULL) is likely to evaluate to false in very first iteration.
Assuming new_msg is correct, you are printing a list of pointers into nothingness, probably resulting in a core dump.
Your M temp; is not initialized. You probably want:
M temp = queue;

Create and traverse a binary tree recursively in C

I want to create a binary tree and traverse it by preorder traversal, and I use recursive method. These code can be compiled but can not run correctly, and I found it maybe can not finish the CreateBitree() function, but I don't know where the problem is.
#include <stdio.h>
#include <malloc.h>
typedef struct BiNode{
int data;
struct BiNode *lchild;
struct BiNode *rchild; //left and right child pointer
}BiNode;
int CreateBiTree(BiNode *T);
int TraverseBiTree(BiNode *T);
int main() {
BiNode *t;
CreateBiTree(t);
TraverseBiTree(t);
return 0;
}
int CreateBiTree(BiNode *T) { //create a binary tree by preorder traversal
char tmp;
scanf("%c", &tmp);
if(tmp == ' ')
T = NULL;
else {
T = (BiNode *)malloc(sizeof(BiNode));
T -> data = tmp;
CreateBiTree(T -> lchild);
CreateBiTree(T -> rchild);
}
return 1;
}
int TraverseBiTree(BiNode *T) { //traverse a binary tree by preorder traversal
if(T != NULL) {
printf("%c\n", T -> data);
TraverseBiTree(T -> lchild);
TraverseBiTree(T -> rchild);
}
return 1;
}
For example, when I input a preorder sequence like "ABC##DE#G##F###"("#"means space), and then it still let me to input, I think the TraverseBiTree() function hasn't been executed.
An assignment of a pointer value to a pointer within a function does not have any effect outside the scope of that function. Doing this:
int CreateBiTree(BiNode *T) {
/* ... */
T = NULL;
is same as doing this:
int func(int i) {
/* ... */
i = 0;
A pointer to the argument is necessary in these cases:
int CreateBiTree(BiNode **T) {
/* ... */
T[0] = NULL; // or... *T = NULL;
With some changes to the initial code:
int main() {
BiNode *t;
CreateBiTree(&t);
TraverseBiTree(t);
return 0;
}
int CreateBiTree(BiNode **T) { //create a binary tree by preorder traversal
char tmp;
scanf("%c", &tmp);
if(tmp == ' ')
T[0] = NULL;
else {
T[0] = (BiNode *)malloc(sizeof(BiNode));
T[0]-> data = tmp;
CreateBiTree(&(T[0]->lchild));
CreateBiTree(&(T[0]->rchild));
}
return 1;
}

Resources