IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

fonction pour lire au clavier


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut fonction pour lire au clavier
    Bonjour,

    J'aurais besoin d'aide pour me guider dans cette tâche :
    Comment faire une fonction qui lit au clavier ?
    Cette fonction retournant une chaîne de caractère lue au clavier.
    La longueur de la chaine peut être quelconque.
    Et ça doit s’arrêter lorsque l’utilisateur frappe la touche <entrée>.


    Bon déjà étant donné que la chaîne de caractère peut être quelconque, cela signifie allocation dynamique je pense non... ?

    Mais après je m'y perds, je ne sais pas trop quoi utiliser, fgets, fread... ou d'autres ?

    J'ai trouvé et lu plusieurs exemples là dessus sur internet (dont notamment des pages sur http://emmanuel-delahaye.developpez.com/inputs.htm) mais ça coince toujours...

    Comment faire pour que l'on puisse taper autant de caractères que l'on veut en une seule fois avant d'appuyer sur la touche <entrée> ? C'est la le problème... si j'utilise un fgets, la taille de ce qu'on peut lire est limitée. Et si on en enchaine plusieurs, ca voudra forcément dire qu'on appuie a chaque fois sur entrée pour finir le fgets non ? donc c'est pas ce qui est recherché..

    Merci
    ++

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    En C, on a aucun moyen de connaître par avance la taille de la saisie utilisateur, il te faut donc fixer une limite forte et de là, tu peux tranquillement utiliser fgets vu que ton but est de tout récupérer d'un seul coup après appui sur la touche Entrée !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut
    Oui mais le but de cet exercice n'est pas de mettre une taille énorme pour que quoi que l'on tape, ca rentrera...
    C'est de gérer la mémoire... des trucs comme ca

  4. #4
    Membre Expert
    Avatar de muad'dib
    Homme Profil pro
    Développeur Java
    Inscrit en
    Janvier 2003
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2003
    Messages : 1 013
    Par défaut
    La solution la plus simple, c'est de ne pas faire une allocation dynamique mais d'initialiser un tableau de caractères suffisamment grand pour contenir la majorité des entrées au clavier (en général 512 est suffisant, mais tu peux l'agrandir autant que le permet le tas (je ne connais pas la taille) ).

    Sinon si ton utilisateur a l'intention d'écrire un roman je sais pas trop je dois dire... peut-être une fonction du genre kbhit() qui compterait le nombre de touches pressées et sur la détection de la touche entrée faire une allocation dynamique ? Ça fait un peu bricolage...

    De toute façon on a toujours plus ou moins une idée de ce que va entrer l'utilisateur.

  5. #5
    Membre confirmé
    Homme Profil pro
    Consultant
    Inscrit en
    Avril 2006
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2006
    Messages : 92
    Par défaut
    Cette solution est peut être bourrin, mais faire une lecture caractère par caractère, de stocker cela dans un tableau alloué dynamiquement, quand il n'y a plus de place dans le tableau du agrandis celui-ci.

    si il tape vraiment quelque chose de très long, passer par un fichier à la place du tableau (cas extrême ou il y aurais pas assez de mémoire ?)

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Quelle que soit la solution employée (caractère-par-caractère ou non), il faut utiliser de l'allocation dynamique, et réallouer ta zone mémoire quand "ça dépasse".
    • Pour la réallocation, une méthode conseillée est de choisir une nouvelle taille multiple de l'ancienne, avec un multiple inférieur au nombre d'or (pour des raisons dont j'ai oublié les détails). Multiplier par 1.5 satisfait ces critères.
    • Si tu ne veux pas faire caractère par caractère, tu peux utiliser la fonction fgets() : C'est en recherchant le \n après chaque saisie que tu sauras si la ligne est terminée ou non...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut
    Oui je suis parti sur caractere par caractere avec getchar, mais avec l'histoie du nombre d'or, j'ai pas trop saisi... enfin je posterais ma fonction pour avoir vos avis.

    Merci
    ++

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par italiasky
    J'aurais besoin d'aide pour me guider dans cette tâche :
    Comment faire une fonction qui lit au clavier ?
    Cette fonction retournant une chaîne de caractère lue au clavier.
    La longueur de la chaine peut être quelconque.
    Et ça doit s’arrêter lorsque l’utilisateur frappe la touche <entrée>.
    fgetc(), malloc(), realloc()... Attention, il peut y avoir une limitation système au nombre de caractères lus d'un coup (DOS, 255, Windows 2048 environ etc.).
    J'ai trouvé et lu plusieurs exemples là dessus sur internet (dont notamment des pages sur http://emmanuel-delahaye.developpez.com/inputs.htm) mais ça coince toujours...
    Qu'est-ce qui coince ? Si tu ne montres pas ton code, on ne pas deviner...
    Comment faire pour que l'on puisse taper autant de caractères que l'on veut en une seule fois avant d'appuyer sur la touche <entrée> ? C'est la le problème... si j'utilise un fgets, la taille de ce qu'on peut lire est limitée. Et si on en enchaine plusieurs, ca voudra forcément dire qu'on appuie a chaque fois sur entrée pour finir le fgets non ? donc c'est pas ce qui est recherché.
    Justement, non. Tu devrais lire ceci :

    http://emmanuel-delahaye.developpez.com/notes.htm#fgetc

  9. #9
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par muad'dib
    Sinon si ton utilisateur a l'intention d'écrire un roman je sais pas trop je dois dire... peut-être une fonction du genre kbhit() qui compterait le nombre de touches pressées et sur la détection de la touche entrée faire une allocation dynamique ? Ça fait un peu bricolage...
    Non. Si tu ne sais pas, c'est pas grave, mis évite de raconter n'importe quoi. Des dizaines de gens lisent ces messages et ils n'ont pas envie de lire des bêtises...

    Et le but de l'opération est justement qu'on ne sait pas ce qui va être lu (ce n'est pas forcément un 'opérateur', ça peut être un fichier texte de 10 Mo avec un \n voire même aucun).

  10. #10
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut
    Voila ce que ca donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    char* lecture_clavier(unsigned short taille_buffer)
    { 
    	char c;
    	unsigned long i=0;
    	unsigned long j=1;
     
     	if(taille_buffer < 2)
    		taille_buffer = 2;
     
    	char buffer[taille_buffer];
    	char* texte = (char*) malloc(sizeof(buffer));
     
    	assert(texte != NULL);
     
    	while((c=getchar()) != '\n')
    	{
          		buffer[i] = c;
    		buffer[++i] = '\0';
     
    		if(i == (taille_buffer-1))
    		{
    			texte = (char*) realloc(texte, sizeof(char)*taille_buffer*++j);
    			assert(texte != NULL);
    			texte = strcat(texte, buffer);
    			i = 0;
    		}      		
      	}
     
    	if(i != 0)
    		texte = strcat(texte, buffer);
     
    	return texte;
    }
    Vous en pensez quoi ?
    Des améliorations à apporter ?

    Merci
    ++

  11. #11
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par italiasky
    Voila ce que ca donne :
    • Ne pas définir de variable de type char sauf absolue nécessité. int suffit dans la majorité des cas. Ca génère moins de code parasite... De plus, ici, on a affaire à getchar() qui retourne un int (comme EOF, par exemple).
    • EOF n'est pas testé. Si on lit a partir d'un fichier,
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      C:\> monappli <data.txt
      c'est la boucle infinie...
    • Pas besoin de cast avec malloc().
    • Mauvais usage de assert() : http://emmanuel-delahaye.developpez....tes.htm#assert
    • utilisation d'un VLA (buffer). Pas portable et surtout absurde. malloc() fait le travail et le fait bien.
    • algorithme complexe et difficile à lire
    • usage dangereux des opérateurs unaires (++)
    • usage naïf de realloc() (en cas d'échec, c'est la fuite mémoire irréparable) : http://emmanuel-delahaye.developpez....es.htm#realloc
    • usage abusif de realloc() (à chaque caractère).
    • inutile d'affecter le résultat de strcat(). (modifier un pointeur sur une zone allouée, ça fout la trouille !).
    • le paramètre de taille ne sert à rien.

    La technique a été expliquée. A toi de la mettre en oeuvre.

  12. #12
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    [LIST][*]Ne pas définir de variable de type char sauf absolue nécessité. int suffit dans la majorité des cas. Ca génère moins de code parasite... De plus, ici, on a affaire à getchar() qui retourne un int (comme EOF, par exemple).
    Oui c'est vrai, mais je pensais que le char était plus logique étant donné qu'on lit un caractère donc ca me paraissait logique de stocké le caractere dans un char.


    Citation Envoyé par Emmanuel Delahaye
    [*]EOF n'est pas testé. Si on lit a partir d'un fichier,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    C:\> monappli <data.txt
    c'est la boucle infinie...
    Le but de la fonction n'est pas de lire à partir d'un fichier, mais bien de lire une chaine de caractères que l'on tape au clavier.
    Mais d'ailleurs j'ai essayé avec un fichier texte, ca fonctionne quand même, comment ca se fait du coup ? Vu que je ne teste pas EOF ?


    Citation Envoyé par Emmanuel Delahaye
    [*]Pas besoin de cast avec malloc().
    Bien étant donné que malloc renvoie un void*, et qu'on va stocké dans un char*, je trouve normale de faire un cast (char*) non ? Enfin il me semble que c'est ce qu'on nous a appris...


    Citation Envoyé par Emmanuel Delahaye
    De ce coté aussi, on nous a fait employé une macro fonction assert pour vérifier des choses qui sont indispensables à certains moments, sinon le programme s'arrete.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define assert(c) { if(!(c)) exit(1); }

    Citation Envoyé par Emmanuel Delahaye
    [*]utilisation d'un VLA (buffer). Pas portable et surtout absurde. malloc() fait le travail et le fait bien.
    Là je ne comprends pas trop... le fait d'utiliser le buffer, c'est pour justement ne pas faire un appel à malloc à chaque fois, a chaque caractere par ex.


    Citation Envoyé par Emmanuel Delahaye
    [*]usage dangereux des opérateurs unaires (++)
    Pourquoi ? comment ca ?


    Citation Envoyé par Emmanuel Delahaye
    [*]usage naïf de realloc() (en cas d'échec, c'est la fuite mémoire irréparable) : http://emmanuel-delahaye.developpez....es.htm#realloc
    Comment ca ? Vous voulez dire qu'au cas ou realloc n'a pa pu aboutir, le reste qu'on avait avant est perdu en fait c'est ca?


    Citation Envoyé par Emmanuel Delahaye
    [*]usage abusif de realloc() (à chaque caractère).
    Euh ca je ne suis pas trop d'accord, ca fait un realloc juste si le buffer est plein. donc si on met une taille de buffer de 255, tous les 255 caracteres ca fait un realloc et non a chaque fois...


    Citation Envoyé par Emmanuel Delahaye
    [*]le paramètre de taille ne sert à rien.
    Le paramètre que je passe c'est justement pour indiquer la taille de buffer, si on sait que l'utilisateur va tapé seulement quelques mots, on peut prendre une taille de buffer de 50 environ mais si on sait de suite que c'est un long texte qui va etre tapée, on peut mettre un buffer plus grand, afin qu'il n'y ait pas trop de realloc...


    Merci de vos explications
    Bonne soirée


    PS : c'est mieux d'utilsier fgetc a la place de getchar ?

  13. #13
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par italiasky
    Le but de la fonction n'est pas de lire à partir d'un fichier, mais bien de lire une chaine de caractères que l'on tape au clavier.
    Mais d'ailleurs j'ai essayé avec un fichier texte, ca fonctionne quand même, comment ca se fait du coup ? Vu que je ne teste pas EOF ?
    Parce que la ligne est terminée par un \n. Ce n'est pas toujours le cas quand c'est la dernière.
    Bien étant donné que malloc renvoie un void*, et qu'on va stocké dans un char*, je trouve normale de faire un cast (char*) non ? Enfin il me semble que c'est ce qu'on nous a appris...
    On t'a appris de travers. en C, void * est compatible avec tous les types pointeur sur objet. Le cast est donc inutile.

    http://emmanuel-delahaye.developpez....tes.htm#malloc
    De ce coté aussi, on nous a fait employé une macro fonction assert pour vérifier des choses qui sont indispensables à certains moments, sinon le programme s'arrete.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define assert(c) { if(!(c)) exit(1); }
    Très mauvaise pratique. Redéfinir une macro standard invoque un comportement indéfini.
    Là je ne comprends pas trop... le fait d'utiliser le buffer, c'est pour justement ne pas faire un appel à malloc à chaque fois, a chaque caractere par ex.
    Un buffer avec malloc(), OK, mais pourquoi un VLA de taille fixe ? Il suffit de remplir le buffer extensible (malloc() / realloc()) au fur et à mesure. Il n'y a pas besoin de ce buffer intermédaire et de faire recopies (strcat(). Il suffit de gérer correctement un pointeur ou un indice d'écriture.
    Comment ca ? Vous voulez dire qu'au cas ou realloc n'a pa pu aboutir, le reste qu'on avait avant est perdu en fait c'est ca?
    Oui, comme expliqué dans mon article.
    Euh ca je ne suis pas trop d'accord, ca fait un realloc juste si le buffer est plein. donc si on met une taille de buffer de 255, tous les 255 caracteres ca fait un realloc et non a chaque fois...
    OK, j'avais mal lu. Le bon usage est d'agrandir le buffer d'un facteur compris entre 1.5 et 2 à chaque fois.
    Le paramètre que je passe c'est justement pour indiquer la taille de buffer, si on sait que l'utilisateur va tapé seulement quelques mots, on peut prendre une taille de buffer de 50 environ mais si on sait de suite que c'est un long texte qui va etre tapée, on peut mettre un buffer plus grand, afin qu'il n'y ait pas trop de realloc...
    Une taille raisonnable suffit pour démarrer (16, 32...) ensuite, le système est auto démerdant... Bon, on peut fixer la taille de démarrage, OK. C'est un détail...
    c'est mieux d'utilsier fgetc a la place de getchar ?
    C'est pareil (pour stdin).

  14. #14
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut
    Salut,

    Je pense que italiasky mélange "saisir avec la console", avec "retaille de la mémoire".

    Ce qui plonge nos exégètes dans des bifurcations insoupçonnées.

  15. #15
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par dj.motte
    Je pense que italiasky mélange "saisir avec la console", avec "retaille de la mémoire".
    Il ne confond pas, il mélange les deux techniques, ce qui est assez courant...

    http://emmanuel-delahaye.developpez.com/clib.htm
    Module IO
    fonctions fget_line() et get_line()
    avec l'aide du module FSTR

  16. #16
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut
    Bonjour,

    J'ai revu ma fonction,
    ca donne cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #define verif_ptr(ope) { if(!(ope)) { printf("\n ----- Erreur d'allocation de la mémoire ----- \n"); exit(1); } } 
     
    char* lecture_clavier(unsigned long taille_buffer)
    { 
    	unsigned long i=0, j=1;
    	char c;
    	char *texte = malloc(sizeof(*texte)*taille_buffer);
    	verif_ptr(texte != NULL);
     
     	if(taille_buffer < 1)
    		taille_buffer = 5;
     
    	while((c=getchar()) != '\n')
    	{
          		*(texte+i) = c;
    		i++;
     
    		if(i%taille_buffer == 0)
    		{
    			texte = realloc(texte, sizeof(*texte)*taille_buffer*++j);
    			verif_ptr(texte != NULL);
    		}      		
      	}
     
    	*(texte+i) = '\0';
    	if(i == 0 || (i+1)%taille_buffer != 0)
    	{
    		texte = realloc(texte, sizeof(*texte)*(i+1));
    		verif_ptr(texte != NULL);
    	}
     
    	return texte;  
    }
    Je n'ai pas mis "int" mais j'ai laissé char parce que sinon après je ne peux pas afficher ma chaine de caractere avec un %s dans un printf...
    C'est vraiment "grave" de stocker dans un char le retour de getchar même si la prototype de cette fonction montre bien qu'elle renvoit un int ?

    Et pour le realloc, je ne passe par pas un pointeur intermédiaire parce que apparement realloc libère quand même l'espace pointé par le pointeur qu'on passe en parametre, donc même apres si on veut récupérer le pointeur originale, c'est trop tard non puisque l'espace mémoire pointée aura été libérée ?

    Merci
    ++

  17. #17
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par italiasky
    J'ai revu ma fonction,
    ca donne cela :
    C'est mieux, mais c'est encore un peu compliqué et ça ne traite pas les fichiers (une redirection est toujours possible, surtout en tests...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
     
    char *lecture_clavier (void)
    {
       char *texte = NULL;
       size_t taille_buffer = 1;
     
       texte = malloc (sizeof *texte * taille_buffer);
       if (texte != NULL)
       {
          size_t i = 0;
          int c;
     
          /* verification du tableau */
          texte[taille_buffer-1] = 0;
     
          while ((c = getchar ()) != '\n' && c != EOF && texte != NULL)
          {
          /* verification du tableau */
             assert (texte[taille_buffer-1] == 0);
             texte[i] = c;
             i++;
             if (i == taille_buffer)
             {
                char *tmp = realloc (texte, sizeof *texte * (taille_buffer * 2));
     
                if (tmp != NULL)
                {
                   texte = tmp;
                   taille_buffer *= 2;
                   /* verification du tableau */
                   texte[taille_buffer-1] = 0;
                }
                else
                {
                   free (texte), texte = NULL;
                }
             }
          }
     
          if (c != EOF)
          {
             texte[i] = 0;
             /* verification du tableau */
             assert (texte[taille_buffer-1] == 0);
          }
          else
          {
             free (texte), texte = NULL;
          }
     
       }
       return texte;
    }
     
    int main (void)
    {
       if (freopen ("main.c", "r", stdin) != NULL)
       {
          char *line;
          while ((line = lecture_clavier ()) != NULL)
          {
             printf ("line = '%s'\n", line);
             free (line);
          }
       }
       return 0;
    }
    Je n'ai pas mis "int" mais j'ai laissé char parce que sinon après je ne peux pas afficher ma chaine de caractere avec un %s dans un printf...
    Bah, aucun rapport. Le type retourné par getchar() est int, alors c doit être de type int (pour pouvoir être comparé à EOF). La chaine, par contre est de type tableau de char, car un caractère qui n'est pas EOF entre forcément dans un char.
    est donc correct.
    C'est vraiment "grave" de stocker dans un char le retour de getchar même si la prototype de cette fonction montre bien qu'elle renvoit un int ?
    Oui, comme il vient d'être expliqué.
    Et pour le realloc, je ne passe par pas un pointeur intermédiaire parce que apparement realloc libère quand même l'espace pointé par le pointeur qu'on passe en parametre, donc même apres si on veut récupérer le pointeur originale, c'est trop tard non puisque l'espace mémoire pointée aura été libérée ?
    Non. En cas d'échec, realloc() ne libère rien. Il faut bien faire ce qui a été recommandé.

  18. #18
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 501
    Par défaut
    Bonjour,

    J'ai encore changé ma fonction, vous en pensez quoi maintenant ?

    Merci
    Bonne journée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    /* Definition des fonctions */
    char* lecture_clavier(unsigned long taille_buffer)
    { 
    	int c;
    	unsigned long i = 0, j = 1;	
    	char *texte = malloc(sizeof(*texte)*taille_buffer);
    	verif_ptr(texte != NULL);
     
     	if(taille_buffer < 1)
    		taille_buffer = 5;
     
    	while((c=getchar()) != '\n' && c != EOF)
    	{
          		texte[i] = c;
    		i++;
     
    		if(i%taille_buffer == 0)
    		{
    			char *tmp = realloc(texte, sizeof(*texte)*taille_buffer*++j);
     
    			if(tmp != NULL)
    			{
    				texte = tmp;
    			}
    			else
    			{
    				free(texte);
    				return NULL;
    			}
    		}
      	}
     
    	if (c == EOF)
          	{
             	free (texte);
    		texte = NULL;
          	}
    	else
    	{	
    		texte[i] = '\0';
    		if(i == 0 || (i+1)%taille_buffer != 0)
    		{
    			char *tmp = realloc(texte, sizeof(*texte)*(i+1));
    			if(tmp != NULL)
    				texte = tmp;
    		}
    	}
     
    	return texte;  
    }

  19. #19
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    86
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 86
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned long taille_buffer

    on utilise size_t pour les tailles en C .

  20. #20
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par italiasky
    Tu l'as testée ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    line = '#include <stdio.h>'
    line = '#♦='
    line = '#♦='
    line = '#♥='
    line = ''
    line = '#♥='
    line = ''
    line = '/♥='
    line = 'c♥='
    line = '{'
    line = '        ☻='
    line = '        '
    line = '        ☻='
    line = '        ☻='
    line = ''
    line = ' ☻='
    line = '        ☻='
    line = ''
    line = '        ☻='
    line = '        {'
    line = ' ☺='
    line = '        ☺='
    line = ''
    line = '        '
    line = '                {'
    line = '        ☺='
    line = ''
    line = '        ☺='
    line = '                        {'
    line = '        ☺='
    line = '                        }'
    line = '        ☺='
    line = '                        {'
    line = '        '
    line = '        ☺='
    line = '                        }'
    line = '                }'
    line = '        }'
    line = ''
    line = '        ☺='
    line = ' '
    line = ' '
    line = '        ☺='
    line = ' ☺='
    line = '        '
    line = '        {'
    line = '        '
    line = '        ☺='
    line = '                {'
    line = '        ☺='
    line = '        ☺='
    line = '        ☺='
    line = '                }'
    line = '        }'
    line = ''
    line = '        ☺='
    line = '}'
    line = ''
    line = ''
    line = ' '
    line = '{'
    line = ' ☺='
    line = '   {'
    line = ' ☺='
    line = ' ☺='
    line = ' ☺='
    line = ' '
    line = ' ☺='
    line = ' ☺='
    line = '   }'
    line = ' '
    line = '}'
     
    Press ENTER to continue.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char* lecture_clavier(unsigned long taille_buffer)
    { 
    	char *texte = malloc(sizeof(*texte)*taille_buffer);
    <...> 
     	if(taille_buffer < 1)
    		taille_buffer = 5;
    Tu ments à ton compilateur. Tu modifies la taille alors que l'allocation a été faite avec la taille originelle... Ca te retomberas dessus un jour où l'autre (perso, j'appelle la fonction avec une taille de 0).

    J'ai déjà donné des solutions qui fonctionnent...

    Après légère réparation du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
     
    #define verif_ptr(ope) { if(!(ope)) { printf("\n ----- Erreur d'allocation de la mémoire ----- \n"); exit(1); } }
     
    /* Definition des fonctions */
    char *lecture_clavier (unsigned long taille_buffer)
    {
       char *texte = NULL;
     
       if (taille_buffer < 1)
          taille_buffer = 5;
       {
          int c;
          unsigned long i = 0, j = 1;
     
          texte = malloc (sizeof (*texte) * taille_buffer);
          verif_ptr (texte != NULL);
     
          /* verification du tableau */
          texte[taille_buffer - 1] = 0;
     
          while ((c = getchar ()) != '\n' && c != EOF)
          {
             /* verification du tableau */
             assert (texte[taille_buffer - 1] == 0);
             texte[i] = c;
             i++;
     
             if (i % taille_buffer == 0)
             {
                char *tmp =
                   realloc (texte, sizeof (*texte) * taille_buffer * ++j);
     
                if (tmp != NULL)
                {
                   texte = tmp;
                   /* verification du tableau */
                   texte[taille_buffer - 1] = 0;
                }
                else
                {
                   free (texte);
                   return NULL;
                }
             }
          }
     
          if (c == EOF)
          {
             free (texte);
             texte = NULL;
          }
          else
          {
             texte[i] = '\0';
             if (i == 0 || (i + 1) % taille_buffer != 0)
             {
                char *tmp = realloc (texte, sizeof (*texte) * (i + 1));
                if (tmp != NULL)
                   texte = tmp;
             }
          }
       }
       return texte;
    }
     
    int main (void)
    {
       if (freopen ("main.c", "r", stdin) != NULL)
       {
          char *line;
          while ((line = lecture_clavier (0)) != NULL)
          {
             printf ("line = '%s'\n", line);
             free (line);
          }
       }
       return 0;
    }
    j'obtiens encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    line = '#inc'
    line = '#inc'
    line = '#inc'
    line = '#inc'
    line = ''
    line = '#def'
    line = ''
    line = '/* D'
    line = 'char'
    line = '{'
    line = '   c'
    line = ''
    line = '        if'
    line = '                ta'
    line = '{'
    line = '        int'
    line = '        uns'
    line = ''
    line = '        tex'
    line = '        ver'
    line = ''
    line = ''
    line = '    '
    line = '    '
    line = ''
    line = '        whi'
    line = '        {'
    line = '    '
    line = '    '
    line = '    '
    line = '                i+'
    line = ''
    line = '                if'
    line = '                {'
    line = '                        c'
    line = ''
    line = '                        i'
    line = '                        {'
    line = '                                '
    line = '    '
    line = '    '
    line = '                        }'
    line = '                        e'
    line = '                        {'
    line = '                                '
    line = '                                '
    line = '                        }'
    line = '                }'
    line = '        }'
    line = ''
    line = '        if '
    line = '    '
    line = '    '
    line = '                te'
    line = '    '
    line = '        els'
    line = '        {'
    line = '                te'
    line = '                if'
    line = '                {'
    line = '                        c'
    line = '                        i'
    line = '                                '
    line = '                }'
    line = '        }'
    line = '}'
    line = '        ret'
    line = '}'
    line = ''
    line = ''
    line = ' int'
    line = '{'
    line = '   i'
    line = '   {'
    line = '    '
    line = '    '
    line = '    '
    line = '    '
    line = '    '
    line = '    '
    line = '   }'
    line = '   r'
    line = '}'
     
    Press ENTER to continue.
    C'est stable, mais en manque des morceaux...

    Il a suffit que j'installe correctement de code de debug pour que ça fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
     
    #define verif_ptr(ope) { if(!(ope)) { printf("\n ----- Erreur d'allocation de la mémoire ----- \n"); exit(1); } }
     
    /* Definition des fonctions */
    char *lecture_clavier (unsigned long taille_buffer)
    {
       char *texte = NULL;
     
       if (taille_buffer < 1)
          taille_buffer = 5;
       {
          int c;
          unsigned long i = 0, j = 1;
     
          texte = malloc (sizeof (*texte) * taille_buffer + j);
          verif_ptr (texte != NULL);
     
          /* verification du tableau */
          texte[(taille_buffer * j) - 1] = 0;
     
          while ((c = getchar ()) != '\n' && c != EOF)
          {
             /* verification du tableau */
             assert (texte[(taille_buffer * j) - 1] == 0);
             texte[i] = c;
             i++;
     
             if (i % taille_buffer == 0)
             {
                j++;
                char *tmp = realloc (texte, sizeof (*texte) * taille_buffer * j);
     
                if (tmp != NULL)
                {
                   texte = tmp;
                   /* verification du tableau */
                   texte[(taille_buffer * j) - 1] = 0;
                }
                else
                {
                   free (texte);
                   return NULL;
                }
             }
          }
     
          if (c == EOF)
          {
             free (texte);
             texte = NULL;
          }
          else
          {
             texte[i] = '\0';
             if (i == 0 || (i + 1) % taille_buffer != 0)
             {
                char *tmp = realloc (texte, sizeof (*texte) * (i + 1));
                if (tmp != NULL)
                   texte = tmp;
             }
          }
       }
       return texte;
    }
     
    int main (void)
    {
       if (freopen ("main.c", "r", stdin) != NULL)
       {
          char *line;
          while ((line = lecture_clavier (0)) != NULL)
          {
             printf ("line = '%s'\n", line);
             free (line);
          }
       }
       return 0;
    }

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Fonction pour lire des nombres dans un fichier
    Par passant_ dans le forum Débuter
    Réponses: 11
    Dernier message: 28/10/2008, 18h47
  2. Recherche fonction pour lire/ecrire fichier ISO
    Par T-B dans le forum Langage
    Réponses: 2
    Dernier message: 21/01/2008, 14h47
  3. sizeof dans une fonction pour lire une chaine
    Par Haze. dans le forum Débuter
    Réponses: 11
    Dernier message: 06/11/2007, 12h07
  4. fonction pour lire les fichier audio
    Par tarek007 dans le forum Multimédia
    Réponses: 1
    Dernier message: 11/05/2005, 16h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo