Le langage SMS est exclu sur les forums ProgBoards, tout message ne respectant pas la charte sera déplacé, modifié, ou supprimé par nos modérateurs.

Forum Langages » C & Cie. » Parser une chaine (C)

Amwus
ProgBoarder
Citer Linux Firefox 3 - Posté le 18/02/2009 à 13:20
Salut les gens ! Comment ça va par ici ?! Ca fait un bail que je ne suis plus venu... Et le pire, c'est que je reviens pour demander un coup de main ! (héhé

Voila, en fait, je suis en train de développer un ensemble de fonctions pour parser des chaines de caractères... Mais voila, pour qu'une fonction me renvoit une chaine, elle est de type char*.

Donc ça implique des mallocs à l'intérieur de la fonction. En effet, par exemple, dans une fonction char* parse(char* string), j'analyse la chaine string, je récupère ce que je veux, je le met dans une nouvelle chaine que je renvoit.

Cette nouvelle chaine est allouée dynamiquement par malloc... Cela implique des frees...

Ma question est : est on obligé d'utiliser une allocation dynamique ? N'y a -t- il pas moyen en C de renvoyer une chaine sans l'allouer dynamiquement ? BOn, pour l'instant ça fonctionne, mais valgrind me renvoit un tas d'erreurs bizarres...

Merci d'avance !

A bientot ! (cool)
"Engl Amps are the best i've ever used... Not only are they powerfull, but they have charachter too..." R. Blackmore
RemonterCiter Linux Firefox 3 - Posté le 18/02/2009 à 13:24
Peut-tu envisager de créer un tableau de char et de retourner son pointeur?
Change la caféine en lignes de code, et aurait parfois besoin de l'inverse.
Amwus
ProgBoarder
RemonterCiter Linux Firefox 3 - Posté le 18/02/2009 à 13:34
je crois que c'est ce que je fais actuellement...

je crée un tableau de ce style :


char* chaine = (char*)malloc(length * sizeof(char));



Ensuite, je le remplis avec des caractères, et je le renvois... Est ce une façon "propre" de bosser ? Je suis assez inquiet des erreurs trouvées par valgrind.

Pourtant je désalloue bien tout...
"Engl Amps are the best i've ever used... Not only are they powerfull, but they have charachter too..." R. Blackmore
beagle
Visiteur
RemonterCiter Windows XP Firefox 3 - Posté le 18/02/2009 à 18:09
hello,

si tu ne veux pas allouer avec malloc, tu peux créer dans ta fonction appelant un tableau de char alloué sur la stack, puis tu le passes en paramètre à ta fonction parse

void
func()
{
char result[256];

parse(result, "stringtoparse");
}



par contre, il faut faire attention que ta fonction parse n'écrit pas des données au delà de la taille du tableau de char alloué sur la stack. Pour ça tu peux passer en 3ème argument de parse, la taille du tableau.

a+
Francesco
Modérateur
RemonterCiter Windows NT Firefox 3 - Posté le 18/02/2009 à 18:19
Solution numéro 1
avoir une variable globale (je sais, c'est moche), qui sera une liste chainée de chaine allouée. A chaque fois que tu fais une nouvelle allocation, tu l'ajoute à cette liste chainée.

Ensuite, il faudra également que tu utilise la fonction atexit pour enregistrer une fonction qui sera automatiquement appelée à la fin du programme et qui liberera toutes les chaines de caractaires contenues dans la liste chainée.

Solution numéro 2
Inclure une nouvelle structure, qui correspond par exemple, à ton parser. Cette structure contiendra une liste chainée comme dans la solution numéro 1.

Ensuite, tu créé une fonction closeParser qui prend en parametre ton parser et qui libère les différentes chaines contenu dans la liste chainée.

Bien évidemment, il faut modifier ta fonction "parse" pour qu'elle prenne également en paramètre un pointeur sur ta structure, afin qu'elle puisse y rajouter une chaine si allocation il y a...

[edit]
Solution 3
Utiliser du C++ et des std::string ^^

[/edit]

Edité par Francesco ( 18/02/2009 18:20:08 )
Gates gave you the windows.
GNU gave us the whole house.(Alexandrin)
zuzuf
ProgBoarder
RemonterCiter Linux Firefox 3 - Posté le 19/02/2009 à 02:58
la meilleure solution dépend entièrement de tes besoins. Comment vas-tu utiliser cette fonction par la suite ?

Par exemple tu n'utilises que temporairement le résultat, un simple char[] "global" peut être suffisant:


char tmp[1024];

char *maFonctionQuiParse(char *monParametre)
{
// TODO: ecrire la fonction
...
return tmp;
}



pas besoin d'initialiser quoi que ce soit, le contenu de tmp est simplement réécrit à chaque appel de la fonction, donc pas d'allocations intempestives, par contre la taille du tampon est fixe donc il faut anticiper les besoins (sourire).

Pas besoin de free/malloc, et s'il faut préserver le résultat entre les appels à la fonction, alors un simple strdup fera l'affaire (héhé

PS: le C++ et les std::string c'est pratique mais pas super performant à cause des opérations de recopiage.
Linux a un noyau, windows un pepin
Freem
Modérateur
RemonterCiter Windows XP Firefox 3 - Posté le 19/02/2009 à 16:02
Si tu veux éviter l'allocation dynamique dans ta fonction à tout prix, je ne vois que la solution de beagle.
Mais comme l'as dis zuzuf, ça dépend de l'utilisation que tu veux en faire. Si tu traites des ensembles de grande taille dont le nombre ou la taille est aléatoire, les listes chaînées me paraissent plus appropriées, si tu ne traites que de petits ensembles, la solution du stack déjà alloué est plus efficace, dans le sens ou tu n'as pas besoin de réallouer a chaque fois, mais tu auras de la perte de mémoire.
Une solution alternative serait de chaîner des stacks, ce qui peut permettre d'avoir moins de pointeurs à gérer. Ce serait par exemple approprié dans le cas d'un nombre aléatoire de petits éléments, car ça consomme moins de mémoire qu'une liste chaînée (par exemple, si tes éléments font 10 caractères, une liste chaînée de 200 élément pèsera 200*(10+4)=2800, dont 800 de "perdus", avec un stack de 2000 octets, tu n'aurais pas de perte, mais si c'est aléatoire, comment estimer juste? Un mixe des 2 serait de chaîner 20 stacks de 100 octets. consommation: 20*(100+4)=2080 octets.).
Comme dis plus haut, la solution dépends de l'application.
Si tu peux prévoir de manière fiable la taille des éléments que tu parses, le stack est approprié.
Si tu ne peux pas le prévoir, mais que tes éléments seront probablement importants, la liste chaînée est idéale.
Si tu peux prévoir en partie, et que tes éléments sont probablement de taille réduite, le mixe des 2 pourrait être plus efficace, mais au niveau code, tu auras les contraintes des 2 solutions: la libération correcte de la mémoire, et l'obligation de communiquer la taille des stacks, pour éviter tout problème de sécurité et de stabilité.
Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. - Benjamin Franklin

Poster une réponse

STOP aux fautes volontaires !
Message
Formatage
Note: pour partager du code source, merci d'utiliser le wall !
Smileys (sourire) (yekyek) (clein d'oeil) (désapprouve) (triste) (cool) (langue) (confus) (gêné) (neutre) (eek) (surpris) (diable) (flèche) (exclamation) (question) (diable) (idée) (méchant)
Pseudonyme
Recopiez le code
v6 © Computaid SPRL 2005-2010 - Tous droits réservés - Hébergé par eTigris - Page générée en 0,018 s - Crédits - Stats
1 connecté