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 :

allocation mémoire d'une chaine de caractères


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut allocation mémoire d'une chaine de caractères
    Bonjour,

    Je suis étudiant et je débute en C. Dans un petit programme, je dois utiliser une allocation dynamique pour une chaine de caractère.
    Cette chaine sert à récupérer le nom d'une personne.

    Mon problème c'est que je ne vois pas dutout comment savoir quel espace je dois allouer pour la chaine, vu qu'on ne connait pas la longueur dun nom que l'utilisateur va entrer.
    Mon professeur a bien précisé qu'il faut que l'espace alloué soit exactement la taille de la chaine.

    Je ne vois pas comment faire à part, utiliser une variable intermédiaire pour stocker le nom et puis compter le nombre de caractère avec strlen(). Mais je crois pas vraiment que ce soit ça que le prof veut.

    Si quelqu'un peu me mettre sur une piste, ce serait sympa.

  2. #2
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Evidemment, si tu ne connais pas la taille de la chaine lue a l'avance, il serait miraculeux d'avoir la bonne taille la premiere fois.
    Ce que tu peux faire, c'est allouer une taille raisonnable (80 caracteres, disont). Tu lis caractere par caractere. Si jamais le nombre de caracteres depasse 80 - 1, alors tu realloues (realloc) le double de la taille (pour une raison de performance, il ne faut pas reallouer a chaque caractere). Si tu ne depasses pas les 80 - 1 caracteres, il est inutile d'agrandir l'allocation, evidemment.
    A la fin de la lecture, tu connais le nombre de caracteres lus. Il te suffit alors de reallouer la chaine a exactement ce nombre + 1 (ce qui va probablement reduire la dimension de l'allocation), et ton utilisation memoire est minimale.

  3. #3
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

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

    à moins que ton prof soit sadique, il ne peux t'empécher d'utiliser une variable intermédiaire.
    Ensuite comme tu l'as dis, il te suffit d'allouer dynamiquement à la bonne taille.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  4. #4
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    Tu lis caractere par caractere. Si jamais le nombre de caracteres depasse 80 - 1, alors tu realloues (realloc) le double de la taille (pour une raison de performance, il ne faut pas reallouer a chaque caractere). Si tu ne depasses pas les 80 - 1 caracteres, il est inutile d'agrandir l'allocation, evidemment.
    C'est aussi comme celà que je l'aurai vu, étant donné tes contraintes, je ne suis même pas sur que tu ai besoin d'autant de mémoire puisque comme tu le dis :

    Cette chaine sert à récupérer le nom d'une personne.
    Je pense que tu peux te contenter de 32 caractères, ça sera suffisant pour une bonne proportion des cas (même le nom premier ministre passe ...)

  5. #5
    Invité
    Invité(e)
    Par défaut
    il n'y a pas 36 solutions :
    - déclarer un char string[MAX_CHAR] (avec MAX_CHAR = 30,50,80, as you want)
    - scanf de la string
    - length = strlen(string)
    - if (length < MAX_CHAR) realloc de la string

    sincèrement utiliser une variable intermédiaire n'est JAMAIS problématique.
    Parfois plus long mais jamais problématique !
    (mieux vaut plus d'instructions plus lisibles qu'un code trop compact)

  6. #6
    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 gagaches
    il n'y a pas 36 solutions :
    - déclarer un char string[MAX_CHAR] (avec MAX_CHAR = 30,50,80, as you want)
    - scanf de la string
    - length = strlen(string)
    - if (length < MAX_CHAR) realloc de la string
    realloc() sur une chaine statique, ca va saigner...

  7. #7
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Par défaut
    Une méthode (débile) possible est ça :
    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
    char *SaisieNom(void)
    {
      char *p = NULL;
      int c;
      int len = 1;
      if (p == NULL)
      {
        fprintf(stderr, "pb alloc mémoire\n");
        return NULL;
      }
      *p = 0;
      while ( (c = fgetc(stdin)) != '\n' && c != EOF)
      {
        char *tmp;
        len++;
        tmp = realloc(p, len);
        if (tmp == NULL)
        {
            fprintf(stderr, "pb alloc memoire\n");
            // ClearClavier permet de vider le buffer de stdin
            // Cette fonction est détaillée, peut-être pas sous ce nom
            // Dans la FAQ
            ClearClavier();
            return p;
        }
        p = tmp;
        p[len-1] = (char) c;
        p[len] = 0;
      }
      return p;
    }
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  8. #8
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *p = NULL;
      int c;
      int len = 1;
      if (p == NULL)
      {
        fprintf(stderr, "pb alloc mémoire\n");
        return NULL;
      }
    Ca marchera jamais.
    Et l'allocation?

  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 seriousme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *p = NULL;
      int c;
      int len = 1;
      if (p == NULL)
      {
        fprintf(stderr, "pb alloc mémoire\n");
        return NULL;
      }
    Ca marchera jamais.
    Et l'allocation?
    Y'a pas besoin, mais effectivement, il faut retirer ce test...

  10. #10
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Ah oui "realloc" sert de "malloc".

  11. #11
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Par défaut
    Citation Envoyé par seriousme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *p = NULL;
      int c;
      int len = 1;
      if (p == NULL)
      {
        fprintf(stderr, "pb alloc mémoire\n");
        return NULL;
      }
    Ca marchera jamais.
    Et l'allocation?
    Exact, j'ai modifé en écrivant et je me suis trrrrrrrrès mal relu.
    Comme l'a dit Emmanuel, il faut supprimer le if (p == NULL) ...
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  12. #12
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par seriousme
    Ah oui "realloc" sert de "malloc".
    A la condition que son premièr argument soit NULL :
    man realloc :
    Si ptr est NULL, l'appel de realloc() est équivalent à malloc(size).

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut
    Merci pour votre aide

    Vu vos réponses je pense que je vais passer par la variable intérmédiaire. Le code de Trap D risque de pas plaire à mon prof vu ça longueur alors que ce selon lui ce n'est qu'une petite modification.

    Une petite question qui sur un point qui m'a étonné:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while ( (c = fgetc(stdin)) != '\n' && c != EOF)
      {
        char *tmp;
        ect...
        }
    Ce n'est quand C99 que l'on n'est pas obligé de déclarer une variable en début de fonction ou de fichier ?
    Et puis ce que ma surtout marqué, c'est le fait que la déclaration soit dans une boucle. Ca veut dire qu'on redéclare la même variable à chaque passage, ça pose pas problème ?

  14. #14
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Ca réduit les performances.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {char *tmp;
    while ( (c = fgetc(stdin)) != '\n' && c != EOF)
      {
       ...
       } 
    }
    Ce code permet de ne pas redéclarer "tmp" à chaque fois et que cette variable ne soit valable que pour le "while".

  15. #15
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par oFlex
    Ce n'est quand C99 que l'on n'est pas obligé de déclarer une variable en début de fonction ou de fichier ?
    C'est une variable a portee de bloc. Cela existe depuis longtemps.

    Et puis ce que ma surtout marqué, c'est le fait que la déclaration soit dans une boucle. Ca veut dire qu'on redéclare la même variable à chaque passage, ça pose pas problème ?
    Cela depend du compilateur et des optimisations qu'il apporte.

  16. #16
    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 oFlex
    Une petite question qui sur un point qui m'a étonné:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while ( (c = fgetc(stdin)) != '\n' && c != EOF)
      {
        char *tmp;
        ect...
        }
    Ce n'est quand C99 que l'on n'est pas obligé de déclarer une variable en début de fonction ou de fichier ?
    Depuis les origines du C, il est possible de définir une variable en début de bloc.
    Et puis ce que ma surtout marqué, c'est le fait que la déclaration soit dans une boucle. Ca veut dire qu'on redéclare la même variable à chaque passage, ça pose pas problème ?
    Non. En fait la réservation de la mémoire automatique est faite soit une fois en entrant dans la fonction, soit une fois en entrant dans le bloc si le compilateur cherche à optimiser en mémoire...

  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 seriousme
    Ca réduit les performances.
    T'as fait des mesures ?

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut
    oki merci à vous

  19. #19
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    T'as fait des mesures ?
    Je veux dire si le compilateur n'optimise pas, ce qui ne doit être le cas pour aucun.

  20. #20
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Version compacte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char s[100];
    char *p_s=malloc(strlen(fgets(s,100,stdin)));
    strcpy(p_s,s);
    mais illisible.

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

Discussions similaires

  1. convertir une chaine de caract en code Perl
    Par radahm dans le forum Langage
    Réponses: 3
    Dernier message: 29/04/2009, 21h05
  2. Allocation d' une chaine juste à la bonne taille
    Par emprex dans le forum Débuter
    Réponses: 4
    Dernier message: 25/04/2008, 10h06
  3. [VBA excel] Extraire une chaine de caract. d'une cellule.
    Par Mourne dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 17/01/2007, 08h35
  4. Réponses: 10
    Dernier message: 22/05/2004, 13h51
  5. [TP]lire une ligne de l'ecran et la stocker dans une chaine
    Par Bleuarff dans le forum Turbo Pascal
    Réponses: 26
    Dernier message: 02/07/2002, 10h08

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