Erreur de segmentation (core dumped) + encoder avec accents

Résolu/Fermé
darkin - 9 déc. 2022 à 22:31
 darkin - 11 déc. 2022 à 18:51

Bonjour à tous,

Je viens vers vous car j'ai une erreur de segmentation (core dumped) lorsque ma fonction RechercheArbre2 se lance. Je n'arrive pas à savoir quand est-ce que j'arrive dans l'erreur dans ma fonction.

Je me demandais également s'il était possible de faire en sorte que tout ce qui écrit et enregistré gardent les accents ? Si oui comment. Par exemple dans mon fichier CSV j'ai le mot "évadé", je souhaiterai qu'ils gardent bien les accents, et lorsque je le recherche avec un mon arbre de recherche en écrivant "évadé" qu'il le retrouve bien car ce sont les mêmes caractères.

Voici mon code :

#include <SDL2/SDL.h>
#include <stdio.h>
#include <SDL2/SDL_image.h>
#include <stdlib.h>
#include <time.h>
#define G_MAX_LEN_WORDS 20
#define G_MAX_WORDS     587

// Créer un Noeud
struct Noeud {
    char trad_anglais[20];
    char mot_francais[20];
    char lien_image[20];
    struct Noeud *left;
    struct Noeud *right;
};

//int max(int a, int b);
int max(int a, int b) {
    return (a > b) ? a : b;
}
// Calcul hauteur
int HauteurArbre(struct Noeud *N) {
    if (N == NULL) return -1;
    else return max(HauteurArbre(N->left),HauteurArbre(N->right))+1;
}



// Create a Noeud
struct Noeud *CreerNoeud(char trad_anglais[],char mot_francais[], char lien_image[]) {
    struct Noeud *Noeud = (struct Noeud *) malloc(sizeof(struct Noeud));
    strcpy(Noeud->trad_anglais,trad_anglais);
    strcpy(Noeud->mot_francais,mot_francais);
    strcpy(Noeud->lien_image,lien_image);
    Noeud->left = NULL;
    Noeud->right = NULL;
    return (Noeud);
}

// Right rotate
struct Noeud *rotationDroite(struct Noeud *N) {
    struct Noeud *y = N->left;
    struct Noeud *N2 = y->right;

    y->right = N;
    N->left = N2;

    return y;
}

// Left rotate
struct Noeud *rotationGauche(struct Noeud *N) {
    struct Noeud *y = N->right;
    struct Noeud *N2 = y->left;

    y->left = N;
    N->right = N2;

    return y;
}

// Get the balance factor
int ecart(struct Noeud *N) {
    if (N == NULL)
        return 0;
    return HauteurArbre(N->left)-HauteurArbre(N->right);
}

// Insert Noeud
struct Noeud *ajoutNoeud(struct Noeud *Noeud,char trad_anglais[],char mot_francais[], char lien_image[]) {
    // place le nouveau Noeud au bon endroit
    if (Noeud == NULL)
        return (CreerNoeud(trad_anglais,mot_francais,lien_image));

    if (strcmp(mot_francais,Noeud->mot_francais)<0)
        Noeud->left = ajoutNoeud(Noeud->left,trad_anglais,mot_francais,lien_image);
    else if (strcmp(mot_francais,Noeud->mot_francais)>0)
        Noeud->right = ajoutNoeud(Noeud->right,trad_anglais,mot_francais,lien_image);
    else
        return Noeud;
   
    //équilibrage
    int balance = ecart(Noeud);
    if (balance > 1 && strcmp(mot_francais,Noeud->left->mot_francais)<0) 
        return rotationDroite(Noeud);

    if (balance < -1 && strcmp(mot_francais,Noeud->right->mot_francais)>0)
        return rotationGauche(Noeud);

    if (balance > 1 && strcmp(mot_francais,Noeud->left->mot_francais)>0) {
        Noeud->left = rotationGauche(Noeud->left);
        return rotationDroite(Noeud);
    }

    if (balance < -1 && strcmp(mot_francais,Noeud->right->mot_francais)<0) {
        Noeud->right = rotationDroite(Noeud->right);
        return rotationGauche(Noeud);
    }

    return Noeud;
}

// Print the tree
void printPreOrder(struct Noeud *root) {
    if (root != NULL) {
        printf("f=%s \n", root->mot_francais);
        printf("a=%s \n", root->trad_anglais);
        printf("l=%s \n", root->lien_image);
        printPreOrder(root->left);
        printPreOrder(root->right);
    }
    else{
        EXIT_SUCCESS;
    }
}

char** chargementMotFR(){
    char tmp[90];
    FILE * fichier=fopen("mot.csv","r");
	// La zone de travail (le damier)
	char* work = malloc(G_MAX_WORDS * (G_MAX_LEN_WORDS + 1) * sizeof(*work));
	if (work == NULL) return NULL;

	// Les pointeurs pointant vers chaque "mot" de la zone de travail
	char** tabs=malloc(G_MAX_WORDS * sizeof(*tabs));
	if (tabs == NULL) {
	    free(work);
	    return NULL;
	}

	// Nécessité de faire pointer chaque "pointeur" vers la bonne position dans le damier
	for (size_t i=0; i < G_MAX_WORDS; i++) tabs[i]=work + i * (G_MAX_LEN_WORDS + 1);
	// Remplissage
    int cpt=0;

    if (fichier==NULL) printf("Erreur d'ouverture de fichier");   
    else{	   
        while (fgets(tmp,90,fichier)!=NULL){
            char * pch=strtok(tmp,",");
            char * tmpS;
            while (pch!=NULL){
                tmpS=strtok(pch," ");
                strcpy(tabs[cpt],tmpS);
                pch=strtok(NULL,",");
            }
        cpt++;
        }
    }
	return tabs;
}

struct Noeud * chargementDonnee(struct Noeud* A){ 
    char tmp[90];
    char fr[20],en[20],lien[35];
    FILE* fichier=fopen("mot.csv","r");
    if (fichier==NULL)
        printf("Erreur d'ouverture de fichier \n");
    else {
        while(fgets(tmp,90,fichier)!=NULL){
            for (int i=0; i<strlen(tmp);i++)
            {
                if (tmp[i]==',') tmp[i]=' ';
            }
            sscanf(tmp,"%s%s%s",fr,en,lien);
            A=ajoutNoeud(A,en,fr,lien);
        }
    }
    return A;
}

struct Noeud* RechercheArbre2(struct Noeud *A, char trad_anglais[], char mot_francais[]){
    if (A==NULL){
        printf("NULL");
        return A;
    }
    if (strlen(mot_francais)>2){
        if(strcmp(mot_francais,A->mot_francais)==0) {
            A->right=NULL;
            A->left=NULL;
            return A;
        }

        if(strcmp(mot_francais,A->mot_francais)>0) 
            return RechercheArbre2(A->right,"",mot_francais);
        else 
            return RechercheArbre2(A->left,"",mot_francais);
    }

    if (strlen(trad_anglais)>2){
        if(strcmp(mot_francais,A->mot_francais)==0) {
            A->right=NULL;
            A->left=NULL;
            return A;
        }

        if(strcmp(mot_francais,A->trad_anglais)>0) 
            return RechercheArbre2(A->right,trad_anglais,"");
        else 
            return RechercheArbre2(A->left,trad_anglais,"");
    }
}

char* choixLangue(){
    static char choix[3];
    printf("Veuillez choisir entre Anglais en tapant EN et Français en tapant FR \n");
    scanf("%s",choix);
    
    return choix;
}

char* motChoisi(){
    static char mot[20];
    printf("Veuillez tapez un mot dans la langue choisie \n");
    scanf("%s",mot);
    return mot;
}

int rechercheMOT2J(char** motFR,char elem[]){
    for (int i=0;i<=G_MAX_WORDS;i++){
        if (strcmp(elem,motFR[i])==0) return i;
    }
    return -1;
}

int nbrJoueur(){
    int r=0;
    while (r!=1 || r!=2){
        printf("Combien de joueur entre 1 et 2 ?");
        scanf("%d",&r);
    }
    return r;
}

int main(int argc, char** argv){
    //chargement
    struct Noeud *ArbreP=calloc(1,sizeof(struct Noeud));
    struct Noeud *ArbreTmp=calloc(1,sizeof(struct Noeud));
    
    char ** motsFR=chargementMotFR();
    
    
    chargementDonnee(ArbreP);

    //choix langue/mot/joueur
    char choixL[5];
    char motDemande[20];
    //int nbrJ=nbrJoueur();
    strcpy(choixL,choixLangue());
    strcpy(motDemande,motChoisi());
    
    if (strcmp(choixL,"EN")==0){    
        printf("Entre dans EN \n");   
        ArbreTmp=RechercheArbre2(ArbreP,motDemande,"1");
        printPreOrder(ArbreTmp);
        if (ArbreTmp==NULL){
            while (ArbreTmp==NULL){
                printf("Mot non disponible \n");
                strcpy(motDemande,motChoisi());
                ArbreTmp=RechercheArbre2(ArbreP,motDemande,"1");
            }
        }
    }   

    if (strcmp(choixL,"FR")==0){   
        printf("Entre dans FR \n");  
        int retour=rechercheMOT2J(motsFR,motDemande);
        printf("retour:%d \n",retour);
        printf("e1 \n");
        if (retour<0){
            while (retour<0){
                printf("Mot non disponible \n");
                strcpy(motDemande,motChoisi());
                retour=rechercheMOT2J(motsFR,motDemande);
            }
        }
        printf("mot:%s \n",motsFR[retour]);
        printf("e2 \n");
        ArbreTmp=RechercheArbre2(ArbreP,"1",motsFR[retour]);
        printPreOrder(ArbreTmp);
    }
    //printPreOrder(ArbreP);

    //image
    if (SDL_Init(SDL_INIT_VIDEO)!=0){
        fprintf(stdout,"Echec %s \n",SDL_GetError());
        return -1;
    }
    SDL_Window *pWindow=NULL;
    SDL_Rect dstrect={5,5,120,120}; 
    
    if (0!=SDL_Init(SDL_INIT_VIDEO)){
        printf("Erreur init %s \n",SDL_GetError());
    }
    
    pWindow=SDL_CreateWindow("Jeu",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,1280,720,SDL_WINDOW_SHOWN);
    if (NULL==pWindow){
        printf("Erreur create %s \n",SDL_GetError());
    }

    SDL_Renderer *render = SDL_CreateRenderer(pWindow, -1 ,0);  
    SDL_Rect r;
    r.x=50;
    r.y=50;
    r.w=50;
    r.h=50;

    SDL_SetRenderDrawColor(render,255,0,0,255);
    SDL_Surface *fond =IMG_Load("akastuki.png");
    char * tmpM=(char *)malloc(strlen(ArbreTmp->lien_image)*sizeof(char));
    strcpy(tmpM,ArbreTmp->lien_image);
    printf("%s \n",ArbreTmp->lien_image);
    printf("%s \n",tmpM);
    
    SDL_Surface *image =IMG_Load(tmpM);
    free(tmpM);

    if(!fond || !image){
        printf("erreur fichier image %s\n",SDL_GetError());
    }

    SDL_Texture *texture=SDL_CreateTextureFromSurface(render,fond);
    SDL_Texture *texture2=SDL_CreateTextureFromSurface(render,image);
    SDL_RenderFillRect(render,&r);
    SDL_RenderPresent(render);
    
    if(!texture||!texture2){
        printf("erreur texture %s \n",SDL_GetError());
    }

    if (pWindow){
        SDL_RenderCopy(render,texture,NULL,NULL);
        SDL_RenderCopy(render,texture2,NULL,&dstrect);
        SDL_RenderPresent(render);
        SDL_Delay(3000);
        SDL_DestroyWindow(pWindow);
        SDL_FreeSurface(fond);
        SDL_DestroyTexture(texture);
        SDL_DestroyRenderer(render);
        SDL_FreeSurface(image);
        SDL_DestroyTexture(texture2);  
    }
    else{
        printf("Erreur création de la fenêtre :%s\n",SDL_GetError());
    }

    SDL_Quit();
    return 0;   
}

Merci d'avance.
 

A voir également:

4 réponses

Il y a des choses bizarres dans cette fonction:
+ Pourquoi mettre les pointeurs right et left à NULL quand tu trouves?
+ Pourquoi strlen > 2? J'aurais cru > 0 puisque tu as des chaînes vides ""

Je ne peux pas traduire "tu" en "you" ?
+ On dirait que ton arbre est ordonné de deux façons. (français ou anglais).
Dans la seconde partie, c'est incohérent. Tu testes d'abord le mot français et tu passes aux traductions anglaises.
    if (strlen(trad_anglais)>2){
        if(strcmp(mot_francais,A->mot_francais)==0) {
   ... et tu passes en anglais.
+ On ne sait pas si les chaînes correspondant aux mots dans l'arbre sont correctes ou NULL.
Je te suggère d'essayer d'afficher tout ton arbre de façon récursive: gauche milieu droite
Si ça plante, tu devrais pouvoir trouver ce qui manque (un noeud ou une chaîne)
Pour les lettres accentuées, on ne sait pas dans quel code tu es: latin-1 ou utf-8, etc.
Dans certains cas, les lettres accentuées peuvent prendre plus d'un octet. Si ton mot est long, tu pourrais dépasser tes 20 caractères.

0

J'avais mis ça pour tenter de résoudre le soucis, j'ai souvent du mal à comprendre d'où viennent les erreurs de segmentation. Et puisque je n'ai pas besoin de gauche et droite dans ma sortie de fonction, je me suis dit que ce n'était pas grave.

J'avais mis >2 par question de sécurité avec les caractères invisibles, mais il est vrai qu'ils ne sont pas comptés.

Merci de m'avoir remarqué l'erreur :

if (strlen(trad_anglais)>2){
        if(strcmp(mot_francais,A->mot_francais)==0) {

Je n'avais pas du tout vu.

Pour l'affichage récursif de mon arbre, j'ai la fonction printPreOrder, mais j'ai l'impression qu'il y a un problème : elle m'affiche d'abord des choses vides, puis d'un coup un endroit de mon arbre, mais je ne pense pas la fin car ce n'est pas les derniers données de mon CSV.

Fichier en question : https://www.mediafire.com/file/8crb8luaio7i6kq/mot.csv/file

Je crois que les données de base sont entrées en UTF-8 mais je ne suis pas sûr.

J'ai essayé d'actualiser le code avec tes conseils :

#include <SDL2/SDL.h>
#include <stdio.h>
#include <SDL2/SDL_image.h>
#include <stdlib.h>
#include <time.h>
#define G_MAX_LEN_WORDS 20
#define G_MAX_WORDS     587

// Créer un Noeud
struct Noeud {
    char trad_anglais[20];
    char mot_francais[20];
    char lien_image[20];
    struct Noeud *left;
    struct Noeud *right;
};

//int max(int a, int b);
int max(int a, int b) {
    return (a > b) ? a : b;
}
// Calcul hauteur
int HauteurArbre(struct Noeud *N) {
    if (N == NULL) return -1;
    else return max(HauteurArbre(N->left),HauteurArbre(N->right))+1;
}



// Create a Noeud
struct Noeud *CreerNoeud(char trad_anglais[],char mot_francais[], char lien_image[]) {
    struct Noeud *Noeud = (struct Noeud *) malloc(sizeof(struct Noeud));
    strcpy(Noeud->trad_anglais,trad_anglais);
    strcpy(Noeud->mot_francais,mot_francais);
    strcpy(Noeud->lien_image,lien_image);
    Noeud->left = NULL;
    Noeud->right = NULL;
    return (Noeud);
}

// Right rotate
struct Noeud *rotationDroite(struct Noeud *N) {
    struct Noeud *y = N->left;
    struct Noeud *N2 = y->right;

    y->right = N;
    N->left = N2;

    return y;
}

// Left rotate
struct Noeud *rotationGauche(struct Noeud *N) {
    struct Noeud *y = N->right;
    struct Noeud *N2 = y->left;

    y->left = N;
    N->right = N2;

    return y;
}

// Get the balance factor
int ecart(struct Noeud *N) {
    if (N == NULL)
        return 0;
    return HauteurArbre(N->left)-HauteurArbre(N->right);
}

// Insert Noeud
struct Noeud *ajoutNoeud(struct Noeud *Noeud,char trad_anglais[],char mot_francais[], char lien_image[]) {
    // place le nouveau Noeud au bon endroit
    if (Noeud == NULL)
        return (CreerNoeud(trad_anglais,mot_francais,lien_image));

    if (strcmp(mot_francais,Noeud->mot_francais)<0)
        Noeud->left = ajoutNoeud(Noeud->left,trad_anglais,mot_francais,lien_image);
    else if (strcmp(mot_francais,Noeud->mot_francais)>0)
        Noeud->right = ajoutNoeud(Noeud->right,trad_anglais,mot_francais,lien_image);
    else
        return Noeud;
   
    //équilibrage
    int balance = ecart(Noeud);
    if (balance > 1 && strcmp(mot_francais,Noeud->left->mot_francais)<0) 
        return rotationDroite(Noeud);

    if (balance < -1 && strcmp(mot_francais,Noeud->right->mot_francais)>0)
        return rotationGauche(Noeud);

    if (balance > 1 && strcmp(mot_francais,Noeud->left->mot_francais)>0) {
        Noeud->left = rotationGauche(Noeud->left);
        return rotationDroite(Noeud);
    }

    if (balance < -1 && strcmp(mot_francais,Noeud->right->mot_francais)<0) {
        Noeud->right = rotationDroite(Noeud->right);
        return rotationGauche(Noeud);
    }

    return Noeud;
}

// Print the tree
void printPreOrder(struct Noeud *root) {
    if (root != NULL) {
        printf("f=%s \n", root->mot_francais);
        printf("a=%s \n", root->trad_anglais);
        printf("l=%s \n", root->lien_image);
        printPreOrder(root->left);
        printPreOrder(root->right);
    }
    else{
        EXIT_SUCCESS;
    }
}

char** chargementMotFR(){
    char tmp[90];
    FILE * fichier=fopen("mot.csv","r");
	// La zone de travail (le damier)
	char* work = malloc(G_MAX_WORDS * (G_MAX_LEN_WORDS + 1) * sizeof(*work));
	if (work == NULL) return NULL;

	// Les pointeurs pointant vers chaque "mot" de la zone de travail
	char** tabs=malloc(G_MAX_WORDS * sizeof(*tabs));
	if (tabs == NULL) {
	    free(work);
	    return NULL;
	}

	// Nécessité de faire pointer chaque "pointeur" vers la bonne position dans le damier
	for (size_t i=0; i < G_MAX_WORDS; i++) tabs[i]=work + i * (G_MAX_LEN_WORDS + 1);
	// Remplissage
    int cpt=0;

    if (fichier==NULL) printf("Erreur d'ouverture de fichier");   
    else{	   
        while (fgets(tmp,90,fichier)!=NULL){
            char * pch=strtok(tmp,",");
            char * tmpS;
            while (pch!=NULL){
                tmpS=strtok(pch," ");
                strcpy(tabs[cpt],tmpS);
                pch=strtok(NULL,",");
            }
        cpt++;
        }
    }
	return tabs;
}

struct Noeud * chargementDonnee(struct Noeud* A){ 
    char tmp[90];
    char fr[20],en[20],lien[35];
    FILE* fichier=fopen("mot.csv","r");
    if (fichier==NULL)
        printf("Erreur d'ouverture de fichier \n");
    else {
        while(fgets(tmp,90,fichier)!=NULL){
            for (int i=0; i<strlen(tmp);i++)
            {
                if (tmp[i]==',') tmp[i]=' ';
            }
            sscanf(tmp,"%s%s%s",fr,en,lien);
            A=ajoutNoeud(A,en,fr,lien);
        }
    }
    return A;
}

struct Noeud* RechercheArbre2(struct Noeud *A, char trad_anglais[], char mot_francais[]){
    if (A==NULL){
        printf("NULL");
        return A;
    }
    if (strlen(mot_francais)>0){
        if(strcmp(mot_francais,A->mot_francais)==0) {
            A->right=NULL;
            A->left=NULL;
            return A;
        }

        if(strcmp(mot_francais,A->mot_francais)>0) 
            return RechercheArbre2(A->right,"",mot_francais);
        else 
            return RechercheArbre2(A->left,"",mot_francais);
    }

    else{
        if(strcmp(trad_anglais,A->mot_francais)==0) {
            A->right=NULL;
            A->left=NULL;
            return A;
        }

        if(strcmp(trad_anglais,A->trad_anglais)>0) 
            return RechercheArbre2(A->right,trad_anglais,"");
        else 
            return RechercheArbre2(A->left,trad_anglais,"");
    }
}

char* choixLangue(){
    static char choix[3];
    printf("Veuillez choisir entre Anglais en tapant EN et Français en tapant FR \n");
    scanf("%s",choix);
    
    return choix;
}

char* motChoisi(){
    static char mot[20];
    printf("Veuillez tapez un mot dans la langue choisie \n");
    scanf("%s",mot);
    return mot;
}

int rechercheMOT2J(char** motFR,char elem[]){
    for (int i=0;i<=G_MAX_WORDS-1;i++){
        if (strcmp(elem,motFR[i])==0) return i;
    }
    return -1;
}

int nbrJoueur(){
    int r=0;
    while (r!=1 || r!=2){
        printf("Combien de joueur entre 1 et 2 ?");
        scanf("%d",&r);
    }
    return r;
}

int main(int argc, char** argv){
    //chargement
    struct Noeud *ArbreP=calloc(1,sizeof(struct Noeud));
    struct Noeud *ArbreTmp=calloc(1,sizeof(struct Noeud));
    
    char ** motsFR=chargementMotFR();
    
    
    chargementDonnee(ArbreP);

    //choix langue/mot/joueur
    char choixL[5];
    char motDemande[20];
    //int nbrJ=nbrJoueur();
    strcpy(choixL,choixLangue());
    strcpy(motDemande,motChoisi());
    
    if (strcmp(choixL,"EN")==0){    
        printf("Entre dans EN \n");   
        ArbreTmp=RechercheArbre2(ArbreP,motDemande,"1");
        printPreOrder(ArbreTmp);
        if (ArbreTmp==NULL){
            while (ArbreTmp==NULL){
                printf("Mot non disponible \n");
                strcpy(motDemande,motChoisi());
                ArbreTmp=RechercheArbre2(ArbreP,motDemande,"1");
            }
        }
    }   

    if (strcmp(choixL,"FR")==0){   
        printf("Entre dans FR \n");  
        long int retour=rechercheMOT2J(motsFR,motDemande);
        printf("retour:%ld \n",retour);
        printf("e1 \n");
        if (retour<0){
            while (retour<0){
                printf("Mot non disponible \n");
                strcpy(motDemande,motChoisi());
                retour=rechercheMOT2J(motsFR,motDemande);
            }
        }
        printf("mot:%s \n",motsFR[retour]);
        printf("e2 \n");
        ArbreTmp=RechercheArbre2(ArbreP,"1",motsFR[retour]);
        printPreOrder(ArbreTmp);
    }
    printPreOrder(ArbreP);

    //image
    if (SDL_Init(SDL_INIT_VIDEO)!=0){
        fprintf(stdout,"Echec %s \n",SDL_GetError());
        return -1;
    }
    SDL_Window *pWindow=NULL;
    SDL_Rect dstrect={5,5,120,120}; 
    
    if (0!=SDL_Init(SDL_INIT_VIDEO)){
        printf("Erreur init %s \n",SDL_GetError());
    }
    
    pWindow=SDL_CreateWindow("Jeu",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,1280,720,SDL_WINDOW_SHOWN);
    if (NULL==pWindow){
        printf("Erreur create %s \n",SDL_GetError());
    }

    SDL_Renderer *render = SDL_CreateRenderer(pWindow, -1 ,0);  
    SDL_Rect r;
    r.x=50;
    r.y=50;
    r.w=50;
    r.h=50;

    SDL_SetRenderDrawColor(render,255,0,0,255);
    SDL_Surface *fond =IMG_Load("akastuki.png");
    char * tmpM=(char *)malloc(strlen(ArbreTmp->lien_image)*sizeof(char));
    strcpy(tmpM,ArbreTmp->lien_image);
    printf("%s \n",ArbreTmp->lien_image);
    printf("%s \n",tmpM);
    
    SDL_Surface *image =IMG_Load(tmpM);
    free(tmpM);

    if(!fond || !image){
        printf("erreur fichier image %s\n",SDL_GetError());
    }

    SDL_Texture *texture=SDL_CreateTextureFromSurface(render,fond);
    SDL_Texture *texture2=SDL_CreateTextureFromSurface(render,image);
    SDL_RenderFillRect(render,&r);
    SDL_RenderPresent(render);
    
    if(!texture||!texture2){
        printf("erreur texture %s \n",SDL_GetError());
    }

    if (pWindow){
        SDL_RenderCopy(render,texture,NULL,NULL);
        SDL_RenderCopy(render,texture2,NULL,&dstrect);
        SDL_RenderPresent(render);
        SDL_Delay(3000);
        SDL_DestroyWindow(pWindow);
        SDL_FreeSurface(fond);
        SDL_DestroyTexture(texture);
        SDL_DestroyRenderer(render);
        SDL_FreeSurface(image);
        SDL_DestroyTexture(texture2);  
    }
    else{
        printf("Erreur création de la fenêtre :%s\n",SDL_GetError());
    }

    SDL_Quit();
    return 0;   
}
0

Ok je viens de comprendre mon erreur de segmentation. Je l'ai corrigé dans mon message du dessus. Maintenant mon seul problème est l'encryptage des mots.

0

> J'avais mis ça pour tenter de résoudre le soucis, j'ai souvent du mal à comprendre d'où viennent les erreurs de segmentation. Et puisque je n'ai pas besoin
> de gauche et droite dans ma sortie de fonction, je me suis dit que ce n'était pas grave.
En faisant ça, tu détruis littéralement ton arbre. Mais je ne crois pas que c'est la cause du Segmentation fault.
Je n'avais pas remarqué, mais c'est un ABR équilibré ...
Dans ta fonction d'affichage, tu affiches d'abord le noeud courant, puis la branche gauche et la branche droite.
Normalement, on affiche d'abord la gauche, le noeud et la droite.
On voit mieux ainsi si c'est en ordre.
Les fonctions de rotations sont normalement assez complexes. Le problème est peut-être là.
Si tu peux faire des tests en insérant des éléments fictifs et si tu affiches à mesure, tu trouveras sans doute.
Tu les choisis pour pouvoir contrôler toi-même la position.
Par exemple, tu places "mm" au début, puis "aa" ou "zz" ou tout autre chose pour mieux contrôler.

Dans ta rotation droite:
    y->right = N;
Qui te dis que y n'est pas NULL puisque tu effaces des liens?

0

En insérant à la main, j'obtiens bien un arbre trié et la fonction affiche bien comme il faut l'arbre. Cependant lorsque c'est la fonction chargementDonnee qui le fait, j'ai l'impression qu'il n'y a qu'une seule chose qui s'enregistre dans l'arbre, pourtant je fais la même chose qu'à la main mais en boucle.

Je n'arrive pas à comprendre le problème, ça serait la sortie des données via le tableau ? Ou ma boucle qui est mal faite ?

J'ai corrigé ma fonction d'affichage en affichant dans l'ordre que tu m'as indiqué.

0
PierrotLeFou
11 déc. 2022 à 04:05

Je n'ai pas analysé en détail, mais je trouve étrange que dans la fonction ajoutNoeud, tu retournes directement rotationDroite ou rotationGauche. dans certains cas
Qui va recevoir ce pointeur? Est-ce que ça remonte à la racine?
À moins que ton fichier soit très gros, tu pourrais afficher les lignes du fichier et l'arbre après chaque ajout dans chargementDonnee.

0

Je viens de d'afficher comme tu me l'as conseiller. C'était un peu compliqué à lire car j'ai 580 mots et quelques, mais j'ai donc pu remarquer de 1/ que mon arbre de ne retourner que le dernier Noeud A traité, et ne renvoyer donc jamais l'arbre entier (donc A->right et A->left ne sont vraisemblablement pas renvoyé), car dans la fonction, l'arbre s'affiche en entier, mais pas à l'extérieur.

De 2/ j'ai pu voir que l'arbre arrêté de s'agrandir au 380e mot alors que j'en ai 587, comment expliquer cela ? Je n'ai pas pourtant pas l'impression d'avoir fait d'erreur dans ma boucle while.

0
PierrotLeFou
11 déc. 2022 à 05:45

Tu as défini chargementDonnee avec une valeur de retour, mais tu ne l'assignes à rien.
Si ton arbre est bon avant le retour, c'est la cause de ton premier problème.
Je soupçonne encore tes retours des rotations.
Peux-tu générer des séquences de 2 lettres comme "aa", "ab", "ac", etc.
Et tu les entres dans cet ordre. Tu devrais forcer des rotations.
Fais-le à l'envers pour la symétrie: "zz", "zy", ...
Ou si tu veux générer des chaînes de chiffres avec rand()%1000 (0 à999) et tu en fait une chaîne avec un ssprintf("%03d" ... par exemple.

0

J'ai corrigé et en effet je n'ai plus de problème. J'ai re testé mes rotations avec une cinquantaine de doubles lettres et triples lettres, aucun soucis, tout s'équilibre comme il faut.

Je viens juste de voir que lorsque je recherchai en anglais ça ne fonctionnait pas car je triais en français, j'ai modifié un peu et ça fonctionne toujours, mais trie selon les langues.

#include <SDL2/SDL.h>
#include <stdio.h>
#include <SDL2/SDL_image.h>
#include <stdlib.h>
#include <time.h>
#define G_MAX_LEN_WORDS 20
#define G_MAX_WORDS     587

// Créer un Noeud
struct Noeud {
    char trad_anglais[20];
    char mot_francais[20];
    char lien_image[50];
    struct Noeud *left;
    struct Noeud *right;
};

//int max(int a, int b);
int max(int a, int b) {
    return (a > b) ? a : b;
}
// Calcul hauteur
int HauteurArbre(struct Noeud *N) {
    if (N == NULL) return -1;
    else return max(HauteurArbre(N->left),HauteurArbre(N->right))+1;
}



// Create a Noeud
struct Noeud *CreerNoeud(char trad_anglais[],char mot_francais[], char lien_image[]) {
    struct Noeud *Noeud = (struct Noeud *) malloc(sizeof(struct Noeud));
    strcpy(Noeud->trad_anglais,trad_anglais);
    strcpy(Noeud->mot_francais,mot_francais);
    strcpy(Noeud->lien_image,lien_image);
    Noeud->left = NULL;
    Noeud->right = NULL;
    return (Noeud);
}

// Right rotate
struct Noeud *rotationDroite(struct Noeud *N) {
    struct Noeud *y = N->left;
    struct Noeud *N2 = y->right;

    y->right = N;
    N->left = N2;

    return y;
}

// Left rotate
struct Noeud *rotationGauche(struct Noeud *N) {
    struct Noeud *y = N->right;
    struct Noeud *N2 = y->left;

    y->left = N;
    N->right = N2;

    return y;
}

// Get the balance factor
int ecart(struct Noeud *N) {
    if (N == NULL)
        return 0;
    return HauteurArbre(N->left)-HauteurArbre(N->right);
}

// Insert Noeud
struct Noeud *ajoutNoeud(struct Noeud *Noeud,char trad_anglais[],char mot_francais[], char lien_image[],char choixL[]) {
    // place le nouveau Noeud au bon endroit
    if (Noeud == NULL)
        return (CreerNoeud(trad_anglais,mot_francais,lien_image));

    //fr
    if (strcmp(choixL,"FR")==0){
        if (strcmp(mot_francais,Noeud->mot_francais)<0)
            Noeud->left = ajoutNoeud(Noeud->left,trad_anglais,mot_francais,lien_image,choixL);
        else if (strcmp(mot_francais,Noeud->mot_francais)>0)
            Noeud->right = ajoutNoeud(Noeud->right,trad_anglais,mot_francais,lien_image,choixL);
        else
            return Noeud;
    
        //équilibrage
        int balance = ecart(Noeud);

        if (balance > 1 && strcmp(mot_francais,Noeud->left->mot_francais)<0) 
            return rotationDroite(Noeud);

        if (balance < -1 && strcmp(mot_francais,Noeud->right->mot_francais)>0)
            return rotationGauche(Noeud);

        if (balance > 1 && strcmp(mot_francais,Noeud->left->mot_francais)>0) {
            Noeud->left = rotationGauche(Noeud->left);
            return rotationDroite(Noeud);
        }

        if (balance < -1 && strcmp(mot_francais,Noeud->right->mot_francais)<0) {
            Noeud->right = rotationDroite(Noeud->right);
            return rotationGauche(Noeud);
        }
    }

    //en
    else{
        if (strcmp(trad_anglais,Noeud->trad_anglais)<0)
            Noeud->left = ajoutNoeud(Noeud->left,trad_anglais,mot_francais,lien_image,choixL);
        else if (strcmp(trad_anglais,Noeud->trad_anglais)>0)
            Noeud->right = ajoutNoeud(Noeud->right,trad_anglais,mot_francais,lien_image,choixL);
        else
            return Noeud;
    
        //équilibrage
        int balance = ecart(Noeud);

        if (balance > 1 && strcmp(trad_anglais,Noeud->left->trad_anglais)<0) 
            return rotationDroite(Noeud);

        if (balance < -1 && strcmp(trad_anglais,Noeud->right->trad_anglais)>0)
            return rotationGauche(Noeud);

        if (balance > 1 && strcmp(trad_anglais,Noeud->left->trad_anglais)>0) {
            Noeud->left = rotationGauche(Noeud->left);
            return rotationDroite(Noeud);
        }

        if (balance < -1 && strcmp(trad_anglais,Noeud->right->trad_anglais)<0) {
            Noeud->right = rotationDroite(Noeud->right);
            return rotationGauche(Noeud);
        }
    }
        return Noeud;
    }

// Print the tree
void printPreOrder(struct Noeud *root) {
    if (root != NULL) {
        printPreOrder(root->left);
        printf("f=%s \n", root->mot_francais);
        printf("a=%s \n", root->trad_anglais);
        printf("l=%s \n", root->lien_image);
        printPreOrder(root->right);
    }
    else{
        EXIT_SUCCESS;
    }
}

char** chargementMotFR(){
    char tmp[90];
    FILE * fichier=fopen("mot.csv","r");
	// La zone de travail (le damier)
	char* work = malloc(G_MAX_WORDS * (G_MAX_LEN_WORDS + 1) * sizeof(*work));
	if (work == NULL) return NULL;

	// Les pointeurs pointant vers chaque "mot" de la zone de travail
	char** tabs=malloc(G_MAX_WORDS * sizeof(*tabs));
	if (tabs == NULL) {
	    free(work);
	    return NULL;
	}

	// Nécessité de faire pointer chaque "pointeur" vers la bonne position dans le damier
	for (size_t i=0; i < G_MAX_WORDS; i++) tabs[i]=work + i * (G_MAX_LEN_WORDS + 1);
	// Remplissage
    int cpt=0;

    if (fichier==NULL) printf("Erreur d'ouverture de fichier");   
    else{	   
        while (fgets(tmp,90,fichier)!=NULL){
            char * pch=strtok(tmp,",");
            char * tmpS;
            while (pch!=NULL){
                tmpS=strtok(pch," ");
                strcpy(tabs[cpt],tmpS);
                pch=strtok(NULL,",");
            }
        cpt++;
        }
    }
	return tabs;
}

struct Noeud * chargementDonnee(struct Noeud* A,char choixL[]){ 
    char tmp[90];
    char fr[20],en[20],lien[50];
    FILE* fichier=fopen("mot.csv","r");
    if (fichier==NULL)
        printf("Erreur d'ouverture de fichier \n");
    else {
        while(fgets(tmp,90,fichier)!=NULL){
            for (int i=0; i<strlen(tmp);i++)
            {
                if (tmp[i]==',') tmp[i]=' ';
            }
            sscanf(tmp,"%s%s%s",fr,en,lien);
            printf("ccccccccccccc %s %s %s \n",fr,en,lien);
            A=ajoutNoeud(A,en,fr,lien,choixL);
            //printPreOrder(A);
        }
    }
    return A;
}

struct Noeud* RechercheArbre2(struct Noeud *A, char trad_anglais[], char mot_francais[]){
    if (A==NULL){
        printf("NULL");
        return A;
    }
    if (strlen(mot_francais)>1){
        printf("non \n");
        if(strcmp(mot_francais,A->mot_francais)==0) {
            return A;
        }

        if(strcmp(mot_francais,A->mot_francais)>0) 
            return RechercheArbre2(A->right,"",mot_francais);
        else 
            return RechercheArbre2(A->left,"",mot_francais);
    }

    else{
        if (strlen(trad_anglais)>1){
            printf("oui \n");
            if(strcmp(trad_anglais,A->trad_anglais)==0) {
                return A;
            }

            if(strcmp(trad_anglais,A->trad_anglais)>0) 
                return RechercheArbre2(A->right,trad_anglais,"");
            else 
                return RechercheArbre2(A->left,trad_anglais,"");
        }
    }
}

char* choixLangue(){
    static char choix[3];
    printf("Veuillez choisir entre Anglais en tapant EN et Français en tapant FR \n");
    scanf("%s",choix);
    
    return choix;
}

char* motChoisi(){
    static char mot[20];
    printf("Veuillez tapez un mot dans la langue choisie \n");
    scanf("%s",mot);
    return mot;
}

int rechercheMOT2J(char** motFR,char elem[]){
    for (int i=0;i<=G_MAX_WORDS-1;i++){
        if (strcmp(elem,motFR[i])==0) return i;
    }
    return -1;
}

int nbrJoueur(){
    int r=0;
    while (r!=1 || r!=2){
        printf("Combien de joueur entre 1 et 2 ?");
        scanf("%d",&r);
    }
    return r;
}

int main(int argc, char** argv){
    //chargement
    struct Noeud *ArbreP=calloc(1,sizeof(struct Noeud));
    struct Noeud *ArbreTmp=calloc(1,sizeof(struct Noeud));

    char ** motsFR=chargementMotFR();   

    //choix langue/mot/joueur
    char choixL[5];
    char motDemande[20];
    //int nbrJ=nbrJoueur();
    strcpy(choixL,choixLangue());
    ArbreP=chargementDonnee(ArbreP,choixL);
    printPreOrder(ArbreP);
    strcpy(motDemande,motChoisi());
    
    if (strcmp(choixL,"EN")==0){    
        printf("Entre dans EN \n");   
        ArbreTmp=RechercheArbre2(ArbreP,motDemande,"1");
        printPreOrder(ArbreTmp);
        if (ArbreTmp==NULL){
            while (ArbreTmp==NULL){
                printf("Mot non disponible \n");
                strcpy(motDemande,motChoisi());
                ArbreTmp=RechercheArbre2(ArbreP,motDemande,"1");
            }
        }
    }   

    if (strcmp(choixL,"FR")==0){   
        printf("Entre dans FR \n");  
        long int retour=rechercheMOT2J(motsFR,motDemande);
        printf("retour:%ld \n",retour);
        printf("e1 \n");
        if (retour<0){
            while (retour<0){
                printf("Mot non disponible \n");
                strcpy(motDemande,motChoisi());
                retour=rechercheMOT2J(motsFR,motDemande);
            }
        }
        printf("mot:%s \n",motsFR[retour]);
        printf("e2 \n");
        ArbreTmp=RechercheArbre2(ArbreP,"1",motsFR[retour]);
        //printPreOrder(ArbreTmp);
    }
    

    //image
    if (SDL_Init(SDL_INIT_VIDEO)!=0){
        fprintf(stdout,"Echec %s \n",SDL_GetError());
        return -1;
    }
    SDL_Window *pWindow=NULL;
    SDL_Rect dstrect={5,5,120,120}; 
    
    if (0!=SDL_Init(SDL_INIT_VIDEO)){
        printf("Erreur init %s \n",SDL_GetError());
    }
    
    pWindow=SDL_CreateWindow("Jeu",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,1280,720,SDL_WINDOW_SHOWN);
    if (NULL==pWindow){
        printf("Erreur create %s \n",SDL_GetError());
    }

    SDL_Renderer *render = SDL_CreateRenderer(pWindow, -1 ,0);  
    SDL_Rect r;
    r.x=50;
    r.y=50;
    r.w=50;
    r.h=50;

    SDL_SetRenderDrawColor(render,255,0,0,255);
    SDL_Surface *fond =IMG_Load("akastuki.png");
    char * tmpM=(char *)malloc(strlen(ArbreTmp->lien_image)*sizeof(char));
    strcpy(tmpM,ArbreTmp->lien_image);
    printf("%s \n",ArbreTmp->lien_image);
    printf("%s \n",tmpM);
    
    SDL_Surface *image =IMG_Load(tmpM);
    free(tmpM);

    if(!fond || !image){
        printf("erreur fichier image %s\n",SDL_GetError());
    }

    SDL_Texture *texture=SDL_CreateTextureFromSurface(render,fond);
    SDL_Texture *texture2=SDL_CreateTextureFromSurface(render,image);
    SDL_RenderFillRect(render,&r);
    SDL_RenderPresent(render);
    
    if(!texture||!texture2){
        printf("erreur texture %s \n",SDL_GetError());
    }

    if (pWindow){
        SDL_RenderCopy(render,texture,NULL,NULL);
        SDL_RenderCopy(render,texture2,NULL,&dstrect);
        SDL_RenderPresent(render);
        SDL_Delay(3000);
        SDL_DestroyWindow(pWindow);
        SDL_FreeSurface(fond);
        SDL_DestroyTexture(texture);
        SDL_DestroyRenderer(render);
        SDL_FreeSurface(image);
        SDL_DestroyTexture(texture2);  
    }
    else{
        printf("Erreur création de la fenêtre :%s\n",SDL_GetError());
    }

    SDL_Quit();
    return 0;   
}

J'obtiens ça au final.

Merci pour ton aide !

0