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 :

concaténation chaines de caractères en C


Sujet :

C

  1. #1
    Candidat au Club
    Femme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Juin 2013
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Juin 2013
    Messages : 2
    Points : 3
    Points
    3
    Par défaut concaténation chaines de caractères en C
    Salut à tous, le code suivant doit en principe faire la concaténation de deux chaines de caractères, mais c'est pas le cas. Sinon, ça compile quand même mais ça renvoi autre chose. J'arrive pas à trouver l'erreur.

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    size_t stringLength(const char* str)
    {
       size_t cpt = 0;
    	while (* str!='\0')
    	{
    		str++;
    		cpt++;
    	}
      return cpt;
    }
     
    char *concatenateString(const char *str1, const char *str2)
    {
        char *ptr;
        size_t s1=stringLength((str1));
        size_t s2=stringLength((str2));
        size_t s3=s1+s2-1;
     
        ptr=(char*)malloc(stringLength(s3)*sizeof(char));
        return ptr;
    }
     
     
     
    int main(void)
    {
       const char *chaine1 = "Salut";
       const char *chaine2 = "valli";
       char *concatenation;
     
        concatenation = concatenateString(chaine1, chaine2);
     
        printf("La nouvelle chaine est %s", concatenation);
     
        return 0;
    }
    merci d'avance

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ptr=(char*)malloc(stringLength(s3)*sizeof(char));


    Enfin tu ne fais qu'allouer une zone mémoire (à laquelle il manque deux char : size_t s3=s1+s2+1;) sans y copier les chaines str1 et str2 dedans.

    N'oublie pas de libérer la mémoire allouée à la fin.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 694
    Points : 30 992
    Points
    30 992
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par valliere Voir le message
    Salut
    Pourquoi ce "-1" ???

    Citation Envoyé par valliere Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    size_t stringLength(const char* str)
    {
       size_t cpt = 0;
    	while (* str!='\0')
    	{
    		str++;
    		cpt++;
    	}
      return cpt;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    size_t stringLength(const char* str)
    {
       size_t cpt;
       for (cpt=0; *str != '\0'; str++, cpt++);
       return cpt;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    pourquoi deux incrémentations quand l'arithmétique des pointeurs permet d'en éliminer une...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    size_t stringLength(const char* str)
    {
      const char *p = str;
      while ( *p++ != '\0');
      return p - str -1;
    }
    l'exemple ci dessous permet de comparer le résultat par rapport a strlen (qui fait le même job au passage)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int main()
    {
      char *hello = "hello";
      char world[50]= { 'W' , 'o', 'r', 'l', 'd', 0, };
      char *empty = "";
     
      printf("%d %d %s\n",stringLength(hello),strlen(hello), hello);
      printf("%d %d %s\n",stringLength(world),strlen(world), world);
      printf("%d %d %s\n",stringLength(empty),strlen(empty), empty);
     
      return EXIT_SUCCES;
    }
    donne

    gcc test.c -o test.exe && test.exe
    5 5 hello
    5 5 World
    0 0
    pour info strlen pour la glibc 2.7 est par exemple disponible ici:
    http://www.stdlib.net/~colmmacc/strlen.c.html
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 694
    Points : 30 992
    Points
    30 992
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jabbounet Voir le message
    pourquoi deux incrémentations quand l'arithmétique des pointeurs permet d'on éliminer 1...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    size_t stringLength(const char* str)
    {
      const char *p = str;
      while ( *p++ != '\0');
      return p - str -1;
    }
    Tant qu'à faire, pourquoi cette incrémentation de trop qui t'oblige a exécuter une soustraction (- 1) supplémentaire...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    size_t stringLength(const char* str)
    {
      const char *p;
      for (p=str; *p != '\0'; p++);
      return p - str;
    }
    ...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce qui est traitre avec les chaînes de caractères, c'est qu'on oublie facilement si une taille donnée contient ou non le caractère nul terminal.

    Je conseille d'adopter une convention pour ça. Personnellement, je différencie mes noms de variable/fonction entre "length" (sans caractère nul, comme le retourne strlen()) et "size" (avec caractère nul, comme une taille de buffer).

    Ce qui donne:
    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
    size_t StringLength(char const *str)
    {
    	size_t i;
    	for(i=0 ; str[i]!='\0' ; i++) {}
    	return i;
    }
     
    void StringCopy(char *buf, size_t bufSize, char const *input)
    {
    	size_t i;
    	for(i=0 ; i<bufSize ; i++) 
    	{
    		/*On copie d'abord, puis on vérifie si on a copié le \0*/
    		if((buf[i] = input[i]) == '\0')
    			break;
    	}
    	/*On termine systématiquement le buffer par \0, pour être sûr.*/
    	buf[bufSize-1] = '\0';
    }
     
    char* StringConcatAlloc(char const *left, char const *right)
    {
    	size_t leftLength = StringLength(left);
    	size_t rightLength = StringLength(right);
    	size_t concatLength = leftLength + rightLength;
    	size_t concatSize = concatLength + 1;
    	char* buf = malloc(concatSize * sizeof *buf);
    	if(buf != NULL)
    	{
    		StringCopy(buf, concatSize, left);
    		StringCopy(buf+leftLength, concatSize-leftLength, right);
    	}
    	return buf;
    }
    Quand je bosse avec des wchar_t, j'ajoute en plus de la notation hongroise pour différentier les tailles en bytes des tailles en caractères, mais ici ce n'est pas la peine.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 694
    Points : 30 992
    Points
    30 992
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void StringCopy(char *buf, size_t bufSize, char const *input)
    {
    	size_t i;
    	for(i=0 ; i<bufSize ; i++) 
    	{
    		/*On copie d'abord, puis on vérifie si on a copié le \0*/
    		if((buf[i] = input[i]) == '\0')
    			break;
    	}
    	/*On termine systématiquement le buffer par \0, pour être sûr.*/
    	buf[bufSize-1] = '\0';
    }
    Ta fonction ressemble à strncpy(). La seule différence, c'est que strncpy() ne met pas le '\0' quand elle arrête sa copie à n caractères. En plus des pb que ça m'a causé quand je l'ai utilisée sans connaitre ce détail, je trouve ça dommage et je suis content que toi tu forces le '\0'...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    strncpy() est une fonction d'un autre temps prévu pour un autre usage que celui pour lequel le manque d'équivalent force tant de gens à l'utiliser.

    Quand tu avais des fichiers contenant des enregistrements de ce type, elle était utile:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct personne __attribute__((packed))
    {
    	short sexe;
    	char nom[10];
    	char prenom[10];
    	short age;
    };
    Cela permettait d'utiliser la structure à pleine capacité plutôt qu'avoir tout le temps un caractère nul à la fin (de plus, elle remplit toujours le buffer complet, donc pas de déchets dans l'enregistrement). Mais pour en faire quoi que ce soit par la suite...

    En fait, tout comme UTF-8, strncpy() est plus appropriée au stockage qu'au traitement.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    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 : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Si c'est pour un besoin dans une application et non pour apprentissage, j'ai mieux... utilise ma bibliothèque (signature) qui gère tout à ta place sauf la libération... pour le moment
    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 !

  10. #10
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    bonjour,
    J'utilise ces codes que j'adapte selon pour une copie sécurisé:
    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
     
    size_t len(char *chaine)
    {
        size_t n = 0;
        while(chaine[n++]);
     
        return n-1;//or n en sachant l'implication
    }
     
    int test_args(unsigned int *ptrRef, unsigned int *ptr_start_index, int *ptr_end_index)
    {
         (*ptr_start_index) = ((*ptr_start_index) < 0 || (*ptr_start_index) > (*ptrRef))?0:(*ptr_start_index);
     
         (*ptr_end_index) = ((*ptr_end_index) <= (*ptr_start_index)
                             ||(*ptr_end_index) > (*ptrRef))?
                             (*ptrRef):(*ptr_end_index);
     
             (*ptrRef) = ((*ptr_end_index) - (*ptr_start_index))+1;
     
         return *ptrRef;//
     
    }
     
    char *copie_cibler(
                     const char *source,
                     unsigned int start_index,
                     int end_index)
                     {
                         size_t largeur = len(source);
                         char *nouv = NULL;
     
                         if(test_args(&largeur, &start_index, &end_index)>0)//regularise arguments
                         {
                             nouv = malloc(sizeof(char) * largeur);
                             nouv[largeur] = '\0';
     
                             //copie
                             for(largeur = 0; start_index <= end_index; nouv[largeur++] = source[start_index++]);
     
                         }
     
                         return nouv;
                     }
    Ce que je déplores c'est que l'ensemble des codes postés sont juste prévus pour une utilisation conventionnelle.
    Quelle parade avez-vous dans le cas d'un appel externe avec un argument qui ne fournit pas le délimiteur '\0'?

    @Franck.H: j'ai visité. ça me paraît intéressant. J'ai téléchargé la source.
    Je comptes explorer.
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Attention, il manque un const à ta fonction len().
    Et aussi, tu devrais utiliser plus de variables plutôt que changer la sémantique de l'une (comme largeur qui passe de "longueur de la source" à "position où l'on insère dans la sortie").

    Ah, et aussi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nouv = malloc(sizeof(char) * largeur);
    nouv[largeur] = '\0';
    Comportement indéfini, tu écris hors du buffer alloué.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    Bonjour
    Excellentes remarques, ça aurait du être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nouv = malloc(sizeof(char) * (largeur+1))
    Mais quand au conseil de plus de variables pour préserver "largeur", je ne vois pas trop l'incidence par rapport à la suite du traitement?
    Aurais tu aussi une idée sur la parade prévue pour la petite remarque qui me turlupine?
    Merci.
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est plus une question de lisibilité et de maintenabilité qu'autre chose. Une variable, une utilité (et au passage, tu peux alors déclarer largeur const pour bien montrer qu'elle n'est pas modifiée après son initialisation).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 694
    Points : 30 992
    Points
    30 992
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    J'utilise ces codes que j'adapte selon pour une copie sécurisé:
    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
    char *copie_cibler(
                     const char *source,
                     unsigned int start_index,
                     int end_index)
                     {
                         size_t largeur = len(source);
                         char *nouv = NULL;
     
                         if(test_args(&largeur, &start_index, &end_index)>0)//regularise arguments
                         {
                             nouv = malloc(sizeof(char) * largeur);
                             nouv[largeur] = '\0';
     
                             //copie
                             for(largeur = 0; start_index <= end_index; nouv[largeur++] = source[start_index++]);
     
                         }
     
                         return nouv;
                     }
    Mouais. Ta fonction est un semblant de strndup(). Toutefois une copie "sécurisée" qui ne teste pas le retour de malloc...

    Citation Envoyé par NVCfrm Voir le message
    Quelle parade avez-vous dans le cas d'un appel externe avec un argument qui ne fournit pas le délimiteur '\0'?
    Tu veux dire une parade dans le cas où l'appelant ne fournit pas ce qui est demandé ? Ben il n'y en a pas. Imagine la zone mémoire suivante: 0x74 0x6f 0x74 0x6f 0x57 0x22. Comment sauras-tu deviner là dedans où se termine la chaine "toto" ???
    S'il y a des obligations c'est un petit peu parce que c'est... obligatoire quoi...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  15. #15
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    Mais quand au conseil de plus de variables pour préserver "largeur", je ne vois pas trop l'incidence par rapport à la suite du traitement?
    Citation Envoyé par Médinoc Voir le message
    C'est plus une question de lisibilité et de maintenabilité qu'autre chose. Une variable, une utilité (et au passage, tu peux alors déclarer largeur const pour bien montrer qu'elle n'est pas modifiée après son initialisation).
    C'est un peu comme si tu disais "mon chat" en parlant de ton chien : ton histoire sera dure à suivre et la moitié des gens ne comprendront rien à ton charabia d'un chat qui aboie le facteur. Le code c'est pareil : on appelle un chat un chat et on ne met pas une largeur dans une variable se nommant longueur.

    Citation Envoyé par Sve@r Voir le message
    Tu veux dire une parade dans le cas où l'appelant ne fournit pas ce qui est demandé ? [...] S'il y a des obligations c'est un petit peu parce que c'est... obligatoire quoi...
    Ah ! Le vaste domaine de la programmation défensive. Malheureusement, il n'y a pas vraiment de défense (simple) contre des chaines qui ne se terminent pas par un '\0'

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Ah ! Le vaste domaine de la programmation défensive. Malheureusement, il n'y a pas vraiment de défense (simple) contre des chaines qui ne se terminent pas par un '\0'
    C'est surtout qu'on les met aux entrées/sorties puis on n'en parle plus. Si on connait la longueur d'un buffer, on écrit un \0 au bout dès que possible, tant et si bien que quand on arrive à des fonctions qui prennent un pointeur const, (et qui donc ne peuvent plus tronquer le buffer) on n'a plus à s'en soucier.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Ah ! Le vaste domaine de la programmation défensive. Malheureusement, il n'y a pas vraiment de défense (simple) contre des chaines qui ne se terminent pas par un '\0'
    L'important est de connaitre les données que l'on manipule, et les restriction que l'on impose aux fonctions que l'on expose en interface, c'est une des responsabilité de base du programmeur.


    il y'a la possibilité d'utiliser/adopter une autre représentation/convention pour les chaînes de caractères comme celle qui ne définissent pas de caractères terminal.

    Certain langages comme Emacs Lisp ne suivent pas la convention du C et leur manipulation ne pose pas de problèmes particuliers, je ne suis pas allé vérifier pour les autres jargon lisp.

    Citation Envoyé par http://www.gnu.org/software/emacs/manual/html_node/elisp/String-Basics.html#String-Basics
    Unlike in C, Emacs Lisp strings are not terminated by a distinguished character code
    faire cela en C impliquerai de se passer des fonctions de la libc sur les chaines (strlen, strcpy, ...)
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  18. #18
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    Bonsoir,

    Sve@r: J'ai réecrit les extraits en m'inspirant des lignes d'un programme qui sont relatives à ce thread. Un peu à la va vite sans doute, mais en omettant volontairement la vérification de malloc. Le but était de donner un exemple participatif.
    Tu veux dire une parade dans le cas où l'appelant ne fournit pas ce qui est demandé ? Ben il n'y en a pas. Imagine la zone mémoire suivante: 0x74 0x6f 0x74 0x6f 0x57 0x22. Comment sauras-tu deviner là dedans où se termine la chaine "toto" ???
    S'il y a des obligations c'est un petit peu parce que c'est... obligatoire quoi...
    Je me demandais... des orientations possibles comme ce qui se fait avec la macro offsetof sur les structures.

    @Médinoc:
    C'est surtout qu'on les met aux entrées/sorties puis on n'en parle plus. Si on connait la longueur d'un buffer, on écrit un \0 au bout dès que possible, tant et si bien que quand on arrive à des fonctions qui prennent un pointeur const, (et qui donc ne peuvent plus tronquer le buffer) on n'a plus à s'en soucier.
    Oui, quand on a un programme hermétique dans un processus.
    Je penses aux cas d'appels incorrects d'une fonction prévue à cet effet par un programme externe, dû à des maladresses ou des intentions curieuses ou malsaines. Et je n'arrives pas à m'expliquer le résultat de certains tests réalisés il y a peu sur l'exemple que j'ai posté.
    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
    int main()
    {
     
        char *salut = "Bonjour";
        char *copie_salut;
     
        int taille = len(salut);
        printf("la longueur de la chaine: '%s' manipuler est de: %d\n",salut, taille);
        copie_salut = copie_cibler(salut,0,0);
        printf("La copie donne sans les 2 derniers arg: %s\n", copie_salut);
        free(copie_salut);copie_salut = NULL;
        //on oublie pas que l'indice de base est zéro
        copie_salut = copie_cibler(salut, 3, 0);
        printf("En ciblant le debut de la copie sur le 4ieme indice, cela nous donne: %s\n", copie_salut);
        free(copie_salut);copie_salut = NULL;
        copie_salut = copie_cibler(salut, 0, 2);
        printf("En ciblant la partie comprise du début au 3ieme indice, cela nous donne: %s\n\n", copie_salut);
        free(copie_salut);copie_salut = NULL;
        copie_salut = copie_cibler(salut, -1, 12);//dépassement d'indice fin
        printf("En tentant un debordement, cela nous donne toujours: %s\n\n", copie_salut);
     
        /**et maintenant avec un type tableau*/
        char inconnu[8] = {'B','o','n','j','o','u','r','!'};
        /**un programmeur distrait qui a oublié la convention du caractère null */
     
        printf("Avec l'absence du delimiteur on a ceci: %s et une longueur de : %d\n",inconnu, len(inconnu));
        printf("Que faire contre cet incident?\n\n");
     
        free(copie_salut);copie_salut = NULL;
     
        /**la fonction n'a pas le même comportement que printf. J'aimerais bien svoir pourquoi? */
        copie_salut = copie_cibler(inconnu, 3, 20);
        printf("Curieusement en creant une copie, la longueur de la copie est: %d\n", len(copie_salut));
        printf("Et la copie se limite juste au derniers caracteres du tableau: %s\n", copie_salut);
        /** Le type tableau qui se confond beaucoup avec les pointeurs aurait-il quelque chose de particulièrement utile dans ce cas?*/
        /** Cela est-il dû à l'instruction "while(chainee[n++]" de la fonction len ? */
        free(copie_salut);
    return 0;
    }
    @Bktero:
    D'habitude je ne réponds pas aux commentaires sarcastiques.
    C'est à croire qu'on a rien de mieux à faire ici que ...
    Ok! Passons.
    Qu'en sais tu du chien et du chat?
    Les deux ont en commun bien de choses comme grogner..., mais surout leurs domesticités et leurs attachements à un maître qui se préoccupe d'eux. Ces deux derniers cas qui sont une caractéristique qu'on trouve dans l'informatique.
    L'allusion devient encore beaucoup plus hors-propos quand on parle de programmation.
    Tu le sais très bien et l’effectues dans chaque programme que tu écris en appelant un chat, un chien ou vice versa.
    Encore que tu ne pourras répondre aux questions:
    Combien de fois tu manipules un char comme si c'était un int, ou l'inverse?
    Combien de contorsions as tu fais à travers des codes pour avoir une autre représentation d'une valeur?
    Cela n’a pas été un inconvénient pour toi ou le lecteur averti de la compréhension de ce qui se passe
    Longueur , largeur représente en géométrie des côtés spécifiques d'un quadrilatère. Autrement dit, on trouve clairement des notions de dimensions à travers ces 2 termes. Cela n’a peut avoir aucune confusion à mon niveau et au niveau de ceux qui comme moi sont à l’aise avec des gallons ou des litres, des cm ou pouces… Diable! Ne s'agit-il pas de mesures?
    Rien n’empêche le chat de miauler à la présence du facteur, pardon d’aboyer un miaouuuuuu, si cela peut se concevoir comme un wouuuuhh. qui sonne faux sans blague !
    J'ai posté un code comme beaucoup, en relation avec un thread que je n'ai pas ouvert.
    Sais tu où as tu seulement compris les motivations et justifications de mon intrusion dans un espace où je n'interviens pas habituellement?
    Naturellement non!
    Comme beaucoup, c’est pour ajouter une pierre aux idées (qui ne sont pas toujours exemptes d’imperfections) qui pleuvent. Mais souvent comme tous ici aussi, c'est parfois pour avoir des éclaircissements. Dans ce cas, il y a avait surtout en arrière plan quelque chose qui me préoccupe sur laquelle j’ai voulu quelques idées.
    La deuxième partie de ta réponse est en relation avec l’éclairage que je cherche.
    Les termes employés supposent que tu aurais des idées.
    Pourquoi ne pas en parler plutôt que d’émettre une raillerie ironique?
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

  19. #19
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    Ce que je déplores c'est que l'ensemble des codes postés sont juste prévus pour une utilisation conventionnelle.
    Quelle parade avez-vous dans le cas d'un appel externe avec un argument qui ne fournit pas le délimiteur '\0'?
    l'exemple soumis dans la question sous entendais assez fortement une utilisation conventionnelle....

    il est a noté que le code de la fonction len() que tu fournit souffre aussi du même problème '\0' est complétement équivalent à la constante entière 0, c'est simplement un notation pour rendre un intention dans le code l'intention étant d'indiquer que l'on manipule des caractères.
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  20. #20
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 694
    Points : 30 992
    Points
    30 992
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    Je penses aux cas d'appels incorrects d'une fonction prévue à cet effet par un programme externe, dû à des maladresses ou des intentions curieuses ou malsaines.
    Quand on débute le C, la première chose qu'on apprend c'est que le C a été développé volontairement sans aucun garde-fou pour être le plus rapide possible. Et que sa philosophie c'est que "le programmeur sait ce qu'il fait". Ca peut plaire ou pas. Ca peut paraitre aujourd'hui incongru au regard de la puissance de nos ordis ; surtout pour ceux qui ne savent pas qu'avant d'être chanteur Noah était un jouer de tennis et qui n'ont pas connus l'oric 16k et l'oric Athmos (rouge et noir) qui arborait fièrement 32ko de ram). Et je ne parle pas des programmes sur cartes perforées ; mais ça n'en reste pas moins une réalité toujours présente.
    Alors effectivement cela amène certains programmes mal conçus à être la cibles des overflows et on ne peut rien faire contre ça. Si une fonction doit recevoir une chaine, elle ne pourra rien faire si le truc qu'on lui passe n'en est pas une. Tout ce qu'on peut faire c'est filtrer au maximum tout ce qui vient de l'extérieur (en commençant par argv).

    Citation Envoyé par NVCfrm Voir le message
    @Bktero:
    D'habitude je ne réponds pas aux commentaires sarcastiques.
    C'est à croire qu'on a rien de mieux à faire ici que ...
    Non faut pas dire ça. C'est vrai qu'on se (te) chambre tous un peu mais je t'assure que c'est très amical. Car je t'assure que si on t'avait perçu comme un mauvais con, ça aurait été autre chose. Punaise je me souviens d'un pauvre type qui voulait absolument me persuader que feof() ne s'utilisait pas comme je lui disais mais comme lui pensait et qui, en plus, nous (me) prenait de haut. Surtout qu'il avait pondu un code de démo qui marchait à cause d'un bug. Qu'est-ce qu'il a pris dans la tronche. Au point que les modis (oui oui, c'est bien du latin => un modo, des modis) ont dû intervenir...

    Citation Envoyé par NVCfrm Voir le message
    Ok! Passons.
    Qu'en sais tu du chien et du chat?
    Les deux ont en commun bien de choses comme grogner..., mais surout leurs domesticités et leurs attachements à un maître qui se préoccupe d'eux. Ces deux derniers cas qui sont une caractéristique qu'on trouve dans l'informatique.
    L'allusion devient encore beaucoup plus hors-propos quand on parle de programmation.
    Tu le sais très bien et l’effectues dans chaque programme que tu écris en appelant un chat, un chien ou vice versa.
    Encore que tu ne pourras répondre aux questions:
    Combien de fois tu manipules un char comme si c'était un int, ou l'inverse?
    Combien de contorsions as tu fais à travers des codes pour avoir une autre représentation d'une valeur?
    Cela n’a pas été un inconvénient pour toi ou le lecteur averti de la compréhension de ce qui se passe
    Longueur , largeur représente en géométrie des côtés spécifiques d'un quadrilatère. Autrement dit, on trouve clairement des notions de dimensions à travers ces 2 termes. Cela n’a peut avoir aucune confusion à mon niveau et au niveau de ceux qui comme moi sont à l’aise avec des gallons ou des litres, des cm ou pouces… Diable! Ne s'agit-il pas de mesures?
    Rien n’empêche le chat de miauler à la présence du facteur, pardon d’aboyer un miaouuuuuu, si cela peut se concevoir comme un wouuuuhh. qui sonne faux sans blague !
    En dehors des exmples donnés en POO, héritage et polymorphisme concernant les chats et les chiens qui héritent de la classe "mamifères" mais qui sont différents des dauphins et baleines, je pense qu'il voulait parler des conventions qui améliorent la lisibilité et le travail en coopération. Perso j'aime bien que mes tailles s'appellent "sz_" et si je dois coder une mesure, j'essaierai de prendre un nom adapté à ladite mesure et à ce qu'elle représente dans la vie réelle. Ne serait-ce que pour pouvoir me relire 6 mois après sans avoir envie de me gifler

    Citation Envoyé par NVCfrm Voir le message
    ...Mais souvent comme tous ici aussi, c'est parfois pour avoir des éclaircissements. Dans ce cas, il y a avait surtout en arrière plan quelque chose qui me préoccupe sur laquelle j’ai voulu quelques idées.
    Citation Envoyé par Bktero Voir le message
    ...Malheureusement, il n'y a pas vraiment de défense (simple) contre des chaines qui ne se terminent pas par un '\0'
    La deuxième partie de ta réponse est en relation avec l’éclairage que je cherche.
    Les termes employés supposent que tu aurais des idées.
    Pourquoi ne pas en parler plutôt que d’émettre une raillerie ironique?
    Je pense qu'il s'agissait d'un euphémisme car (pour moi) il n'y a aucun moyen de détecter, parmi une suite d'octets, quelle suite correspond à une chaine et quelle suite n'y correspond pas. Hormis en passant par une convention précise. Ca peut-être un caractère spécial (comme '\0'), ou alors comme dans un autre langage (que j'ai oublié) la taille de la chaine stockée dans l'élément[0] mais quoi qu'il en soit, une fois la convention établie, il n'y a aucun moyen de détecter celui qui la respecte de celui qui ne la respecte pas. Après-tout, le '\0' n'a pas été mis pour faire suer les progs mais parce qu'il n'y avait pas moyen de faire sans...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Concaténation chaines de caractères
    Par pif_dz dans le forum Cobol
    Réponses: 1
    Dernier message: 21/01/2013, 14h51
  2. Concaténation chaines de caractères
    Par pif_dz dans le forum Cobol
    Réponses: 0
    Dernier message: 21/01/2013, 11h49
  3. Comment concaténer une chaine de caractères avec un espace ?
    Par blanchonvincent dans le forum MATLAB
    Réponses: 6
    Dernier message: 07/04/2007, 21h53
  4. Réponses: 2
    Dernier message: 02/04/2007, 11h07
  5. Réponses: 1
    Dernier message: 25/04/2006, 16h06

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