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 :

Pointeur chaine de caractères


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    cnam
    Inscrit en
    Avril 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Liban

    Informations professionnelles :
    Activité : cnam
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 14
    Par défaut Pointeur chaine de caractères
    bonsoir les amis

    j'utilise code blocks 10.05

    un petite question
    j'ai défini dans ce programme (*resultat) chaine de caractères
    le programme marche très bien mais mon professeur m'a dit qu'il fallait définir une allocation dynamique pour (resultat)
    je ne trouve pas pourquoi c'est nécessaire
    le programme permet de convertir les base il est:

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    void main()
    {
        int n,b,i,r;
        char *resultat;
        do{
        printf("donner le nombre entier n<32000");
         scanf("%d",&n);
          }while(n>32000);
     
          do{
          printf("donner la base b");
          scanf("%d",&b);
          }while((b<2)||(b>9));
          for(i=0;n!=0;i++)
          {
              r=n%b;
              resultat[i]=r+'0';
              n=n/b;
          }
    resultat[i]='\0';
    printf("%s",strrev(resultat));
    }
    le type d'allocation qu'il dit que je dois utiliser est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat=(char*)malloc(strlen(resultat)*sizeof(char));
    merci d'avance pour votre réponse

  2. #2
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Ce sujet revient souvent pour la conversion de base.

    Il faut d'abord calculer le nombre de caractères que le résultat fera, puis tu ajoutes 1, et tu malloc tout cela.
    Ensuite, tu copies tes caractères, puis tu finis la chaîne avec '\0';

    Les problèmes dans ce que tu as compris : tu fais un strlen sur un pointeur non alloué, or, ton professeur voulait que tu calcules la taille de la chaine finale avant de la mallocer, je pense. Et il manque le caractère supplémentaire pour terminer la chaîne.
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,



    Déclarer un pointeur n'alloue pas l'espace pointé.
    Il faut donc allouer l'espace automatiquement (déclaration d'un tableau) ou dynamiquement (avec malloc).

    resultat=(char*)malloc(strlen(resultat)*sizeof(char));.

    sizeof(char) vaut par définition 1.
    Tu dois allouer autant d'éléments qu'il y a de chiffres dans un nombre inférieur à 3200 dans ta base plus un pour le '\0' final.

    Attention, tu ne vérifies pas que le nombre entier est bien supérieur à 0.

    EDIT : grillé par Metalman

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut
    Bonjour,

    c'est la discipline de base en langage C: allouer la mémoire et la libérer.

    si ton programme marche c'est par hasard. Le pointeur à une valeur
    par défaut définie par le compilateur qui est "gentil" dans ton cas.
    (c'est pas gentil du tout en fait de te faire croire que ça marche)
    si ta boucle va suffisamment loin tu finiras fatalement par faire planter ton
    programme.

    comment faire un programme qui fait tout planter:
    déclarer un pointeur, lui donner la valeur 0, initialiser la mémoire sur laquelle il pointe par memset avec une taille qui représente
    la taille de la ram de la machine: ça efface toute la mémoire disponible au programme, si c'est toute la mémoire.
    lorsque l'on programmez en mode réel du µpro c'était fatal; il fallait éteindre la machine et la rallumer. Avec le mode protégé, une alerte interrompt le programme avant qu'il détruise tout.

    Pour limiter ces problèmes à répétition lors de la programmation, une solution
    consiste à encapsuler l'appel aux fonctions malloc et free dans un type défini
    par typedef. On utilise des méthodes pour manipuler le type qui sont des pointeurs
    de fonctions. C'est une façon de programmer dans un style objet mais en C.


    Exemple avec un type "Element" de liste (Liste est un autre type)

    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
    typedef long nListe;
     
    typedef struct Element 
    {
        char *val;		/* valeur de l'élément */
        short lg;	/* taille de l'element */
    } Element;
     
    typedef struct ListeSimple 
    {
        char nom[9];			/* nom de la liste (facilite le debuggage) */
        char chemin[TAILLE_CHEMIN]; /* chemin du fichier de sauvegarde de la liste FP 17/03/2002*/
        Element *elt;	 		/* tableau des éléments */
        nListe taille;			/* nombre d'éléments dans le tableau */
        nListe tailleMaximum;	/* taille maximum d'éléments dans le tableau */
        int (*Chercher)(); 	/* méthode de recherche des éléments */
        enreg enr; /*enregistrement éventuellement associé à la liste */
    } ListeSimple;
    allocation de l'élément dans une fonction de Liste par malloc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        if( liste->taille < liste->tailleMaximum )
        {
            liste->taille++;
            liste->elt[place].lg = pLongueur ? *pLongueur : strlen(valeur);
            liste->elt[place].val = malloc(liste->elt[place].lg+1);
            strcpy(liste->elt[place].val,valeur);
        }
    libération de la mémoire de l'élément par free:

    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
    int ElementDetruire(ListeSimple *liste,nListe place)
    { /* detruit element */
        nListe j    /* indice de boucle */
        ;
        if(liste->taille > 0 )
        {
            /* destruction d'un element */
            free(liste->elt[place].val);
            /* decalage des pointeurs des elements plus grands */
            for (j = place ; j < liste->taille -1; j++)
            {
                 liste->elt[j] = liste->elt[j+1];
            }
            liste->elt[j].lg = 0;
            liste->elt[j].val = (char *) 0;
            liste->taille--;
        }
     
        return VRAI;
    }

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct Element 
    {
    char *val; /* valeur de l'élément */
    short lg; /* taille de l'element */
    } Element;
    Je n'aime pas trop faire cela, Element est le type ou le nom de la structure ?
    Ie instancie-t-on comme cela : Element e; ou comme ceci : struct Element e; ?

    Je trouve bien plus clair de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct 
    {
    char *val; /* valeur de l'élément */
    short lg; /* taille de l'element */
    } Element;
    ou :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct S_Element
    {
    char *val; /* valeur de l'élément */
    short lg; /* taille de l'element */
    } Element;

  6. #6
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bonjour,

    mise à part l'importance pour le PO de comprendre qu'il faut allouer avant d'utiliser puis libérer quand on utilisera plus, le plus simple pour le problème est de remarquer que le plus grand nombre à traiter est 32000 et la plus petite base 2. Du coup la chaîne ne représentera au pire qu'un nombre de 15 chiffes : un char resultat[16] simplifie tout et fonctionne quel que soit le nombre à convertir et quelle que soit la base (tant qu'on ne modifie pas les limites).

  7. #7
    Membre averti
    Homme Profil pro
    cnam
    Inscrit en
    Avril 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Liban

    Informations professionnelles :
    Activité : cnam
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 14
    Par défaut
    Citation Envoyé par kwariz Voir le message
    Bonjour,

    mise à part l'importance pour le PO de comprendre qu'il faut allouer avant d'utiliser puis libérer quand on utilisera plus, le plus simple pour le problème est de remarquer que le plus grand nombre à traiter est 32000 et la plus petite base 2. Du coup la chaîne ne représentera au pire qu'un nombre de 15 chiffes : un char resultat[16] simplifie tout et fonctionne quel que soit le nombre à convertir et quelle que soit la base (tant qu'on ne modifie pas les limites).
    salut
    le but est de faire une allocation dynamique que je ne trouve pas neccesaire dans mon programme comme tu vien de citer 16 cahracter est suffisant ,que je veut savoir c'est quand j'ai definir char *resultat ca me definir une chaine de charactere que chaque caractere est place dans la memoire mais j'ai pas alloce une memoire pour ces caractere et le programme marche ,j'espere que la declaration d'une chaine dans code blocks alloc une memoire par defaut pour cette chaine

  8. #8
    Membre averti
    Homme Profil pro
    cnam
    Inscrit en
    Avril 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Liban

    Informations professionnelles :
    Activité : cnam
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 14
    Par défaut
    Citation Envoyé par lecosmotien Voir le message
    Bonjour,

    c'est la discipline de base en langage C: allouer la mémoire et la libérer.

    si ton programme marche c'est par hasard. Le pointeur à une valeur
    par défaut définie par le compilateur qui est "gentil" dans ton cas.
    (c'est pas gentil du tout en fait de te faire croire que ça marche)
    si ta boucle va suffisamment loin tu finiras fatalement par faire planter ton
    programme.

    comment faire un programme qui fait tout planter:
    déclarer un pointeur, lui donner la valeur 0, initialiser la mémoire sur laquelle il pointe par memset avec une taille qui représente
    la taille de la ram de la machine: ça efface toute la mémoire disponible au programme, si c'est toute la mémoire.
    lorsque l'on programmez en mode réel du µpro c'était fatal; il fallait éteindre la machine et la rallumer. Avec le mode protégé, une alerte interrompt le programme avant qu'il détruise tout.

    Pour limiter ces problèmes à répétition lors de la programmation, une solution
    consiste à encapsuler l'appel aux fonctions malloc et free dans un type défini
    par typedef. On utilise des méthodes pour manipuler le type qui sont des pointeurs
    de fonctions. C'est une façon de programmer dans un style objet mais en C.


    Exemple avec un type "Element" de liste (Liste est un autre type)

    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
    typedef long nListe;
     
    typedef struct Element 
    {
        char *val;		/* valeur de l'élément */
        short lg;	/* taille de l'element */
    } Element;
     
    typedef struct ListeSimple 
    {
        char nom[9];			/* nom de la liste (facilite le debuggage) */
        char chemin[TAILLE_CHEMIN]; /* chemin du fichier de sauvegarde de la liste FP 17/03/2002*/
        Element *elt;	 		/* tableau des éléments */
        nListe taille;			/* nombre d'éléments dans le tableau */
        nListe tailleMaximum;	/* taille maximum d'éléments dans le tableau */
        int (*Chercher)(); 	/* méthode de recherche des éléments */
        enreg enr; /*enregistrement éventuellement associé à la liste */
    } ListeSimple;
    allocation de l'élément dans une fonction de Liste par malloc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        if( liste->taille < liste->tailleMaximum )
        {
            liste->taille++;
            liste->elt[place].lg = pLongueur ? *pLongueur : strlen(valeur);
            liste->elt[place].val = malloc(liste->elt[place].lg+1);
            strcpy(liste->elt[place].val,valeur);
        }
    libération de la mémoire de l'élément par free:

    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
    int ElementDetruire(ListeSimple *liste,nListe place)
    { /* detruit element */
        nListe j    /* indice de boucle */
        ;
        if(liste->taille > 0 )
        {
            /* destruction d'un element */
            free(liste->elt[place].val);
            /* decalage des pointeurs des elements plus grands */
            for (j = place ; j < liste->taille -1; j++)
            {
                 liste->elt[j] = liste->elt[j+1];
            }
            liste->elt[j].lg = 0;
            liste->elt[j].val = (char *) 0;
            liste->taille--;
        }
     
        return VRAI;
    }

    bonsoir
    j'espere c'est comme tu as citer mon compilateur quand j'ai definir la chaine de caractere il a fait une allocation par defaut

  9. #9
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par ali alameh Voir le message
    salut
    le but est de faire une allocation dynamique que je ne trouve pas neccesaire dans mon programme comme tu vien de citer 16 cahracter est suffisant ,que je veut savoir c'est quand j'ai definir char *resultat ca me definir une chaine de charactere que chaque caractere est place dans la memoire mais j'ai pas alloce une memoire pour ces caractere et le programme marche ,j'espere que la declaration d'une chaine dans code blocks alloc une memoire par defaut pour cette chaine
    Bonsoir,
    Pour reprendre ce que d'autres on déjà bien dit :
    écrire char* resultat; dit juste au compilateur que tu vas utiliser une variable résultat qui va pointer quelque part. Le quelque part on ne le connait pas encore, c'est l'allocation qui va nous donner ce quelque part. Malheureusement par défaut resultat pointe vers un endroit complètement au hasard qui peut ou non être utilisé, dans ton cas : coup de bol ton programme tombe en marche, essaye le demain il fonctionnera encore, puis d'un coup le surlendemain il ne fonctionnera plus ...
    Donc pour allouer la mémoire il faut utiliser malloc et lui dire combien de place tu veux. Dans ton cas et dans tous les cas de figures 16 caractères (15 pour les chiffres et un pour le \0 terminal) suffiront.
    Si tu veux allouer au plus juste, le nombre de chiffres qu'il te faut pour écrire n en base B est 1+floor(log(n)/log(B)), tu rajoutes encore 1 pour le \0 terminal et voilà.

  10. #10
    Membre expérimenté Avatar de moins1
    Homme Profil pro
    Autre
    Inscrit en
    Février 2013
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Autre
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 85
    Par défaut
    Sinon avec ceil(log(n) / lob(b));

    En ajoutant 1 pour le '\0', on obtient la longueur du tableau.


  11. #11
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par moins1 Voir le message
    Sinon avec ceil(log(n) / lob(b));

    En ajoutant 1 pour le '\0', on obtient la longueur du tableau.

    En fait il faut utiliser 1+floor plutôt que ceil à cause des puissances exactes de b.
    En base b, b^k nécessite k+1 chiffres
    ceil(log(b^k)/log(b))=ceil(k)=k -> il manquera de la place pour un chiffre
    1+floor(log(b^k)/log(b))=1+floor(k)=1+k -> ok

    Ce détail vient du fait qu'il faut au exatement k chiffres pour écrire tout nombre n en base b>1 tel que
    b^(k-1) <= n < b^k
    (k-1)log(b) <= log(n) < klog(b), si n>0
    k-1 <= log(n)/log(b) < k
    Ce qui par définition de ceil nous donne :
    ceil(log(n)/log(b))=k-1

  12. #12
    Membre expérimenté Avatar de moins1
    Homme Profil pro
    Autre
    Inscrit en
    Février 2013
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Autre
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 85
    Par défaut
    Ah bon! Je le saurai à l'avenir!


Discussions similaires

  1. Pointeur sur une chaine de caractère string
    Par Lucier dans le forum C#
    Réponses: 9
    Dernier message: 17/03/2010, 14h22
  2. Réponses: 10
    Dernier message: 31/05/2007, 15h10
  3. Pointeur, tableau et chaines de caractères.
    Par rouliane dans le forum C++
    Réponses: 8
    Dernier message: 19/12/2006, 20h27
  4. Pointeurs et chaines de caractères
    Par Maria1505 dans le forum C
    Réponses: 3
    Dernier message: 05/11/2006, 13h46
  5. Réponses: 14
    Dernier message: 22/04/2006, 21h59

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