problem in creating binary search tree in c language - c

This code creates a binary search tree but it
runs sometimes normally and sometimes makes errors, even without changing anything in the code.
I can't get why this happening, what's the mistake ?
Even I changed the function that I used to create the tree from recursive to iterative but the same results.
#include <stdio.h>
#include <stdlib.h>
typedef struct sommet{
struct sommet * fg;
int val;
struct sommet * fd;
}sommet;
typedef sommet* ptrm;
ptrm creearbre(ptrm arbre,int ele);
void impression(ptrm arbre);
ptrm creearbre_rec(ptrm arbre,int ele);
int main()
{
ptrm arbre=NULL;
int tarbre,n;
printf("entre la taille de l'arbre:");
scanf("%d",&tarbre);
for(int i=0;i<tarbre;i++)
{
printf("entre l'element %d: ",i+1);
scanf("%d",&n);
arbre=creearbre_rec(arbre,n);
}
impression(arbre);
return 0;
}
ptrm creearbre_rec(ptrm arbre,int ele)
{
if(arbre==NULL)
{
arbre=malloc(sizeof arbre);
arbre->val=ele;
arbre->fd=NULL;
arbre->fg=NULL;
}
else if(arbre->val > ele)
arbre->fg=creearbre_rec(arbre->fg,ele);
else
arbre->fd=creearbre_rec(arbre->fd,ele);
return arbre;
}
void impression(ptrm arbre){
if(arbre != NULL){
printf(" %d -->", arbre->val);
impression(arbre->fg);
impression(arbre->fd);
}
}
ptrm creearbre(ptrm arbre,int ele){
ptrm p,q=arbre,r=NULL;
p=malloc(sizeof arbre);
p->val=ele;
p->fd=NULL;
p->fg=NULL;
if(arbre==NULL){
arbre=p;
}
else{
while(q!=NULL){
r=q;
if(ele > q->val)
q=q->fd;
else
q=q->fg;
}
if(ele > r->val)
r->fd=p;
else
r->fg=p;
}
return arbre;
}

The program has undefined behavior due to using an invalid size in the allocation of memory in statements
arbre=malloc(sizeof arbre);
and
p=malloc(sizeof arbre);
There are allocated memory for pointers instead of objects of the structure type.
You need to write
arbre=malloc(sizeof *arbre);
p=malloc(sizeof *arbre);

Related

C function that creates a linked list with "divisible by 3" numbers from another linked list

First, I need to create and show a list that ends with number 1000. That works well.
Then, I want to create another list with only the numbers that are divisible by 3 in the first list, but it doesn't work.
The worst thing is that it doesn't even tell me what's going on. It just gives error in the execution but the console doesn't say anything.
I will really appreciate any help.
I tried all.
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define CANTIDAD_NUMEROS 13
#define CANTIDAD_NUMEROS2 6
#define DESDE 1
#define HASTA 10
typedef struct lista{
int num;
struct lista *sig;
}nodo;
void crear (nodo *pt, int, int);
void crear2 (nodo *pt, int, nodo *pt2);
void mostrar(nodo *pt);
int main()
{
int i=0;
int t=0;
nodo *prin;
nodo *prin2;
prin=(nodo*)malloc(sizeof(nodo));
prin2=(nodo*)malloc(sizeof(nodo));
crear(prin,i, t); //creates first list
mostrar (prin); //shows first list
crear2(prin,i, prin2); //gets 'divisible by 3' numbers
mostrar(prin2); // shows second list
return 0;
}
//creates list
void crear (nodo *registro, int cont, int t)
{
scanf("%d", &t);
registro->num = t;
if (registro->num == 1000)
registro->sig=NULL;
else
{
registro->sig=(nodo*)malloc(sizeof(nodo));
cont++;
crear (registro->sig,cont, t);
}
return;
}
//shows list
void mostrar (nodo *registro)
{
if (registro->sig !=NULL)
{
printf ("%d\n",registro->num);
mostrar (registro->sig);
}else{
printf("%d\n",registro->num);
}
return;
}
//creates second list with only numbers that are divisible by 3
void crear2 (nodo *registro, int cont, nodo *registroNuevo)
{
if ((registro->num % 3) == 0){
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
}
if(registro->sig != NULL){
crear2(registro->sig,cont, registroNuevo->sig);
}else{
return;
}
}
I expect to have the 1st list shown (which it's happening) and also the 2nd list shown with the numbers that are divisible by 3, which doesn't happen.
First of all, I admire your dedication to recursion!
The problem is that in crear2, registroNuevo->sig is uninitialized which causes a segfault. I almost always start a function that operates on a recursive linked data structure by checking if the parameter node is null. If so, I can safely continue on with the body of the function. Following this logic of protecting against nulls, we need to pass the registroNuevo node along without touching it in the case when registro->num % 3 != 0 and ensure all of its fields are initialized.
Here's the corrected function:
void crear2(nodo *registro, int cont, nodo *registroNuevo)
{
if (registro) {
if (registro->num % 3 == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = NULL;
if (registro->sig) {
registroNuevo->sig = malloc(sizeof(nodo));
}
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
crear2(registro->sig, cont, registroNuevo);
}
}
}
Having said that, this function is still a bit less than ideal for a couple reasons. First of all, the name is vague and could describe the behavior better. Also, if there are no items divisible by three, you've got a malloced node back in the calling scope that never gets initialized, so it's a bit brittle in that regard. Thirdly, even with a parameter, it feels like a highly specific function without much reusability factor that could be written iteratively inside the calling scope like:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo
{
int num;
struct nodo *sig;
} nodo;
nodo *crear(nodo *registro, int num)
{
nodo *n = malloc(sizeof(nodo));
n->num = num;
n->sig = registro;
return n;
}
void mostrar(nodo *registro)
{
if (registro)
{
printf("%d->", registro->num);
mostrar(registro->sig);
}
else puts("");
}
void free_lista(nodo *registro)
{
if (registro)
{
free_lista(registro->sig);
free(registro);
}
}
int main()
{
nodo *prin = NULL;
nodo *prin_div_3 = NULL;
for (int t; scanf("%d", &t) && t != 1000;)
{
prin = crear(prin, t);
}
nodo *tmp = prin;
while (tmp)
{
if (tmp->num % 3 == 0)
{
prin_div_3 = crear(prin_div_3, tmp->num);
}
tmp = tmp->sig;
}
mostrar(prin);
mostrar(prin_div_3);
free_lista(prin);
free_lista(prin_div_3);
return 0;
}
This isn't perfect--without tail nodes, adding to the list is a bit less than ideal, but dangling heads are eliminated, and hopefully it shows an alternate approach to organizing program logic and functions.
A few other remarks:
Always free memory that you've allocated. You can write a simple recursive routine to do so, like free_lista as shown in the above example.
Consider avoiding highly specific functions with hard-coded values like 3 and 1000. Make these parameters to maximize reusability.
crear2 never uses the cont member, and you have global constants that are unused. It's a good idea to clean these up to help clarify your debugging efforts and reduce visual clutter.
No need to cast the result of malloc.
if (registro->sig !=NULL) as the first line of a function is going to crash on a null. You don't need != NULL either. if (registro) { ... } is clearest and avoids problems with null parameters.
void crear2 (nodo *registro, int cont, nodo *registroNuevo) {
if ((registro->num % 3) == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo);
}
}
This is my approach, but you are still getting a final unexpected 0 at the last mostrar() call; and you still need to do the 'free' calls. I think you should avoid the recursive calls, there are easier ways to do it. Saludos.

can i use -> in c? that bring me an error

i wrote this code for the university its an exercise to practice lists and sublists and i can't run it.
#include <stdio.h>
#include <stdlib.h>
typedef struct nodito{
int dato;
struct nodito *sig;}nodito;
typedef struct nodito * Sublista;
typedef struct nodo{
char nombre[10];
Sublista sub;
struct nodo *sig;}nodo;
typedef struct nodo *TLista;
void cargoL(TLista *L){
FILE *arch;
TLista nuevo,ant,act;
Sublista nuevito;
arch=fopen("texto.txt","rt");
if (arch==NULL){
printf("archivo no existe \n");
}
else{
while(!feof(arch)){
nuevo=(TLista)malloc(sizeof(nodo));
fscanf(arch,"%s %d",(nuevo->nombre),& (nuevo->sub->dato));
if ( *L==NULL || strcmp((*L)->nombre,nuevo->nombre)>0){
nuevo->sig=*L;
*L=nuevo;
nuevo->sub->sig=NULL;
}
else{
ant=NULL;
act=*L;
while ( act!=NULL && strcmp(act->nombre,nuevo->nombre)<=0){
ant=act;
act=act->sig;
}
if (act!=NULL && strcmp(act->nombre,nuevo->nombre)==0){
nuevito=(Sublista)malloc(sizeof(nodito));
nuevito->dato=nuevo->sub->dato;
free(nuevo);
nuevito->sig=act->sub;
act->sub=nuevito;
}
else{
ant->sig=nuevo;
nuevo->sig=act;
}
}
}
}
fclose(arch);
}
the line nuevo->sub->sig=NULL bring me an error
same for fscanf(arch,"%s %d",(nuevo->nombre),& (nuevo->sub->dato))
can i use the double ->?
is that the problem?
can anybody help me?
You allocated memory for nuevo using malloc, but you never allocated memory for sub inside nuevo.
You tried dereferencing it in fscanf and the statement where you set it to NULL.
A simple fix would be to allocate space for sub as
nuevo->sub = malloc(sizeof(*Sublista));
Both your errors should disappear now.
Do remember to free sub before you free nuevo.

Linked list sort from smallest to biggest

I am trying sort a number in a linked list from small to big.
But its not working !
the debugger says there are a problem when i put the second number into the
list ( in main )but i dont know why .
Any help ?
#include<stdio.h>
#include<stdlib.h>
typedef struct list list;
struct list{
int a;
list *nxt;
};
void sort(list *l){
int temp,tp;
list *AIDE,*k;
k=AIDE=(list*)malloc(sizeof(list));
while (l->nxt!= NULL)
{
while (l->nxt->a < l->a)
{
temp=l->a;
l=l->nxt;
l->nxt->a=temp;
l=l->nxt;
while (l->a < AIDE->nxt->a )
{
tp=AIDE->a;
AIDE->a=l->a;
AIDE->nxt->a=tp;
AIDE=AIDE->nxt;
}
}
l=l->nxt;
}
while (k->nxt!= NULL)
{
l->a=k->a;
l=l->nxt;
k=k->nxt;
}
l->nxt=NULL;
}
int main() {
list *t,*s;
int n,i,c=0;
printf("\n how many number you need to enter? ");
scanf("%d",&n);
s=t=(list*)malloc(sizeof(list)*n);
while (c!=n)
{
printf("\n Donner le nb %d :",c+1);
scanf("%d",&t->a);
t=t->nxt;
c++;
}
t->nxt=NULL;
sort(s);
while (t->nxt!=NULL)
{
printf("%d",t->a);
}
return 0;
}
In the loop where you have the problem, what do you think the expression t=t->nxt would do?
When you enter the loop, t is pointing to allocated but uninitialized memory, therefore dereferencing e.g. t->nxt will lead to undefined behavior.
A simple solution would be to e.g. do
t->nxt = t++ + 1;

including header file in two .c files

The program should save a couple of points and put them out on request.
The program contains one .h file and two .c files.
This is the compiler info i get:
prog.c:46:25: fatal error: pointstack.h: No such file or directory #include "pointstack.h"
What did I miss?
//File: pointStack.h - Headerfile
#ifndef POINTSTACK_H
#define POINTSTACK_H
#include <stdio.h>
#include <stdlib.h>
//structs
//struct for coordinates
struct point
{
float rX;
float rY;
float rZ;
};
typedef struct point POINT;
struct stackPoint
{
POINT p;
struct stackPoint *next;
};
typedef struct stackPoint STACK_POINT;
typedef STACK_POINT *STACK_POINT_PTR;
//functions
void push(POINT pushPoint);
POINT pop();
int isEmpty();
void printStackElement(POINT aPoint);
#endif
//File: pointstack.c - functions of stack program
#include "pointstack.h"
//global variable
STACK_POINT_PTR stackTop = NULL;
void push(POINT pushPoint)
{
//temporary variable
STACK_POINT_PTR stackPoint = (STACK_POINT_PTR) malloc(sizeof(STACK_POINT));
//in case there is not enough memory
if(stackPoint == NULL)
{
printf("not enough memory ... End \n");
exit(1);
}
//save point
stackPoint->p = pushPoint;
stackPoint->next = stackTop;
stackTop = stackPoint;
return;
}
POINT pop()
{
//save stackTop and nextStackTop
STACK_POINT firstStackPoint = *stackTop;
free(stackTop);
stackTop = firstStackPoint.next;
return firstStackPoint.p;
}
int isEmpty()
{
if(stackTop == NULL)
{
return 1;
}
else {
return 0;
}
}
void printStackElement(POINT aPoint)
{
printf("Point x: %f, Point y: %f, Point z: %f \n", aPoint.rX, aPoint.rY, aPoint.rZ);
return;
}
//File: stackmain.c
#include "pointstack.h"
void exit(int);
POINT readPoint()
{
POINT userPoint;
printf("x-coordinate \n");
scanf("%62f", &userPoint.rX);
printf("y-coordinate \n");
scanf("%62f", &userPoint.rY);
printf("z-coordinate \n");
scanf("%62f", &userPoint.rZ);
return userPoint;
}
int main(void)
{
//declaration
char cCmd;
printf("’p’ for input, ’q’ for output: \n");
while(1)
{
scanf("%c", &cCmd);
if(cCmd == 'p')
{
push(readPoint());
printf("’p’ for input, ’q’ for output: \n");
}
if(cCmd == 'q')
{
while(!isEmpty())
{
printStackElement(pop());
}
break;
}
}
return 0;
}
What you missed is that your file is called pointStack.h with a capital S, not pointstack.h with a lower case s.

c doubly-linked list display method showing redundant elements

I have a small doubly-linked list application. I want to add elements inside the list and then display the list normally. At the output i get my inserted elements allright, but after them i get a bunch of strange numbers( such as .... 28482 -20048 2817 ...... )
I believe it's a problem of space allocation.
Any help is appreciated, thanks in advance!
# include <stdio.h>
# include <conio.h>
# include <string.h>
# include <stdlib.h>
typedef struct elem {
int number;
struct elem * urm;
struct elem * prec;
}nod;
nod *prim=NULL,*ultim=NULL, *local=NULL, *p=NULL;
void insert_element(int numb){
nod *local=(nod *)malloc(sizeof(nod));
local->number = numb;
if (prim==NULL){
prim=local;
ultim=local;
}
else{
ultim->urm = local;
local->prec = ultim;
ultim=local;
}
}
void load_data()
{
int i,n;
nod *c = (nod *)malloc(sizeof(nod));
printf("\n cate elemente va avea lista?");
scanf("%d", &n);
printf("avem %d elemente", n);
for(i=1;i<=n;i++){
printf("\n number: ");
scanf("%d", &c->number);
insert_element(c->number);
}
}
void list_left_to_right()
{
nod *p = (nod*) malloc(sizeof(nod));
p=prim;
while(p){
printf("%d ", p->number);
p=p->urm;
}
printf("\n");
}
int main()
{
int op;
do{
printf("\n1.Enter some data\n");
printf("2.Display left - > right the data\n");
printf("0.Exit\n");
printf("choice : ");
scanf("%d",&op);
switch(op){
case 1: load_data(); break;
case 2: list_left_to_right(); break;
case 0: break;}
}
while (op!=0);
return 0;
}
(1) You have a memory leak in list_left_to_right():
nod *p = (nod*) malloc(sizeof(nod));
p=prim;
This leaks the block returned by malloc().
(2)
void insert_element(int numb) {
nod *local=(nod *)malloc(sizeof(nod));
local->number = numb;
// TODO: set local->urm and local->prec to NULL
if (prim==NULL) {
prim=local;
ultim=local;
OK, so the first time insert_element() is called, the new element is both the head and the tail.
Bug: You need to set the urm and prec fields to NULL. They have undefined values initially.
}
else {
ultim->urm = local;
local->prec = ultim;
ultim=local;
}
}
After that, the subsequent elements are inserted as a new tail (ultim).
Bug: But again you need to make sure that local->urm is set to NULL.

Resources