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.

  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 : 39
    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
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 117
    Points : 630
    Points
    630
    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...

  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;
    }

  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
    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?

  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...

  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
    Points : 3 958
    Points
    3 958
    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
    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) ...

  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
    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 : 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
    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".

  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...

  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 ?

  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 : 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
    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.

  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
    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.

+ 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