Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#26 Le 21/11/2007, à 17:41

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

j'ai remarqué que t[dernier_calculer] pointé en fait sur la première case libre de t.
donc t[dernier_calculer] était toujours égale à NULL.

J'ai aussi remarqué ça sous gdb:

void
insererValeur (char *s) {
  t[dernier_calculer] = s;
}

ou

void
insererValeur (char *s) {
  strcpy (dernier_calculer, s);
}

ne mettait pas s dans t[dernier_calculer]
car après cette affectation, lorsque je fais p t[dernier_calculer]
gdb me renvoi:

$2 = (void *) 0x8048bb7

Pourquoi ?

Hors ligne

#27 Le 21/11/2007, à 17:46

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

nicolas.sitbon a écrit :
void insererValeur (char *s)
{
   strcpy(t[dernier_calculer],s);
}

Hors ligne

#28 Le 21/11/2007, à 18:46

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

TatSou-Max a écrit :

Ben dans mon cours d'algorithmique il est écrit en gras qu'un Tas doit toujours s'implémenter avec un tableau, donc voilà, j'ai fait un tableau.

Mouais, perso je trouve beaucoup plus élégante l'utilisation d'une liste chainée wink

En m'inspirant d'une implémentation basique d'un tas binaire en C, à l'aide d'une liste chainée et de récursivité, voici ce que j'ai pu faire:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

/*****************************************************************************/
struct element 
{
   char           *str;
   struct element *droite;
   struct element *gauche;
};

typedef struct element node_t;

/*****************************************************************************/
void insererElement (node_t ** arbre, node_t * element) 
{
  if ((*arbre) == NULL) 
  {
    *arbre = element;
    return;
  }
  if (strcmp (element->str, (*arbre)->str) < 0) 
  {
    insererElement (&(*arbre)->gauche, element);
  }
  else if (strcmp (element->str, (*arbre)->str) > 0) 
  {
    insererElement (&(*arbre)->droite, element);
  }
}

/*****************************************************************************/
node_t * creerElement (char * str)
{
  node_t * element;

  element = (node_t *)malloc(sizeof(node_t));
  if (element != NULL)
  {
    element->str = (char *)malloc(strlen(str)*sizeof(char));
    if (element->str != NULL)
    {
      strcpy (element->str, str);
    }
    element->gauche = NULL;
    element->droite = NULL;
  }
  
  return element;
}

/*****************************************************************************/
void afficherArbre (node_t * arbre) 
{
  if (arbre->gauche) 
  {
    afficherArbre (arbre->gauche);
  }

  if (arbre->str != NULL)
  {
    printf ("%s ",arbre->str);
  }

  if (arbre->droite) 
  {
    afficherArbre (arbre->droite);
  }
}

/*****************************************************************************/
void detruireArbre (node_t * arbre) 
{
  if (arbre->gauche != NULL) 
  {
    detruireArbre (arbre->gauche);
  }
  if (arbre->droite != NULL) 
  {
    detruireArbre (arbre->droite);
  }
  if (arbre->str != NULL)
  {
    free (arbre->str);
    arbre->str = NULL;
  }
  if (arbre != NULL)
  {
    free (arbre);
    arbre = NULL;
  }
}

/*****************************************************************************/
int main(int argc, char *argv[]) 
{
  node_t * actuel;
  node_t * racine;
  int i;

  racine = NULL;

  for (i=1; i<argc; i++) 
  {
    actuel = creerElement (argv[i]);
    insererElement (&racine, actuel);
  }
  afficherArbre (racine);
  printf ("\n");
  detruireArbre (racine);

}
/*****************************************************************************/

Dernière modification par pipomolo (Le 21/11/2007, à 18:52)

Hors ligne

#29 Le 21/11/2007, à 19:13

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

pipomolo a écrit :
TatSou-Max a écrit :

Ben dans mon cours d'algorithmique il est écrit en gras qu'un Tas doit toujours s'implémenter avec un tableau, donc voilà, j'ai fait un tableau.

Mouais, perso je trouve beaucoup plus élégante l'utilisation d'une liste chainée wink

En m'inspirant d'une implémentation basique d'un tas binaire en C, à l'aide d'une liste chainée et de récursivité, voici ce que j'ai pu faire:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

/*****************************************************************************/
struct element 
{
   char           *str;
   struct element *droite;
   struct element *gauche;
};

typedef struct element node_t;

/*****************************************************************************/
void insererElement (node_t ** arbre, node_t * element) 
{
  if ((*arbre) != NULL) 
  {
    *arbre = element;
    return;
  }
  if (strcmp (element->str, (*arbre)->str) < 0) 
  {
    insererElement (&(*arbre)->gauche, element);
  }
  else if (strcmp (element->str, (*arbre)->str) > 0) 
  {
    insererElement (&(*arbre)->droite, element);
  }
}

/*****************************************************************************/
node_t * creerElement (char * str)
{
  node_t * element;

  element = (node_t *)malloc(sizeof(node_t));
  if (element != NULL)
  {
    element->str = (char *)malloc(strlen(str)*sizeof(char));
    if (element->str != NULL)
    {
      strcpy (element->str, str);
    }
    element->gauche = NULL;
    element->droite = NULL;
  }
  
  return element;
}

/*****************************************************************************/
void afficherArbre (node_t * arbre) 
{
  if (arbre->gauche) 
  {
    afficherArbre (arbre->gauche);
  }

  if (arbre->str != NULL)
  {
    printf ("%s ",arbre->str);
  }

  if (arbre->droite) 
  {
    afficherArbre (arbre->droite);
  }
}

/*****************************************************************************/
void detruireArbre (node_t * arbre) 
{
  if (arbre->gauche != NULL) 
  {
    detruireArbre (arbre->gauche);
  }
  if (arbre->droite != NULL) 
  {
    detruireArbre (arbre->droite);
  }
  if (arbre->str != NULL)
  {
    free (arbre->str);
    arbre->str = NULL;
  }
  if (arbre != NULL)
  {
    free (arbre);
    arbre = NULL;
  }
}

/*****************************************************************************/
int main(int argc, char *argv[]) 
{
  node_t * actuel;
  node_t * racine;
  int i;

  racine = NULL;

  for (i=1; i<argc; i++) 
  {
    actuel = creerElement (argv[i]);
    insererElement (&racine, actuel);
  }
  afficherArbre (racine);
  printf ("\n");
  detruireArbre (racine);

}
/*****************************************************************************/

ouais une fois qu'on a corrigé les fautes...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct element node_t;
struct element
{
   char *str;
   node_t *droite;
   node_t *gauche;
};

void insererElement (node_t ** arbre, node_t * element);
node_t *creerElement (char const *str);
void afficherArbre (node_t const *arbre);
void detruireArbre (node_t ** arbre);

int main (int argc, char *argv[])
{
   node_t *actuel = NULL;
   node_t *racine = NULL;
   int i = 1;

   for (; i < argc; i++)
   {
      actuel = creerElement (argv[i]);
      insererElement (&racine, actuel);
   }

   if (argc > 1)
   {
      afficherArbre (racine);
      puts ("");
      detruireArbre (&racine);
   }
   return 0;
}

void insererElement (node_t ** arbre, node_t * element)
{
   if (*arbre == NULL)
   {
      *arbre = element;
   }
   else
   {
      if (strcmp (element->str, (*arbre)->str) < 0)
      {
         insererElement (&(*arbre)->gauche, element);
      }
      else if (strcmp (element->str, (*arbre)->str) > 0)
      {
         insererElement (&(*arbre)->droite, element);
      }
   }
}

node_t *creerElement (char const *str)
{
   node_t *element = malloc (sizeof *element);
   if (element != NULL)
   {
      element->str = malloc ((1 + strlen (str)) * sizeof *element->str);
      if (element->str != NULL)
      {
         strcpy (element->str, str);
      }
      else
      {
         perror ("creerElement");
      }
      element->gauche = NULL;
      element->droite = NULL;
   }
   else
   {
      perror ("creerElement");
   }

   return element;
}

void afficherArbre (node_t const *arbre)
{
   if (arbre->gauche != NULL)
   {
      afficherArbre (arbre->gauche);
   }

   printf ("%s ", arbre->str);

   if (arbre->droite != NULL)
   {
      afficherArbre (arbre->droite);
   }
}

void detruireArbre (node_t ** arbre)
{
   if ((*arbre)->gauche != NULL)
   {
      detruireArbre (&(*arbre)->gauche);
   }
   if ((*arbre)->droite != NULL)
   {
      detruireArbre (&(*arbre)->droite);
   }
   free ((*arbre)->str), (*arbre)->str = NULL;
   free (*arbre), *arbre = NULL, arbre = NULL;
}

Dernière modification par nicolas.sitbon (Le 21/11/2007, à 19:19)

Hors ligne

#30 Le 21/11/2007, à 19:15

qqun

Re : [Résolu] Programme en C: erreur de segmentation.

a partir de ton source code , si dans

char *
supprimerValeur (void) {
    
  char *racine = t[0];
   t[0] = t[dernier_calculer];
 
  return racine;
}

tu mets  t[0] = t[dernier_calculer-1]; ca passe  ?

#31 Le 21/11/2007, à 19:42

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

Bon alors en fait j'avais 2 erreurs:

La première, qqun la fait remarquer dans son dernier post:
t[0] = t[dernier_calculer]
faisait pointer t[0] sur NULL car dernier_calculer pointe en fait vers la première case libre de t.

La seconde, desallocation(targc-i) n'était pas au bon endroit.
Je libérais la mémoire trop tard.

Donc voilà, je vais rajouter [Résolu] dans mon topic
et je vous remercie tous pour votre aide.
D'ailleurs, les codes que vous avez écrit sur la fin m'ont l'air fortement intéressant, donc je vais les regardé en détails dans la soirée.

Merci et bonne continuation.

Hors ligne

#32 Le 22/11/2007, à 10:14

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

nicolas.sitbon a écrit :

ouais une fois qu'on a corrigé les fautes...

lol, faut pas oublier que j'ai fait le truc en 10 minutes, donc je conçois qu'il y ait 2 ou 3 soucis, le plus grave étant l'oubli d'allouer un caractère supplémentaire pour la terminaison de la string... et le return 0 dans le main, mais rien de bien méchant...pour la destruction, ta proposition n'est pas non plus exempte de défaut, puisque tu accèdes un pointeur sans vérifier s'il est différent de NULL wink sans rancune donc big_smile...

J'avais effectivement oublié de mettre à  NULL la racine de chaque "sous-arbre", ce qui implique de passer un pointeur de pointeur, bien vu...

Pour les prototypes, c'est du chipotage, pour un bout de code posté sur un forum wink

Par contre, je n'aime personnellement pas du tout ce genre de choses:

   int i = 1;

   for (; i < argc; i++)

Chaque bloc de code doit être indépendant du reste du code...ce qui n'est pas le cas ici...

A noter que ça vaut aussi pour l'utilisation de sizeof, sachant que pour ça ton code est meilleur que le mien...

Dernière modification par pipomolo (Le 22/11/2007, à 10:39)

Hors ligne

#33 Le 22/11/2007, à 10:52

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

Pour conclure sur mon bout de code posté plus haut, voici une version corrigée, a priori assez robuste :

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

/*****************************************************************************/
typedef struct element 
{
   char             *str;
   struct element   *droite;
   struct element   *gauche;
} node_t;

/*****************************************************************************/
static void     insererElement  (node_t **arbre, node_t *element);
static node_t   *creerElement   (const char *str);
static void     afficherArbre   (const node_t *arbre);
static void     detruireArbre   (node_t **arbre);

/*****************************************************************************/
int main(int argc, char *argv[]) 
{
  node_t *actuel = NULL;
  node_t *racine = NULL;
  int i;

  for (i = 1; i < argc; i++) 
  {
    actuel = creerElement (argv[i]);
    if (actuel != NULL)
    {
      insererElement (&racine, actuel);
    }
  }

  if (racine != NULL)
  {
    afficherArbre (racine);
    printf ("\n");
    detruireArbre (&racine);
  }

  return 0;
}

/*****************************************************************************/
void insererElement (node_t **arbre, node_t *element) 
{
  if (element != NULL)
  {
    if ((*arbre) == NULL) 
    {
      *arbre = element;
      return;
    }
    else if (element->str != NULL && (*arbre)->str != NULL)
    {
      if (strcmp (element->str, (*arbre)->str) < 0) 
      {
        insererElement (&(*arbre)->gauche, element);
      }
      else if (strcmp (element->str, (*arbre)->str) > 0) 
      {
        insererElement (&(*arbre)->droite, element);
      }
    }
  }
  
  return;
}

/*****************************************************************************/
node_t *creerElement (const char *str)
{
  node_t *element;

  element = malloc (sizeof *element);
  if (element != NULL)
  {
    element->str = malloc ((strlen(str)+1)*sizeof *element->str);
    if (element->str != NULL)
    {
      strcpy (element->str, str);
    }
    element->gauche = NULL;
    element->droite = NULL;
  }
  
  return element;
}

/*****************************************************************************/
void afficherArbre (const node_t *arbre) 
{
  if (arbre != NULL)
  {
    if (arbre->gauche != NULL)
    {
      afficherArbre (arbre->gauche);
    }
    if (arbre->str != NULL)
    {
      printf ("%s ",arbre->str);
    }
    if (arbre->droite != NULL)
    {
      afficherArbre (arbre->droite);
    }
  }
  
  return;
}

/*****************************************************************************/
void detruireArbre (node_t **arbre) 
{
  if (arbre != NULL && (*arbre) != NULL)
  {
    if ((*arbre)->gauche != NULL) 
    {
      detruireArbre (&(*arbre)->gauche);
    }
    if ((*arbre)->droite != NULL) 
    {
      detruireArbre (&(*arbre)->droite);
    }
    if ((*arbre)->str != NULL)
    {
      free ((*arbre)->str);
      (*arbre)->str = NULL;
    }
    free (*arbre);
    *arbre = NULL;
    arbre  = NULL;
  }
  
  return;
}

/*****************************************************************************/

Dernière modification par pipomolo (Le 22/11/2007, à 11:12)

Hors ligne

#34 Le 22/11/2007, à 11:25

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

pipomolo a écrit :
nicolas.sitbon a écrit :

ouais une fois qu'on a corrigé les fautes...

lol, faut pas oublier que j'ai fait le truc en 10 minutes, donc je conçois qu'il y ait 2 ou 3 soucis, le plus grave étant l'oubli d'allouer un caractère supplémentaire pour la terminaison de la string... et le return 0 dans le main, mais rien de bien méchant...pour la destruction, ta proposition n'est pas non plus exempte de défaut, puisque tu accèdes un pointeur sans vérifier s'il est différent de NULL wink sans rancune donc big_smile...

J'avais effectivement oublié de mettre à  NULL la racine de chaque "sous-arbre", ce qui implique de passer un pointeur de pointeur, bien vu...

Pour les prototypes, c'est du chipotage, pour un bout de code posté sur un forum wink

Par contre, je n'aime personnellement pas du tout ce genre de choses:

   int i = 1;

   for (; i < argc; i++)

Chaque bloc de code doit être indépendant du reste du code...ce qui n'est pas le cas ici...

A noter que ça vaut aussi pour l'utilisation de sizeof, sachant que pour ça ton code est meilleur que le mien...

Le fait de vérifier si le pointeur est à  NULL n'est pas imposer par la norme et est à  la charge du programmeur pas de l'implémenteur. Pour les prototypes, pas le choix, un compilateur bien réglé (et j'aime à  croire que c'est le cas du mien) refusera de compiler sans les prototypes.
Pour la boucle for je suis de ton avis mais la c'est de votre faute, la plupart des gens utilisent encore des compilateur pre c99 du coup impossible de limiter la porter de la variable i comme ceci

for (int i = 0; i < ...; i++)
{
}

Cordialement.

Hors ligne

#35 Le 22/11/2007, à 12:02

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

nicolas.sitbon a écrit :

Le fait de vérifier si le pointeur est à  NULL n'est pas imposer par la norme et est à  la charge du programmeur pas de l'implémenteur.

C'est vrai...du coup mon implémentation consiste à  rajouter les bretelles en plus de la ceinture...je conçois que c'est exagéré, et alourdi inutilement le code.

nicolas.sitbon a écrit :

Pour les prototypes, pas le choix, un compilateur bien réglé (et j'aime à  croire que c'est le cas du mien) refusera de compiler sans les prototypes.

Quel compilateur utilise-tu et avec quelle configuration ? à‡a m'intéresse.

nicolas.sitbon a écrit :

Pour la boucle for je suis de ton avis mais la c'est de votre faute, la plupart des gens utilisent encore des compilateur pre c99 du coup impossible de limiter la porter de la variable i comme ceci

for (int i = 0; i < ...; i++)
{
}

Cordialement.

J'utilise gcc 4.1 avec la configuration par défaut sous Ubuntu 7.10. Pour compiler en c99, il suffit de passer l'option -std=c99 à  gcc ?

Hors ligne

#36 Le 22/11/2007, à 12:34

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

pipomolo a écrit :
nicolas.sitbon a écrit :

Le fait de vérifier si le pointeur est à  NULL n'est pas imposer par la norme et est à  la charge du programmeur pas de l'implémenteur.

C'est vrai...du coup mon implémentation consiste à  rajouter les bretelles en plus de la ceinture...je conçois que c'est exagéré, et alourdi inutilement le code.

Non au contraire, je suis d'accord avec toi, moi j'avais juste fais le minimum syndical mais c'est mieux comme ça c'est sûr.

pipomolo a écrit :
nicolas.sitbon a écrit :

Pour les prototypes, pas le choix, un compilateur bien réglé (et j'aime à  croire que c'est le cas du mien) refusera de compiler sans les prototypes.

Quel compilateur utilise-tu et avec quelle configuration ? à‡a m'intéresse.

Sunstudio 12 et gcc.

pipomolo a écrit :
nicolas.sitbon a écrit :

Pour la boucle for je suis de ton avis mais la c'est de votre faute, la plupart des gens utilisent encore des compilateur pre c99 du coup impossible de limiter la porter de la variable i comme ceci

for (int i = 0; i < ...; i++)
{
}

Cordialement.

J'utilise gcc 4.1 avec la configuration par défaut sous Ubuntu 7.10. Pour compiler en c99, il suffit de passer l'option -std=c99 à  gcc ?

tu crois mais le support de C99 sous n'est pas encore abouti http://www.gnu.org/software/gcc/gcc-4.2/c99status.html néanmoins c'est vrai qu'il supporte ce type de déclaration.
Pour les options de gcc je conseille :

-g -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int -Werror-implicit-function-declaration -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings  -Wsign-compare -Waggregate-return  -Wmissing-prototypes  -Wmissing-declarations -Wmissing-noreturn -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wlong-long -Wunreachable-code -std=gnu99 -Werror

Cordialement.

Hors ligne