π
<-
Chat plein-écran
[^]

Besoin d'aide pour trouver des erreurs dans du code C

Assembleur, Axe, C/C++, ICE...

Besoin d'aide pour trouver des erreurs dans du code C

Message non lude Bobb » 07 Fév 2022, 18:44

Bonjour à tous,
J'ai commencé à apprendre le C il n'y a pas si longtemps, et débutant que je suis, il m'arrive souvent de faire des erreurs.
En ce moment, je programme des fonctions pour les chaînes de caractères et pour des listes de nombres entiers et de chaines de caractères, dans le but après de les utiliser pour un plus gros programme.
Le problème est que dans ces manipulations de mémoire et de pointeurs, il faut faire attention aux fuites de mémoire etc, et si je ne règle pas tous les problèmes de mes fonctions maintenant, c'est tout mon programme après qui causera plein d'erreurs.

C'est pour ça que j'ai besoin de votre aide.

J'ai testé toutes les fonctions grâce au compilateur MinGW sur Windows 10, et tout fonctionne, mais j'aimerais avoir des conseils de personnes qui s'y connaissent.

Si vous voyez des mauvaises habitudes de programmation dans mon code, ou des choses que je pourrais optimiser, ou des choses à ne pas faire, ou juste si vous avez un commentaire à faire, n'hésiter pas à répondre au topic et à me donner des conseils.

Même si cette démarche de trouver des erreurs dans un code qui n'en présente pas quand on l'exécute peut paraître étrange, je préfère être sûr de partir avec un code propre.

Voici déjà les fonctions de chaînes de caractères :

Code: Tout sélectionner

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



void testsFonctions(void);
char* sub(char* string,int debut,int fin);//a liberer après
char* replace(char*, char*, char*);//a liberer après
void cleanStdin(void);
char* addStr(char* str1, char* str2);//a liberer après
long double strToNb(char *string);
char* nbToStr(long double number);//a liberer après
int count(char* string, char* search);
void pause(void);
char* input(char *text);//a libérer après
char* subReplace(char* string, int debut, int longueur, char* remplacement);//à liberer après


int main(void)
{
 
  testsFonctions();
 
  return 0;
}




void testsFonctions(void)
{
 
  //test pour nbToStr
  long double nombre = 16516.5563;
  char* nombrestr=nbToStr(nombre);
  printf("%s\n",nombrestr);
  pause();
 
 
 
 
  //tests pour input et addStr
  char* prenom = input("Quel est votre prenom ? ");
  char* nom = input("Quel est votre nom ? ");
  char* nom_prenom=addStr(addStr(prenom," "),nom);
  printf("Vous vous appelez %s.\n",nom_prenom);
  pause();
  free(nom);free(prenom);
 
 
 
 
  //tests pour sub
  char* chaine="salut les potes";
  char* souschaine=sub(chaine,4,7);
  printf("%s\n",souschaine);
  free(souschaine);
 
 
 
 
  //tests pour replace, nbToStr
  long double nombre2=123456.123;
  printf("%s\n",nbToStr(nombre2));
 
  char* str1 = "01011000101011100010101010100011";
 
  char* str2;
  printf("%s\n",str1);
  str2 = replace(replace(replace(str1,"1","tic"),"0","toc"),"ct","c,t");
  printf("%s\n",str2);
 
  pause();
  free(str2);
 
}





void cleanStdin(void)// vide le buffer
{
    int c = 0;
    while ((c = getchar()) != '\n' && c != EOF);
}



void pause(void)//
{
  printf("\nAppuyez sur une touche pour continuer...");
  cleanStdin();
  //getchar();

}




char* input(char *text)//
{
  char* var=malloc(101*sizeof(char)); // allocation d'un pointeur pour l'entrée de l'utilisateur (+1 char pour le caractère nul)
  if (var==NULL) { exit(-1); }// si l'allocation échoue
 
  memset(var,(char)0,101*sizeof(char));//initialise le pointeur à '\0' partout
 
  //on effectue l'entrée
  printf("%s",text);
  scanf("%100[^\n]",var);
  cleanStdin();
 
  //crée un deuxième pointeur pour y copier le contenu de l'entrée de la vraie longueur
  char* newVar = malloc(sizeof(char)*(strlen(var)+1));//réserve une place de la longueur de l'entrée + 1 pour le caractère nul
  if (newVar==NULL) { exit(-1); }// si l'allocation échoue
 
  memset(newVar,0,sizeof(char)*(strlen(var)+1));//initialise tout à 0
 
  strcpy(newVar,var);//copie de var dans newVar
  free(var);var=NULL;//libération de var
 
  return newVar;
}




int count(char* string, char* search)//compte le nombre d'occurrences d'une chaîne dans une autre
{

int count=0;

  if ( strlen(search) <= strlen(string) )//si la chaîne à rechercher est plus petite que celle dans laquelle on effectue la recherche
  {
    char* tempstr;
    for(int i=0;i<=strlen(string)-strlen(search);i++)
    {
      tempstr=sub(string,i,i+strlen(search)-1);//on va tester la sous chaine de position i
     
      if ( strcmp(search,tempstr)==0 )
      {
        count++;
      }
      free(tempstr);
    }
   
  }
 
 
  return count;
}




char* sub(char* string,int debut,int fin)//permet d'extraire une sous-chaine
{
  int longueur = fin-debut+1;
  char* newStr = malloc(longueur * sizeof(char)+1);//allocation d'un pointeur
  memset(newStr,0,longueur*sizeof(char)+1);//initialisation à 0
  if (newStr==NULL) { exit(-1); }
 
  for (int i=0; i<longueur && i+debut<strlen(string); i++) {//recopie les caractères
    newStr[i]=string[i+debut];
  }
 
  newStr[longueur]='\0';// ajoute je caractère nul
 
  return newStr;
}




char* addStr(char* str1, char* str2)// concatène deux chaines de caractères
{
  char* newStr = malloc(strlen( str1 ) + strlen( str2 ) + 1);
  if (newStr==NULL) { exit(-1); }
 
  strcpy(newStr,str1 );
  strcat(newStr,str2 );

  return newStr;
}




long double strToNb(char *string)//convertit une chaîne de caractère en nombre
{
  long double nombre;
  sscanf(string,"%Lf",&nombre);
  return nombre;
}



char* nbToStr(long double number)//nombre en chaine de caractère
{
  char* strNombre=malloc(50*sizeof(char));//on estime qu'un long double ne fait pas plus de 50 caractères de longueur
  if (strNombre==NULL) { exit(-1); }
  snprintf(strNombre, 50, "%Lf", number);//converison du nombre
 
 
  while (strNombre[strlen(strNombre)-1]=='0')//on enlève les zéros inutiles à la fin
  {
    strNombre[strlen(strNombre)-1]='\0';
  }
 
 
  if (strNombre[strlen(strNombre)-1]=='.')//si on a enlevés tous les zéros, on enlève aussi la virgure
  {
    strNombre[strlen(strNombre)-1]='\0';
  }
 
  return strNombre;
 
}



char* subReplace(char* string, int debut, int longueur, char* remplacement)//effectue un remplacement quand on lui indique l’endroit et la longueur
{
  char* resultat=sub(string,0,debut-1);//prend le début

  resultat=addStr(resultat,remplacement);//ajoute la chaîne de remplacement
 
  resultat=addStr(resultat,sub(string,debut+longueur,strlen(string)-1));//ajoute la fin
   
  return resultat;
}



char* replace(char* string, char* aRemplacer, char* remplacement)//remplace toutes les occurrences d’une chaine par une autre
{
  char* ptrSubStr=0;
  char* tmp;
  while ((ptrSubStr=strstr(string,aRemplacer)) != NULL)//appels successifs a subReplace tant que l’on detecte la chaine a remplacer dans string
  {
    tmp=subReplace(string,(int)ptrSubStr-(int)string,strlen(aRemplacer),remplacement);//enregistrement du résultat dans une chaine temporaire pour pouvoir libérer le contenu pointé par string avant de réaffecter string
   free(string);
   string=tmp;
  }
 
  return string;
}







et voici le retour d'exécution :

Image



Maintenant les fonctions de listes :


Code: Tout sélectionner
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char* nbToStr(long double number)//nombre en chaine de caractère
{
  char* strNombre=malloc(50*sizeof(char));//on estime qu'un long double ne fait pas plus de 50 caractères de longueur
  if (strNombre==NULL) { exit(-1); }
  snprintf(strNombre, 50, "%Lf", number);//converison du nombre
 
 
  while (strNombre[strlen(strNombre)-1]=='0')//on enlève les zéros inutiles à la fin
  {
    strNombre[strlen(strNombre)-1]='\0';
  }
 
 
  if (strNombre[strlen(strNombre)-1]=='.')//si on a enlevés tous les zéros, on enlève aussi la virgure
  {
    strNombre[strlen(strNombre)-1]='\0';
  }
 
  return strNombre;
 
}


//définition des structures de listes de nombres et de chaînes de caractères et définition des deux nouveaux types
typedef struct
{
  long long int* tab;
  unsigned len;
 
} intlist;




typedef struct
{
  char** tab;
  unsigned len;
 
} strlist;


//prototypes des fonctions

//intlist
intlist intlist_create(unsigned len);
void intlist_aff(intlist* list);
void intlist_append(intlist* list,long long int nombre);
void intlist_resize(intlist* list, unsigned newLen);
void intlist_remove(intlist* list,unsigned index);


//strlist
strlist strlist_create(unsigned len);
void strlist_aff(strlist* list);
void strlist_append(strlist* list, char *chaine);
void strlist_resize(strlist* list, unsigned newLen);
void strlist_remove(strlist* list,unsigned index);






int main(void)
{
  //contient les tests
 
  intlist maListe=intlist_create(0);//crée une liste de taille zéro
 
  intlist_aff(&maListe);// affiche la liste
 
  for (unsigned i=0;i<14;i++)// ajoute des éléments
    intlist_append(&maListe,(long long int)i);

  intlist_aff(&maListe);// affiche la liste
 
  intlist_resize(&maListe, maListe.len+5);// ajoute 5 éléments à la taille actuelle
  intlist_aff(&maListe);// affiche
 
  intlist_remove(&maListe,0);// supprime le premier élément
  intlist_aff(&maListe);// affiche la liste
 
  /*****************************************/
 
  strlist maListestr=strlist_create(0);//crée une liste de taille zéro
  strlist_aff(&maListestr);// affiche la liste
 
  for (unsigned i=0;i<14;i++)// ajoute des éléments
    strlist_append(&maListestr,nbToStr(15-i));

  strlist_aff(&maListestr);// affiche la liste
 
  strlist_resize(&maListestr, maListestr.len-5);// enlève 5 éléments à la taille actuelle
  strlist_aff(&maListestr);// affiche
 
  strlist_remove(&maListestr,0);// supprime le premier élément
  strlist_aff(&maListestr);// affiche la liste

 
 
  return 0;
}




//intlist

intlist intlist_create(unsigned len)// crée une liste d'entiers
{
  intlist list;//crée la structure
  list.tab=malloc(len*sizeof(long long int));//initialise le tableau de longueur len avec de zéros
  if (list.tab==NULL) {exit(-1);}
  memset(list.tab,0,len);
 
  list.len=len;//initialise la bonne longueur
  return list;//retourne la structure
}




void intlist_aff(intlist* list)//affiche une liste d'entiers
{
  if (list->len == 0)//si la liste a une longueur de zéro
  {
    printf("[]\n");
  }
  else
  {
    printf("[");
    for ( unsigned i = 0 ; i < list->len -1 ; i++)//affiche les éléments du premier à l'avant-dernier
      printf("%lli, ",list->tab[i]);
 
    printf("%lli]\n",list->tab[list->len-1]);//affiche le dernier élément
  }
}




void intlist_append(intlist* list,long long int nombre)//ajoute un élément à la fin de la liste
{
  long long int *tmp = realloc(list->tab, (list->len+1)*sizeof(long long int));//réallocation de list.tab
  if (tmp == NULL){exit(-1);}

  list->tab = tmp;//affectation du pointeur de tmp vers list.tab

  list->tab[list->len]=nombre;//affecte nombre au dernier élément
  list->len++;//incrémente la longueur
}



void intlist_resize(intlist* list, unsigned newLen)//redimensionne la liste avec la nouvelle longueur
{
  long long int *tmp = realloc(list->tab, newLen*sizeof(long long int));//réalloue un pointeur de la nouvelle taille

  if (tmp == NULL){exit(-1);}

  list->tab = tmp;
 
  if (newLen > list->len)//initialisation des nouveaux éléments à 0 si nouveaux éléments il y a
  {
    for (unsigned i = list->len ; i < newLen ; i++)
     list->tab[i]=0;
  }
 
  list->len=newLen;//modification de la longueur
 
}





void intlist_remove(intlist* list,unsigned index)//supprime un élément de la liste
{
  for (unsigned i = index ; i < list->len -1; i++)//décale tous les éléments à partir de celui à supprimer
    list->tab[i]=list->tab[i+1];
 
  long long int *tmp = realloc(list->tab, (list->len-1)*sizeof(long long int));//réalloue un nouveau pointeur de la bonne taille

  if (tmp == NULL){exit(-1);}

  list->tab = tmp;
 
  list->len--;//décrémentation de la longueur
 
}







//strlist


strlist strlist_create(unsigned len)
{
  strlist list;
  list.tab=malloc(len*sizeof(char*));
  if (list.tab==NULL) {exit(-1);}
  memset(list.tab,0,len);
  list.len=len;
  return list;
}





void strlist_aff(strlist* list)
{
  if (list->len == 0)
  {
    printf("[]\n");
  }
  else
  {
    printf("[");
    for ( int i = 0 ; i < list->len -1 ; i++)
      (list->tab[i]==NULL) ? printf("\"\", ") : printf("\"%s\", ",list->tab[i]);//affiche "" si le pointeur est nul
 
 
   (list->tab[list->len-1]==NULL) ? printf("\"\"]\n") : printf("\"%s\"]\n",list->tab[list->len-1]);//dernier élément
  }
}




void strlist_append(strlist* list, char *chaine)
{
  char **tmp = realloc(list->tab, (list->len+1)*sizeof(char*));

  if (tmp == NULL){exit(-1);}

  list->tab = tmp;

  list->tab[list->len]=chaine;
  list->len++;
}




void strlist_resize(strlist* list, unsigned newLen)
{
 
  //il faut au préalable libérer les éléments qui vont être tronqués si la nouvelle longueur est plus petite
  if (newLen < list->len)
  {
      for (unsigned i = newLen ; i < list->len ; i++)
       free(list->tab[i]);
  }
 
 
  char **tmp = realloc(list->tab, newLen*sizeof(char*));
  if (tmp == NULL){exit(-1);}

  list->tab = tmp;
 
 
  if (newLen > list->len)//on initialise les nouveaux elements si nouveaux elements il y a
  {
    for (unsigned i = list->len ; i < newLen ; i++)
     list->tab[i]=(char*)0;
  }
 
  list->len=newLen;
 
}



void strlist_remove(strlist* list,unsigned index)
{
  for (unsigned i = index ; i < list->len -1; i++)
    list->tab[i]=list->tab[i+1];
 
  free(list->tab[list->len]);
 
  char **tmp = realloc(list->tab, (list->len-1)*sizeof(char*));
  if (tmp == NULL){exit(-1);}
 
  list->tab = tmp;
  list->len--;
 
}





Le retour d'exécution :
Image

Merci de votre contribution,
Bobb
Dernière édition par Bobb le 07 Fév 2022, 19:20, édité 2 fois.

Tous mes programmes sont disponibles ici

↳ Testez mon simulateur Android sur Ti-83 Premium CE et / ou Édition Python
Jetez un coup d'oeil à mon langage de programmation interprété Neon.

Image
Avatar de l’utilisateur
BobbProgrammeur
Niveau 10: GR (Guide de Référence)
Niveau 10: GR (Guide de Référence)
Prochain niv.: 94.5%
 
Messages: 300
Inscription: 19 Avr 2020, 12:37
Localisation: Morbihan
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: CPGE MPI

Re: Besoin d'aide pour trouver des erreurs dans du code C

Message non lude Adriweb » 07 Fév 2022, 19:05

J'ai juste parcouru tres rapidement le code, et je vois que tu définis la fonction "subReplace" à l'intérieur d'une autre fonction ! Ca c'est pas bon, tu as de la chance que ca marche, c'est une extension spéciale du compilateur gcc. Déplace la uste au dessus, par exemple.
As-tu utilisé des outils d'analyse statique ? genre cppcheck.
Par ailleurs, essaye un IDE genre Clion, c'est gratuit pour les etudiants :) (et sinon trial) Il t'aidera pas mal, voire trouvera des choses à améliorer/corriger dans ton code.

Sur Windows ca risque d'etre compliqué, mais sinon pour les fuites et comportements pas normaux, ASAN et Valgrind sont des bons amis à avoir...
Image

MyCalcs: Help the community's calculator documentations by filling out your calculators info!
MyCalcs: Aidez la communauté à documenter les calculatrices en donnant des infos sur vos calculatrices !
Inspired-Lua.org: All about TI-Nspire Lua programming (tutorials, wiki/docs...)
Avatar de l’utilisateur
AdriwebAdmin
Niveau 16: CC2 (Commandeur des Calculatrices)
Niveau 16: CC2 (Commandeur des Calculatrices)
Prochain niv.: 80.2%
 
Messages: 14613
Images: 1218
Inscription: 01 Juin 2007, 00:00
Localisation: France
Genre: Homme
Calculatrice(s):
MyCalcs profile
Twitter/X: adriweb
GitHub: adriweb

Re: Besoin d'aide pour trouver des erreurs dans du code C

Message non lude Bobb » 07 Fév 2022, 19:22

OK, c'est bon,j'ai changé subReplace.
Sinon, merci pour tous les outils je testerai un peu tout ça.

Tous mes programmes sont disponibles ici

↳ Testez mon simulateur Android sur Ti-83 Premium CE et / ou Édition Python
Jetez un coup d'oeil à mon langage de programmation interprété Neon.

Image
Avatar de l’utilisateur
BobbProgrammeur
Niveau 10: GR (Guide de Référence)
Niveau 10: GR (Guide de Référence)
Prochain niv.: 94.5%
 
Messages: 300
Inscription: 19 Avr 2020, 12:37
Localisation: Morbihan
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: CPGE MPI

Re: Besoin d'aide pour trouver des erreurs dans du code C

Message non lude Bobb » 14 Fév 2022, 11:36

Bon j'ai trouvé environ 200 fuites mémoire dans le programme à cause de la fonction subReplace et 2 ou 3 dans la fonction de tests des fonctions de chaînes de caracteres.
Je préviens que je n'ai pas mis à jour le code dans le premier message.

Tous mes programmes sont disponibles ici

↳ Testez mon simulateur Android sur Ti-83 Premium CE et / ou Édition Python
Jetez un coup d'oeil à mon langage de programmation interprété Neon.

Image
Avatar de l’utilisateur
BobbProgrammeur
Niveau 10: GR (Guide de Référence)
Niveau 10: GR (Guide de Référence)
Prochain niv.: 94.5%
 
Messages: 300
Inscription: 19 Avr 2020, 12:37
Localisation: Morbihan
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: CPGE MPI


Retourner vers Langages alternatifs

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 7 invités

-
Rechercher
-
Social TI-Planet
-
Sujets à la une
Comparaisons des meilleurs prix pour acheter sa calculatrice !
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
Phi NumWorks jailbreak
123
-
Faire un don / Premium
Pour plus de concours, de lots, de tests, nous aider à payer le serveur et les domaines...
Faire un don
Découvrez les avantages d'un compte donateur !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partenaires et pub
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
1271 utilisateurs:
>1235 invités
>31 membres
>5 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Autres sites intéressants
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)