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 à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Points : 12
    Points
    12
    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 expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    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 : 45
    Localisation : Etats-Unis

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    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 éminent
    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 : 38
    Localisation : France, Vienne (Poitou Charente)

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    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
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 114
    Points : 618
    Points
    618
    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 sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    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...
    Pas de Wi-Fi à la maison : CPL

  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
    Points : 6 498
    Points
    6 498
    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 : 37
    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
    Points : 3 958
    Points
    3 958
    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?
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    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...
    Pas de Wi-Fi à la maison : CPL

  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 : 37
    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
    Points : 3 958
    Points
    3 958
    Par défaut
    Ah oui "realloc" sert de "malloc".
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  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
    Points : 6 498
    Points
    6 498
    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 : 40
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    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 à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Points : 12
    Points
    12
    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 : 37
    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
    Points : 3 958
    Points
    3 958
    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".
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  15. #15
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    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 sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    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...
    Pas de Wi-Fi à la maison : CPL

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par seriousme
    Ca réduit les performances.
    T'as fait des mesures ?
    Pas de Wi-Fi à la maison : CPL

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Points : 12
    Points
    12
    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 : 37
    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
    Points : 3 958
    Points
    3 958
    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.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  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 : 37
    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
    Points : 3 958
    Points
    3 958
    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.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

+ 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