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: Select all
#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 :

Maintenant les fonctions de listes :
- Code: Select all
#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 :

Merci de votre contribution,
Bobb