cs_flofloo
Messages postés45Date d'inscriptionsamedi 5 juin 2004StatutMembreDernière intervention16 mars 2009
-
6 août 2008 à 11:49
SAKingdom
Messages postés3212Date d'inscriptionlundi 7 novembre 2005StatutMembreDernière intervention16 février 2009
-
7 août 2008 à 16:10
bonjour tout le monde j'ai un probleme avec la gestion des pointeurs voila je m'explique de suite...
j'ai une fonction "ExtractString" dont voici l'entete :
char *ExtractString(char *string,int pos,char sep);cette fonction extrait une sous chaine de l'argument "string".le remplisage du pointeur renvoyer par la fonction commence a partir de l'argument pos et continue tant que le caractere lu est different de l'argument sep!
mais voila la sous chaine renvoyee ne prend que 32 caracteres!alors comment empecher le debordement memoire durant le remplisage du pointeur!
gespere m'etre bien expliquer
merci..
Neo_Fr
Messages postés653Date d'inscriptionmardi 6 décembre 2005StatutMembreDernière intervention10 novembre 20142 6 août 2008 à 12:28
Une string est normalement toujours terminer par le caractere NULL(0), tu as donc juste a controle que le caractere pointé par ton pointeur est positif..
Poste ton code sinon ce sera mieux pour t'aider
cs_flofloo
Messages postés45Date d'inscriptionsamedi 5 juin 2004StatutMembreDernière intervention16 mars 2009 6 août 2008 à 15:21
mince g fait kelke erreur dsl :
dans le while :
extract[i] = c;//et non sep
i++;
c = string[i];
et si vous pouver m'aider dans l'ecriture avec les pointeur d'une facon plus efficace merci..et dsl encore
Neo_Fr
Messages postés653Date d'inscriptionmardi 6 décembre 2005StatutMembreDernière intervention10 novembre 20142 6 août 2008 à 16:19
Evite tant que possible de retourner de la memoire allouer avec malloc si tu veux pas etre obliger de faire des free() partout dans ton code.., le mieux reste d'écrire directement sur un pointeur passer en param de cette facon tu fait l'alloc/desalloc en dehors de ta fonction ce qui evite tout oublie de desalloc..
zaibacker
Messages postés97Date d'inscriptionvendredi 17 février 2006StatutMembreDernière intervention24 janvier 2018 6 août 2008 à 16:29
Salut, je te propose ce code que je n'ai pas testé
2 inconvénients:
- dans notre cas nous n'avons alloué que 32 octets(soit 32 caractères au maximum).
- si l'arguments "sep" n'est pas trouvé, je ne veux même pas savoir ce qui va se passer car ile while n'a aucune autre clause d'arret.
extract[i] = '\0';
}
PS: je crois que "char *extract malloc(32*sizeof(char));" pourrait être remplacé par "char *extract malloc(strlen(string)*sizeof(char)); "
cs_Telepathmaster
Messages postés46Date d'inscriptionvendredi 31 octobre 2003StatutMembreDernière intervention 7 août 2008 7 août 2008 à 13:34
Pour revenir à la question de l'allocation dynamique, même si pour ce type de fonction il est clair qu'un alloc interne n'est pas la meilleure solution, je donnerais ça pour la posterité et la pédagogie pour les cas où c'est nécessaire :
/* Rappel au passage qu'un pointeur est passé par valeur */
str += pos;
for ( i = 0; i < strlen(str) && str[i] != sep;i++);
/* Connaissant désormais la taille à allouer on ne risque plus l'overflow */
ext = malloc(i+1);
memcpy(ext,str,i);
ext[i] = 0;
return ext;
}
int main() {
char str [] = "da;test;string", * tmp;
if ((tmp = extractString(str,3,';')) != NULL)
printf("%s\n",tmp);
free(tmp);
return 0;
}
Une autre solution, come cité plus haut serait de systématiquement allouer la taille de la chaine originale, mais dans ce cas l'utilité d'une allocation dynamique devient nulle.
SAKingdom
Messages postés3212Date d'inscriptionlundi 7 novembre 2005StatutMembreDernière intervention16 février 200915 7 août 2008 à 14:47
Appel strlen UNE SEULE FOIS avant le test if(pos > strlen(...)). D'ailleurs ici, ça devrait être if(pos >= len).
Puisque que la taille est déjà récupérée, on l'utilisera aussi dans la boucle mais sinon, suffit simplement de tester si le caractère courant (str[i]) est non nul.
"mais dans ce cas l'utilité d'une allocation dynamique devient nulle."
Peut-être mais pour la perte de cycle CPU que cela occasionne, peut-être est-il mieux de ne pas en tenir compte.
cs_Telepathmaster
Messages postés46Date d'inscriptionvendredi 31 octobre 2003StatutMembreDernière intervention 7 août 2008 7 août 2008 à 15:13
Tout d'abord, les "oprimisations" du type n'appeller une fonction constante qu'une fois ont rarement un effet positif. Voire des effets négatifs. Pourquoi ? Parce qu'il est incroyable de voir ce que le compilateur fait dans notre dos. Notamment, ce genre de chose est transformée en un seul appel dont la valeur est stockée dans un registre (pas forcément le cas d'une variable déclarée explicitement). Ca dépend des compilateurs, des plateformes, à tel point que ça ne vaut pas la peine d'en parler.
Si on veut chipoter, je dirais qu'un str[i] impose un defer du pointeur et prends un cycle d'horloge de plus qu'une comparaison avec un entier.
Enfin, et *surtout* j'ai écrit rapidement ce bout de code pour permettre à l'auteur du topic d'avoir un exemple d'utilisation de pointeurs et de l'allocation dynamique, sans prétendre qu'il était meilleur ou optimisé. J'ai d'ailleurs précisé que ce n'était pas la meilleure solution. Ceci dit, pour la compréhension il est bon de pouvoir connaitre une ou deux manières de faire. Je rappelle d'ailleurs que beaucoup de librairies ou d'interfaces (SQLite, OpenSSL, ...) utilisent couramment ce genre de techniques.
Quoiqu'il en soit, j'avoue que je passe par ce site assez rarement. Quand je vois un message auquel je peux répondre rapidement et simplement je le fais. Si c'est pour me coltiner des réponses négatives et qui réduisent ma contribution à deux points lambda qui n'ont pas de rapport avec le sujet alors que j'essaie d'apporter un tout petit peut de pédagogie, merci bien...
SAKingdom
Messages postés3212Date d'inscriptionlundi 7 novembre 2005StatutMembreDernière intervention16 février 200915 7 août 2008 à 16:10
"Parce qu'il est incroyable de voir ce que le compilateur fait dans
notre dos. Notamment, ce genre de chose est transformée en un seul
appel dont la valeur est stockée dans un registre (pas forcément le cas
d'une variable déclarée explicitement)."
Pas du tout. La valeur déclaré explicitement a toutes les chances d'être placée directement dans un registre. Un appel à une fonction de ce genre est trop incertain. En effet, rien ne garanti au compilo que la chaine ne sera pas modifiée dans la boucle (explicitement ou avec une fonction). Pour cette raison, un appel à une fonction reste un appel à une fonction ("inliné" dans certains cas mais dont le code est toujours présent.) et doit être considéré ainsi dans le code source aussi.
char buf[300];
int i;
fgets(buf, sizeof(buf), stdin);
for(i = 0; i < strlen(buf); i++)
printf("%c", buf[i]);
Génère donc un listing de ce code et jette un coup d'oeil au code assembler (optimiser par le compilo bien entendu). Tu me reparleras de tes supposées optimisations automatiques après.
Je remarque une chose bien précis (code généré avec VC++):
$LL9@main:
mov cl, BYTE PTR [eax]
inc eax
test cl, cl
jne SHORT $LL9@main
C'est le strlen "inliné".
Et ce code est tout en bas de la boucle et reviendra donc forcément à chaque tour de boucle.
"Si c'est pour me coltiner des réponses négatives et qui réduisent ma
contribution à deux points lambda qui n'ont pas de rapport avec le
sujet alors que j'essaie d'apporter un tout petit peut de pédagogie,
merci bien..."
Je n'essaie pas de réduire pas tes efforts à zéro. J'essaie de les corriger au mieux de mon savoir.
N'oublie pas que les débutants on tendance à tout copier sans se posé de question.