Je d=E9bute avec le C depuis quelques mois =E0 mon rhytme. J'arrive au
chapitre de l'allocation dynamique. J'ai abord=E9 les tableaux uni et
multidimensionnels, les pointeurs, les fonctions.
En fait, je comprends l'utilit=E9 de malloc dans le sens ou la
r=E9servation de la m=E9moire pour un tableau peut se faire en cours
d'ex=E9cution...
Pour la saisie de texte, je voudrais savoir s'il serait possible de
saisir une cha=EEne de caract=E8re variable avec fgets ? Je pense beaucoup
=E0 utiliser realloc.
Par exemple : je r=E9serve de la m=E9moire pour un pointeur vers une
adresse de type caract=E8re, pour 1 ou 2 caract=E8res et =E0 je demande =E0
l'utilisateur de saisir du texte. A chaque saisie, je r=E9serve la place
pour un caract=E8re suppl=E9mentaire en m=E9moire avec realloc, c'est
faisable? Bizarement, je ne trouve aucun code qui correspond =E0 ce que
je recherche sur le net.
Ca ressemble =E0 peu pr=E8s, mais =E7a ne marche pas :
http://www.cppfrance.com/forum/sujet-RECUERATION-CHAINE-CARACTERE-TAILLE-VA=
RIABLE-STDIN_1405662.aspx
Autre question sans lien avec la premi=E8re :
est-ce que =E9crire char* chaine =3D 0 et char *chaine =3D 0 revient =E0 la
m=EAme chose?
Par exemple : je réserve de la mémoire pour un pointeur vers une adresse de type caractère, pour 1 ou 2 caractères et à je demande à l'utilisateur de saisir du texte. A chaque saisie, je réserve la place pour un caractère supplémentaire en mémoire avec realloc, c'est faisable? Bizarement, je ne trouve aucun code qui correspond à ce que je recherche sur le net.
C'est faisable, mais personne ne le fait parce que ca n'est pas efficace. realloc a un cout non nul, du coup, on en fait moins.
Le classique, c'est de doubler la taille du tampon a chaque fois.
In article <10e8931a-0a01-4d97-9127-99399f04f4a8@e28g2000vbd.googlegroups.com>,
heron <cream1000s@yahoo.com> wrote:
Par exemple : je réserve de la mémoire pour un pointeur vers une
adresse de type caractère, pour 1 ou 2 caractères et à je demande à
l'utilisateur de saisir du texte. A chaque saisie, je réserve la place
pour un caractère supplémentaire en mémoire avec realloc, c'est
faisable? Bizarement, je ne trouve aucun code qui correspond à ce que
je recherche sur le net.
C'est faisable, mais personne ne le fait parce que ca n'est pas efficace.
realloc a un cout non nul, du coup, on en fait moins.
Le classique, c'est de doubler la taille du tampon a chaque fois.
Par exemple : je réserve de la mémoire pour un pointeur vers une adresse de type caractère, pour 1 ou 2 caractères et à je demande à l'utilisateur de saisir du texte. A chaque saisie, je réserve la place pour un caractère supplémentaire en mémoire avec realloc, c'est faisable? Bizarement, je ne trouve aucun code qui correspond à ce que je recherche sur le net.
C'est faisable, mais personne ne le fait parce que ca n'est pas efficace. realloc a un cout non nul, du coup, on en fait moins.
Le classique, c'est de doubler la taille du tampon a chaque fois.
heron
Pourquoi ce code ne renvoie pas le texte saisie?
#include <stdio.h> #include <stdlib.h>
int main(void) { char* chaine = 0 ; char c ; int i = 0 ;
printf("nVous avez entre : '%s'n", chaine) ; free(chaine) ;
return 0 ; }
simple question : char* chaine et char *chaine c'est différent?
De le même manière que "bonnet blanc" et "blanc bonnet" sont différents :-) Pour le compilateur: non.
-- Eric
heron
> char c ;
> while ( (c = getchar() ) && c != EOF ) {
while ( (c = getchar() ) && c != EOF && c != 'n' ) { termine la boucle en fin de ligne et affiche le texte.
> simple question : char* chaine et char *chaine c'est différent?
De le même manière que "bonnet blanc" et "blanc bonnet" sont différents :-) Pour le compilateur: non.
-- Eric
Il me semblait que c devait être déclaré comme int pour agir dans le buffer avec while ( c = getchar() != 'n' && c != EOF ) ; je pense que c'est parce que EOF renvoie -1 ...
Merci de l'info pour char* et char *
> char c ;
> while ( (c = getchar() ) && c != EOF ) {
while ( (c = getchar() ) && c != EOF && c != 'n' ) {
termine la boucle en fin de ligne et affiche le texte.
> simple question : char* chaine et char *chaine c'est différent?
De le même manière que "bonnet blanc" et "blanc bonnet" sont
différents :-)
Pour le compilateur: non.
--
Eric
Il me semblait que c devait être déclaré comme int pour agir dans le
buffer avec
while ( c = getchar() != 'n' && c != EOF )
;
je pense que c'est parce que EOF renvoie -1 ...
while ( (c = getchar() ) && c != EOF && c != 'n' ) { termine la boucle en fin de ligne et affiche le texte.
> simple question : char* chaine et char *chaine c'est différent?
De le même manière que "bonnet blanc" et "blanc bonnet" sont différents :-) Pour le compilateur: non.
-- Eric
Il me semblait que c devait être déclaré comme int pour agir dans le buffer avec while ( c = getchar() != 'n' && c != EOF ) ; je pense que c'est parce que EOF renvoie -1 ...
Merci de l'info pour char* et char *
Eric Dorino
On Fri, 14 May 2010 18:19:07 -0700, heron wrote:
Il me semblait que c devait être déclaré comme int pour agir dans le buffer avec
Effectivement.
while ( c = getchar() != 'n' && c != EOF ) ;
Attention à la priorité des opérateurs: vous voulez certainement while ( ( c = getchar() ) != 'n' && c != EOF )
je pense que c'est parce que EOF renvoie -1 ...
Plus exactement, getchar() renvoie un int.
Merci de l'info pour char* et char *
-- Eric
On Fri, 14 May 2010 18:19:07 -0700, heron wrote:
Il me semblait que c devait être déclaré comme int pour agir dans le
buffer avec
Effectivement.
while ( c = getchar() != 'n' && c != EOF )
;
Attention à la priorité des opérateurs: vous voulez certainement
while ( ( c = getchar() ) != 'n' && c != EOF )
Il me semblait que c devait être déclaré comme int pour agir dans le buffer avec
Effectivement.
while ( c = getchar() != 'n' && c != EOF ) ;
Attention à la priorité des opérateurs: vous voulez certainement while ( ( c = getchar() ) != 'n' && c != EOF )
je pense que c'est parce que EOF renvoie -1 ...
Plus exactement, getchar() renvoie un int.
Merci de l'info pour char* et char *
-- Eric
espie
Tant qu'a expliquer... meme si c'est de la FAQ.
Le type char est exactement assez grand pour contenir tous les codes de caracteres.
Du coup, la fin de fichier ne "rentre" pas: c'est un code en plus (et sur beaucoup d'OS, il n'y a pas de code specifique stocke sur le disque pour indiquer la fin de fichier, c'est la taille du fichier qui est marquee "quelque part" dans le repertoire).
En C, on utilise simplement un type un peu plus grand, a savoir int, qui permet: - de stocker tous les codes de caracteres sans perte - de rajouter un code supplementaire, qu'on appelle EOF.
Attention: EOF vaut souvent -1, mais je ne crois pas que ca soit meme rendu oblige par la norme. Suffit que ca soit une valeur distincte de tous les codes de caracteres (et c'est le plus souvent -1 parce que sinon du code mal ecrit va peter, et vous me croirez ma bonne dame, mais du code mal ecrit il y en a, et souvent les gens font passer la compatibilite avant le reste...)
Il y a pas mal de details scabreux, mais au final, cote typage:
int char_ou_eof = fgetc(f); if (char_ou_eof != EOF) { char c = char_ou_eof; }
doit avoir l'effet attendu sur tous les OS: lire "quelque chose" d'un fichier, reperer un EOF, et stocker ce quelque chose sous forme de caractere si on n'est pas arrive en fin de fichier.
Tant qu'a expliquer... meme si c'est de la FAQ.
Le type char est exactement assez grand pour contenir tous les codes de
caracteres.
Du coup, la fin de fichier ne "rentre" pas: c'est un code en plus (et sur
beaucoup d'OS, il n'y a pas de code specifique stocke sur le disque pour
indiquer la fin de fichier, c'est la taille du fichier qui est marquee "quelque
part" dans le repertoire).
En C, on utilise simplement un type un peu plus grand, a savoir int, qui
permet:
- de stocker tous les codes de caracteres sans perte
- de rajouter un code supplementaire, qu'on appelle EOF.
Attention: EOF vaut souvent -1, mais je ne crois pas que ca soit meme
rendu oblige par la norme. Suffit que ca soit une valeur distincte de
tous les codes de caracteres (et c'est le plus souvent -1 parce que sinon du
code mal ecrit va peter, et vous me croirez ma bonne dame, mais du code mal
ecrit il y en a, et souvent les gens font passer la compatibilite avant le
reste...)
Il y a pas mal de details scabreux, mais au final, cote typage:
int char_ou_eof = fgetc(f);
if (char_ou_eof != EOF) {
char c = char_ou_eof;
}
doit avoir l'effet attendu sur tous les OS: lire "quelque chose" d'un fichier,
reperer un EOF, et stocker ce quelque chose sous forme de caractere si on n'est
pas arrive en fin de fichier.
Le type char est exactement assez grand pour contenir tous les codes de caracteres.
Du coup, la fin de fichier ne "rentre" pas: c'est un code en plus (et sur beaucoup d'OS, il n'y a pas de code specifique stocke sur le disque pour indiquer la fin de fichier, c'est la taille du fichier qui est marquee "quelque part" dans le repertoire).
En C, on utilise simplement un type un peu plus grand, a savoir int, qui permet: - de stocker tous les codes de caracteres sans perte - de rajouter un code supplementaire, qu'on appelle EOF.
Attention: EOF vaut souvent -1, mais je ne crois pas que ca soit meme rendu oblige par la norme. Suffit que ca soit une valeur distincte de tous les codes de caracteres (et c'est le plus souvent -1 parce que sinon du code mal ecrit va peter, et vous me croirez ma bonne dame, mais du code mal ecrit il y en a, et souvent les gens font passer la compatibilite avant le reste...)
Il y a pas mal de details scabreux, mais au final, cote typage:
int char_ou_eof = fgetc(f); if (char_ou_eof != EOF) { char c = char_ou_eof; }
doit avoir l'effet attendu sur tous les OS: lire "quelque chose" d'un fichier, reperer un EOF, et stocker ce quelque chose sous forme de caractere si on n'est pas arrive en fin de fichier.
Jean-Marc Bourguet
(Marc Espie) writes:
Attention: EOF vaut souvent -1, mais je ne crois pas que ca soit meme rendu oblige par la norme.
Expression constante entière négative et je n'ai pas l'impression que POSIX impose plus.
Pour la saisie avec allocation dynamique de caractères avec getchar() comme dans le code plus haut ou de nombres entiers avec scanf, je trouve que ça rend les choses plus simples. Est-ce que pour la saisie d'une chaîne de caractère, on peut procéder avec fgets au lieu de getchar() ? Jusque là, fgets était le plus souvent employé.
Mais pour reprendre Marc plus haut
C'est faisable, mais personne ne le fait parce que ca n'est pas efficace. realloc a un cout non nul, du coup, on en fait moins.
L'allocation dynamique dans la saisie d'une chaîne de caractères de longeur variable ou d'entier avec scanf n'est pas efficace dans le sens ou il y a moins de sécurité ?
Le classique, c'est de doubler la taille du tampon a chaque fois.
Est-ce que c'est parce qu'un dépassement de buffer peut se produire avec l'allocation dynamique. Je ne vois pas très bien comment car getchar() ne lit qu'un seul caractère à chaque appel. Dans le premier post, je pensais à fgets, je pense que c'est pour fgets que ce n'est pas efficace. Je n'ai pas réfléchi à comment y arriver. Mais est-ce que ce n'est pas efficace parce le code est trop compliqué ou parce qu'il y a moins de sécurité?
Pour la saisie avec allocation dynamique de caractères avec getchar()
comme dans le code plus haut ou de nombres entiers avec scanf, je
trouve que ça rend les choses plus simples. Est-ce que pour la saisie
d'une chaîne de caractère, on peut procéder avec fgets au lieu de
getchar() ? Jusque là, fgets était le plus souvent employé.
Mais pour reprendre Marc plus haut
C'est faisable, mais personne ne le fait parce que ca n'est pas efficace.
realloc a un cout non nul, du coup, on en fait moins.
L'allocation dynamique dans la saisie d'une chaîne de caractères de
longeur variable ou d'entier avec scanf n'est pas efficace dans le
sens ou il y a moins de sécurité ?
Le classique, c'est de doubler la taille du tampon a chaque fois.
Est-ce que c'est parce qu'un dépassement de buffer peut se produire
avec l'allocation dynamique. Je ne vois pas très bien comment car
getchar() ne lit qu'un seul caractère à chaque appel. Dans le premier
post, je pensais à fgets, je pense que c'est pour fgets que ce n'est
pas efficace. Je n'ai pas réfléchi à comment y arriver. Mais est-ce
que ce n'est pas efficace parce le code est trop compliqué ou parce
qu'il y a moins de sécurité?
Pour la saisie avec allocation dynamique de caractères avec getchar() comme dans le code plus haut ou de nombres entiers avec scanf, je trouve que ça rend les choses plus simples. Est-ce que pour la saisie d'une chaîne de caractère, on peut procéder avec fgets au lieu de getchar() ? Jusque là, fgets était le plus souvent employé.
Mais pour reprendre Marc plus haut
C'est faisable, mais personne ne le fait parce que ca n'est pas efficace. realloc a un cout non nul, du coup, on en fait moins.
L'allocation dynamique dans la saisie d'une chaîne de caractères de longeur variable ou d'entier avec scanf n'est pas efficace dans le sens ou il y a moins de sécurité ?
Le classique, c'est de doubler la taille du tampon a chaque fois.
Est-ce que c'est parce qu'un dépassement de buffer peut se produire avec l'allocation dynamique. Je ne vois pas très bien comment car getchar() ne lit qu'un seul caractère à chaque appel. Dans le premier post, je pensais à fgets, je pense que c'est pour fgets que ce n'est pas efficace. Je n'ai pas réfléchi à comment y arriver. Mais est-ce que ce n'est pas efficace parce le code est trop compliqué ou parce qu'il y a moins de sécurité?
espie
In article , heron wrote:
L'allocation dynamique dans la saisie d'une chaîne de caractères de longeur variable ou d'entier avec scanf n'est pas efficace dans le sens ou il y a moins de sécurité ?
Non, je parle d'efficacite au sens algorithmique.
Le classique, c'est de doubler la taille du tampon a chaque fois.
Est-ce que c'est parce qu'un dépassement de buffer peut se produire avec l'allocation dynamique. Je ne vois pas très bien comment car getchar() ne lit qu'un seul caractère à chaque appel. Dans le premier post, je pensais à fgets, je pense que c'est pour fgets que ce n'est pas efficace. Je n'ai pas réfléchi à comment y arriver. Mais est-ce que ce n'est pas efficace parce le code est trop compliqué ou parce qu'il y a moins de sécurité?
Non, aucun rapport avec la securite.
ce dont je parle, c'est les tampons de taille variable.
schematiquement, et sans controle d'erreur (tous les malloc doivent etre verifies, en general).
(ce que tu proposes, c'est de faire capacity += constante dans grow_array).
Analyse classique algorithmique: si tu fais croitre la capacite de +N a chaque fois, tu vas gaspiller la place de N/2 elements en moyenne, et tu vas faire size/N reallocations.
Si tu fais croitre la capacite du tableau * 2 a chaque fois, tu vas gaspiller la place de 1/4 size elements en moyenne, et tu vas faire log2(size) reallocations.
On prefere le 2e schema dans l'enorme majorite des applications. Sur la plupart des OS, le plus souvent, il n'y a "pas de place" apres ton tableau, et realloc revient donc a allouer un nouveau tableau et tout copier... en general, la place memoire coute peu cher, mais la bande passante vers la memoire domine largement le temps d'execution: on s'en fout de gaspiller un peu, mais on veut faire le moins possible de copies inutiles.
Pour des chaines de caracteres, un idiome classique, c'est d'avoir un tampon global qui va croitre avec l'idiome ci-dessus, et une fois lue une chaine qui t'interesse, en general, tu ne stockes que les bouts qui t'interessent, donc soit tu parses au vol, soit tu fais du strdup() a partir du tampon... -> au final tu gaspilles un peu de place dans un seul tampon, tu as tes donnees qui sont copiees au plus juste, et ca marche tres bien...
In article <238c1a2d-0fc5-4443-90da-b26f46a8167a@f14g2000vbn.googlegroups.com>,
heron <cream1000s@yahoo.com> wrote:
L'allocation dynamique dans la saisie d'une chaîne de caractères de
longeur variable ou d'entier avec scanf n'est pas efficace dans le
sens ou il y a moins de sécurité ?
Non, je parle d'efficacite au sens algorithmique.
Le classique, c'est de doubler la taille du tampon a chaque fois.
Est-ce que c'est parce qu'un dépassement de buffer peut se produire
avec l'allocation dynamique. Je ne vois pas très bien comment car
getchar() ne lit qu'un seul caractère à chaque appel. Dans le premier
post, je pensais à fgets, je pense que c'est pour fgets que ce n'est
pas efficace. Je n'ai pas réfléchi à comment y arriver. Mais est-ce
que ce n'est pas efficace parce le code est trop compliqué ou parce
qu'il y a moins de sécurité?
Non, aucun rapport avec la securite.
ce dont je parle, c'est les tampons de taille variable.
schematiquement, et sans controle d'erreur (tous les malloc doivent etre
verifies, en general).
(ce que tu proposes, c'est de faire capacity += constante dans grow_array).
Analyse classique algorithmique:
si tu fais croitre la capacite de +N a chaque fois, tu vas gaspiller la place
de N/2 elements en moyenne, et tu vas faire size/N reallocations.
Si tu fais croitre la capacite du tableau * 2 a chaque fois, tu vas gaspiller
la place de 1/4 size elements en moyenne, et tu vas faire log2(size)
reallocations.
On prefere le 2e schema dans l'enorme majorite des applications. Sur la
plupart des OS, le plus souvent, il n'y a "pas de place" apres ton tableau,
et realloc revient donc a allouer un nouveau tableau et tout copier... en
general, la place memoire coute peu cher, mais la bande passante vers la
memoire domine largement le temps d'execution: on s'en fout de gaspiller un
peu, mais on veut faire le moins possible de copies inutiles.
Pour des chaines de caracteres, un idiome classique, c'est d'avoir un
tampon global qui va croitre avec l'idiome ci-dessus, et une fois lue une
chaine qui t'interesse, en general, tu ne stockes que les bouts qui
t'interessent, donc soit tu parses au vol, soit tu fais du strdup() a partir
du tampon... -> au final tu gaspilles un peu de place dans un seul tampon,
tu as tes donnees qui sont copiees au plus juste, et ca marche tres bien...
L'allocation dynamique dans la saisie d'une chaîne de caractères de longeur variable ou d'entier avec scanf n'est pas efficace dans le sens ou il y a moins de sécurité ?
Non, je parle d'efficacite au sens algorithmique.
Le classique, c'est de doubler la taille du tampon a chaque fois.
Est-ce que c'est parce qu'un dépassement de buffer peut se produire avec l'allocation dynamique. Je ne vois pas très bien comment car getchar() ne lit qu'un seul caractère à chaque appel. Dans le premier post, je pensais à fgets, je pense que c'est pour fgets que ce n'est pas efficace. Je n'ai pas réfléchi à comment y arriver. Mais est-ce que ce n'est pas efficace parce le code est trop compliqué ou parce qu'il y a moins de sécurité?
Non, aucun rapport avec la securite.
ce dont je parle, c'est les tampons de taille variable.
schematiquement, et sans controle d'erreur (tous les malloc doivent etre verifies, en general).
(ce que tu proposes, c'est de faire capacity += constante dans grow_array).
Analyse classique algorithmique: si tu fais croitre la capacite de +N a chaque fois, tu vas gaspiller la place de N/2 elements en moyenne, et tu vas faire size/N reallocations.
Si tu fais croitre la capacite du tableau * 2 a chaque fois, tu vas gaspiller la place de 1/4 size elements en moyenne, et tu vas faire log2(size) reallocations.
On prefere le 2e schema dans l'enorme majorite des applications. Sur la plupart des OS, le plus souvent, il n'y a "pas de place" apres ton tableau, et realloc revient donc a allouer un nouveau tableau et tout copier... en general, la place memoire coute peu cher, mais la bande passante vers la memoire domine largement le temps d'execution: on s'en fout de gaspiller un peu, mais on veut faire le moins possible de copies inutiles.
Pour des chaines de caracteres, un idiome classique, c'est d'avoir un tampon global qui va croitre avec l'idiome ci-dessus, et une fois lue une chaine qui t'interesse, en general, tu ne stockes que les bouts qui t'interessent, donc soit tu parses au vol, soit tu fais du strdup() a partir du tampon... -> au final tu gaspilles un peu de place dans un seul tampon, tu as tes donnees qui sont copiees au plus juste, et ca marche tres bien...