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 :

Initialisation chaine de caractère


Sujet :

C

  1. #1
    Inactif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Par défaut Initialisation chaine de caractère
    Bonjour,

    mon programme m'affiche ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    nouveautest.c: In function `main':
    nouveautest.c:67: warning: initialization discards qualifiers from pointer target type

    Ce ne comprend pas le problème car je passe à Analyse un &

    le prototype de ma fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     int Analyse(char **ligne)

    mon main:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int main(void)
    {
      char *ligne = "1 25 125.25";
      printf("la chaine %s que des chiffres\n",Analyse(&ligne)==1?"ne contient pas":"contient");
      return 0;
    }

  2. #2
    Expert confirmé
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Par défaut
    C'est laquel la ligne 67

    N'oubli pas qu'un chaine declare comme cela
    char * = "df";

    n'est pas modifiable

    Citation Envoyé par FAQ de C
    La syntaxe suivante :

    char* chaine="bonjour";

    ne crée pas une chaîne initialisée à la valeur "bonjour" mais crée un pointeur contenant l'adresse d'une chaîne littérale valant "bonjour". L'emplacement des chaînes littérales dépend de la cible. Le langage C ne garantit pas que cette zone soit modifiable.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 237
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     printf("la chaine %s que des chiffres\n",Analyse(&ligne)==1?"ne contient pas":"contient");
    C'est celle la je parie!

    essaie plutot ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if (Analyse(&ligne)==1)
      printf("la chaine ne contient pas que des chiffres\n");
    else
      printf("la chaine contient que des chiffres\n");
    Je trouve ton printf bizarre...
    Le "==1" sert a rien, non?


    EDIT : beaucoup de betise dans mon post la... desole...

  4. #4
    Inactif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Par défaut
    Citation Envoyé par Skyrunner
    C'est laquel la ligne 67

    N'oubli pas qu'un chaine declare comme cela
    char * = "df";

    n'est pas modifiable

    Citation Envoyé par FAQ de C
    La syntaxe suivante :

    char* chaine="bonjour";

    ne crée pas une chaîne initialisée à la valeur "bonjour" mais crée un pointeur contenant l'adresse d'une chaîne littérale valant "bonjour". L'emplacement des chaînes littérales dépend de la cible. Le langage C ne garantit pas que cette zone soit modifiable.
    La ligne 67 est cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     char *ligne = "1 25 125.25";
    Comment faut-il faire ?

  5. #5
    Expert confirmé
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Par défaut
    Citation Envoyé par Gryzzly
    Citation Envoyé par Skyrunner
    C'est laquel la ligne 67

    N'oubli pas qu'un chaine declare comme cela
    char * = "df";

    n'est pas modifiable

    Citation Envoyé par FAQ de C
    La syntaxe suivante :

    char* chaine="bonjour";

    ne crée pas une chaîne initialisée à la valeur "bonjour" mais crée un pointeur contenant l'adresse d'une chaîne littérale valant "bonjour". L'emplacement des chaînes littérales dépend de la cible. Le langage C ne garantit pas que cette zone soit modifiable.
    La ligne 67 est cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     char *ligne = "1 25 125.25";
    Comment faut-il faire ?
    essaye a coup de malloc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ligne = malloc(100);
    strcpy(ligne,"1 25 125.25");
    [...]
    free(ligne);
    ou comme ca
    char ligne[] = "1 25 125.25";

  6. #6
    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
    Est-ce qu'on peut avoir un code compilable, moi je viens de regarder mais je ne vois pas spécialement de problème. De plus, si tu ne modifies pas ta chaîne, tu peut la déclarer de la sorte (comme tu as fait) !
    Par ailleurs, si tu ne modifies pas ta chaîne, il est inutile de passer l'adresse du pointeur !
    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 !

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Gryzzly
    nouveautest.c:67: warning: initialization discards qualifiers from pointer target type
    La ligne 67 est cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     char *ligne = "1 25 125.25";
    Comment faut-il faire ?
    Je suppose que tu utilises -Wwrite-strings avec gcc (ou l'équivalent avec un autre compilateur, mais le texte et le format de l'erreur sont ceux de gcc) dont l'objectif est de signaler ce genre de cas.

    Le code que tu donnes est conforme, mais il faut faire attention car ligne est initialisé en pointant vers une zone de mémoire qui peut ne pas être modifiable, et qui peut être partagée (par exemple si la constante "125.25" apparaît ailleurs) bien que rien dans le type de ligne ne signale le problème. Un moyen de permettre au compilateur de vérifier autant que possible que la mémoire soit modifiée, c'est de déclarer ligne comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char const* ligne = "1 25 125.25";
    où tu dis que ligne pointe vers des caractères constants. Si par contre tu voulais déclarer un tableau de char et l'initialiser à la valeur constante donnée, il aurait fallu écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char ligne[] = "1 25 125.25";
    ligne aurait été alors un tableau de 12 char (12 à cause du \0 final), tu aurais aussi pu spécifier la taille explicitement de 11 (auquel ca il n'y aurait pas eu de \0 final) à ce que tu veux (auquel cas le tableau aurait contenu des \0 en plus).

  8. #8
    Inactif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Citation Envoyé par Gryzzly
    nouveautest.c:67: warning: initialization discards qualifiers from pointer target type
    La ligne 67 est cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     char *ligne = "1 25 125.25";
    Comment faut-il faire ?
    Je suppose que tu utilises -Wwrite-strings avec gcc (ou l'équivalent avec un autre compilateur, mais le texte et le format de l'erreur est celui de gcc) dont l'objectif est de signaler ce genre de cas.

    Le code que tu donnes est conforme, mais il faut faire attention car ligne est initialisé en pointant vers une zone de mémoire qui peut ne pas être modifiable, et qui peut être partagée (par exemple si la constante "125.25" apparaît ailleurs) bien que rien dans le type de ligne ne signale le problème. Un moyen de permettre au compilateur de vérifier autant que possible que la mémoire soit modifiée, c'est de déclarer ligne comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char const* ligne = "1 25 125.25";
    où tu dis que ligne pointe vers des caractères constants. Si par contre tu voulais déclarer un tableau de char et l'initialiser à la valeur constante donnée, il aurait fallu écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char ligne[] = "1 25 125.25";
    ligne aurait été alors un tableau de 12 char (12 à cause du \0 final), tu aurais aussi pu spécifier la taille explicitement de 11 (auquel ca il n'y aurait pas eu de \0 final) à ce que tu veux (auquel cas le tableau aurait contenu des \0 en plus).
    Bonjour,
    je compile effectivement de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -Wall -ansi -g -Wwrite-strings nouveautest.c -o nt
    En utilisant la manière dont tu as écris,j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nouveautest.c: In function `main':
    nouveautest.c:76: warning: passing arg 1 of `Analyse' from incompatible pointer type
    En revanche,lorsque j'utilises ce que j'ai mis en commentaire dans le main,cela fonctionne.
    Pourquoi?


    Avec ce programme:
    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<ctype.h>
    #include<stdlib.h>
    #include<float.h>
    #include<string.h>
     
     
    void espace(char **ligne)
    {
      while(**ligne == ' ')
        (*ligne)++;
    }
     
     
    int Analyse(char **ligne)
    {
      double val;
      char *mot = malloc(256);
      char *endptr = NULL;
     
      espace(ligne);
     
      /* on est en fin de chaine */
      if(**ligne == '\0')
        {
          fprintf(stderr,"erreur : rien n'a ete lu\n");
          return 1;
        }
     
      while(**ligne != '\0')
        {
          /* c'est un chiffre */
          if(isdigit(**ligne))
    	{
    	  mot = *ligne;
     
    	  while(isdigit(**ligne) || **ligne == '.') (*ligne)++;
     
    	  /*if(**ligne != ' ') 
    	    return 1;*/
     
    	  **ligne = '\0';
    	  (*ligne)++;
    	  espace(ligne);
     
    	  double v = strtod(mot,&endptr);
     
    	  /*la chaine ne commence pas par un chiffre */ 
    	  if(endptr == mot)
    	    return 1;
     
    	  if(*endptr != '\0')
    	    return 1;
    	  val = v;
    	  printf("%lf\n",val);
    	}
          else
    	{
    	  fprintf(stderr,"erreur\n");
    	  return 1;
    	}
        }
     
      return 0;
    }
     
     
     
    int main(void)
    {
      /*char *ligne = malloc(100);
        strcpy(ligne,"144   478 12.4755");*/
     
      char const *ligne = "144   478  12.4750";
     
      if (Analyse(&ligne)==1)
        printf("la chaine ne contient pas que des chiffres\n");
      else
        printf("la chaine contient que des chiffres\n");
     
      return 0;
    }

  9. #9
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Gryzzly
    je compile effectivement de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -Wall -ansi -g -Wwrite-strings nouveautest.c -o nt
    Continue à le faire. Je te conseille aussi au minimum -W (qui peut s'écrire -Wextra dans les dernières versions) et -pedantic-errors.

    En utilisant la manière dont tu as écris,j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nouveautest.c: In function `main':
    nouveautest.c:76: warning: passing arg 1 of `Analyse' from incompatible pointer type
    En effet, Analyse prend un char** et si tu fais &ligne avec ligne qui est un char const*, le résultat est char const**. Les deux types sont incompatibles et pour de bonnes raisons.

    En effet, maitenant qu'on sait un peu plus du contexte, on voit qu'Analyse modifie à le pointeur dont on passe l'adresse (il y a des (*ligne)++) et ce vers quoi il pointe (il y a **ligne = '\0'). Donc tu te trouves dans le cas où le warning initial signalait effectivement un problème.

    J'ai mes doutes sur l'intérêt du comportement d'Analyse, mais pour rendre le programme conforme sur ce point, ce que tu as fait est une option. La deuxième méthode que je signalais me semble un peu plus simple à mettre en oeuvre:

  10. #10
    Inactif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Par défaut
    Bonjour,

    si au lieu mettre ma chaine de caractère dans le main,j'utilises
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char*argv[])
    comment est ce que j'appeles ma fonction Analyse?
    Comme ceci?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(i=0;i<argc,i++)
    if(Analyse(&argv[i])==0)
    <...>

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Gryzzly
    si au lieu mettre ma chaine de caractère dans le main, j'utilises
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char*argv[])
    comment est ce que j'appeles ma fonction Analyse?
    Ta fonction Analyse modifiant la chaîne sur laquelle on lui donne un pointeur, tu ne peux pas lui passer un pointeur vers les arguments sans les avoir recopiés.

Discussions similaires

  1. [SSE] Initialiser un DOM XML à partir d'une chaine de caractères ?
    Par nd786mar1 dans le forum Eclipse Platform
    Réponses: 5
    Dernier message: 16/12/2010, 17h02
  2. Réponses: 7
    Dernier message: 12/10/2009, 17h00
  3. Initialiser une chaine de caractère
    Par lutin06 dans le forum C
    Réponses: 27
    Dernier message: 11/03/2007, 12h39
  4. Réponses: 15
    Dernier message: 04/11/2006, 10h02
  5. Réponses: 3
    Dernier message: 17/12/2003, 11h26

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