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 :

Un printf différent


Sujet :

C

  1. #1
    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 Un printf différent
    Bonjour !


    Ca fait un bail que j'ai plus posé de question mais là je suis devant un petit problème sans doute de conception de l'époque mais pas trouvé réellement d'alternative.

    J'ai créé il y a bien 2 ans un objet String perso "C_Str" et je vais reprendre un peu le développement pour l'améliorer et voir peut-être même le compléter. Dans cet objet se trouve des fonctions de la famille printf genre:

    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
    int C_Str_printf (C_Str * const format, ...)
    {
       int ret = -1;
       va_list params;
     
     
       if (format != NULL && format->sz_string != NULL && format->len > 0)
       {
          va_start (params, format->sz_string);
          ret = vprintf (format->sz_string, params);
          va_end (params);
       }
     
     
       return ret;
    }
    L'objet de base est le suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct _C_Str
    {
       char * sz_string;
       size_t len;
    };
    Mon problème viens de la liste variable. Je sais que
    La macro va_arg se développe en une expression qui a le type et la valeur de l'argument suivant de l'appel.
    hors ici dans l'ouverture de la liste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    va_start (params, format->sz_string);
    le type n'est plus le même vu que le but est d'utiliser la chaîne contenu dans l'objet et non pas l'objet lui même et que pour une question de sécurité au niveau de la chaîne, seul l'objet peut être passé en argument aux fonctions car c'est un objet opaque.

    Le compilateur me dit
    D:\Programmation\Modules\C_Str\v2.3\c_str.c|765|warning: second parameter of `va_start' not last named argument|
    ce qui est tout à fait normal Bien sûr cela fonctionne quand même, testé sur la même machine, windows et linux mais est-ce que ca peut engendrer tôt ou tard chez d'autre personnes des comportements indéterminés ca, ca reste à savoir

    Enfin bref après cette présentation précise, quelles seraient les solutions, en tenant compte que le but final est d'avoir des fonctions comme printf (et les autres de la même famille) jusqu'au niveau de leur utilisation et tout en étant des fonction variadiques ?


    Merci pour vos suggestions/conseils
    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 !

  2. #2
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Je n'ai pas du comprendre ton problème car que je comprend toujours pas pourquoi tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    va_start (params, format->sz_string);
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    va_start (params, format);

  3. #3
    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
    Citation Envoyé par nicolas.sitbon Voir le message
    Je n'ai pas du comprendre ton problème car que je comprend toujours pas pourquoi tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    va_start (params, format->sz_string);
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    va_start (params, format);
    Oui en effet tu n'as pas compris mon problème

    Ce que tu m'a proposé plus haut ne fonctionne pour la simple et bonne raison évoquée dans mon premier post, est que ici format représente mon objet String et non la chaîne qui est le memebre sz_string de l'objet en question.

    Ici le but est de travailler sur la chaîne donc je suis obligé de faire format->sz_string étant donné que le compilateur ne va pas deviner ce que je veux faire (quoique, ca serait pas mal ca )
    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 !

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 726
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 726
    Par défaut
    D'après ce que j'ai compris le c_str_printf prend est un printf dans lequel les différents char* ont été remplacés par des c_str.
    Et peut être pas seulement le premier argument => il faut peut être analyser le contenu du fmt pour traiter les éventuels %s comme c_str?
    Pour le reste, je pense comme nicolas.sitbon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          va_start (params, format);  // a-t-on le choix???
    ce qui n'empêche pas de passer le "format->sz_string" à vsxxx
    non?
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Je suis de l'avis de nicolas.sitbon et wiztricks :
    Ceci "semble" marcher (j'ai légèrement modifié C_Str pour tester)
    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
    typedef struct _C_Str
    {
       char  sz_string[256];
       size_t len;
    }C_Str;
    //---------------------------------------------------------------------------
    int C_Str_printf (C_Str * const format, ...)
    {
       int ret = -1;
       va_list params;
     
     
       if (format != NULL && format->sz_string != NULL && format->len > 0)
       {
          va_start (params, format);
          ret = vprintf (format->sz_string, params);
          va_end (params);
       }
       return ret;
    }
    //---------------------------------------------------------------------------
    int main(void)
    {
      char fr[] = "%d%s" ;
      int i;
      C_Str frmt;
      strcpy(frmt.sz_string,fr);
      frmt.len = strlen(fr);
      i = C_Str_printf(&frmt, 18,"azerty");
      return 0;
    }
    alors qu'avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    va_start (params, format->sz_string);
    ça plante.

    Reste le problème d'avoir comme argument un c_str comme le signale wiztricks

  6. #6
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Ce que tu m'a proposé plus haut ne fonctionne pour la simple et bonne raison évoquée dans mon premier post, est que ici format représente mon objet String et non la chaîne qui est le memebre sz_string de l'objet en question.

    Ici le but est de travailler sur la chaîne donc je suis obligé de faire format->sz_string étant donné que le compilateur ne va pas deviner ce que je veux faire (quoique, ca serait pas mal ca )
    Je pense qu'il y a une incompréhension sur les paramètres à passer à va_start(). Il n'attend pas du tout la chaîne de formatage (qui peut très bien ne pas exister du tout par ailleurs, l'ellipse n'est pa réservé à des utilisation du style de printf() ou de scanf() bien que ce soit l'usage le plus fréquent) mais le paramètre précédent l'ellipse.

  7. #7
    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
    Citation Envoyé par wiztricks Voir le message
    D'après ce que j'ai compris le c_str_printf prend est un printf dans lequel les différents char* ont été remplacés par des c_str.
    Et peut être pas seulement le premier argument => il faut peut être analyser le contenu du fmt pour traiter les éventuels %s comme c_str?
    C'est une des raisons pour laquelle je reprend le développement de ces fonctions car elles sont inachevées et d'ailleurs je ne sais pas encore comment déterminer si un argument de la liste variable est par exemple une chaîne ou un objet C_Str dans quel cas il va falloir accéder à sa chaîne, tout est faisable mais je crois que j'ai un petit problème, je ne sais pas encore comment faire

    Mettre peut-être en place une balise de type %s mais correspondant plutôt à mon objet string (%S ? ) et parcourir la liste tout en en recréant une plus viable (ou réussir à déterminer si on tombe sur %s que l'argument correspondant est une chaîne ou un objet dont lequel il faudra extraire la chaîne) tout en passant cette fois les chaînes des objets au lieu des objets eux-même. Je reste ouvert à toutes suggestions

    Cette solution qui est plutôt sympa du point de vue théorie peut être un peu casse-tête à mettre en place d'autant plus qu'un objet de ce type ne possède pas réellement de type comme si on était en OO à moins d'un tour de force que je ne connais pas

    Citation Envoyé par wiztricks Voir le message
    Pour le reste, je pense comme nicolas.sitbon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          va_start (params, format);  // a-t-on le choix???
    ce qui n'empêche pas de passer le "format->sz_string" à vsxxx
    non?
    -W
    Oui c'était effectivement une grossière erreur de ma part
    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 !

  8. #8
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Pour continuer le débat, je dirais que la seule manière de faire ça de façon portable serait de recoder intégralement les fonctions des familles printf() et scanf(), c'est fastidieux, autant améliorer le travail déjà fournis par les autres, pour ma part j'aime bien la bibliothèque trio, ou si la portabilité n'est pas un soucis mais j'en doute : http://www.gnu.org/s/libc/manual/htm...ng-Printf.html.
    A toi de voir de Franck, j'opterai personnellement pour trio qui reste une implémentation en C ANSI, donc très portable et facilement extensible.
    Cordialement.

  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 : 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
    En fait ma bibliothèque est un petit plaisir perso, je travaille dessus quand j'en ai le temps et l'envie et ca s'arrête là. Bien sûr elle m'a déjà servie et je la diffuse car elle est assez avancée maintenant mais sinon personne n'en aurait connaissance donc travailler sur quelque chose de déjà existant m'est d'aucune utilité
    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
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 726
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 726
    Par défaut
    Il faut que vous arrêtiez les spécifications de l'API sur le point:

    Est-ce que les char* coexistent avec c_str? Dans ce cas, comment les représenter dans un format: %s et %S (ou autre) me semble une bonne idée.

    si un argument de la liste variable est par exemple une chaîne ou un objet C_Str dans quel cas il va falloir accéder à sa chaîne, tout est faisable mais je crois que j'ai un petit problème, je ne sais pas encore comment faire
    Je n'ai pas compris: le format vous donne implicitement le type donc l'argument correspondant au %S doit être de type c_str.

    Mettre peut-être en place une balise de type %s mais correspondant plutôt à mon objet string (%S ? ) et parcourir la liste tout en en recréant une plus viable (ou réussir à déterminer si on tombe sur %s que l'argument correspondant est une chaîne ou un objet dont lequel il faudra extraire la chaîne) tout en passant cette fois les chaînes des objets au lieu des objets eux-même. Je reste ouvert à toutes suggestions
    En poursuivant l'idée précédente, il s'agirait de créer un format et modifier la liste des paramètres pour *printf à partir de ceux reçus par votre API en:
    • détectant et remplaçant %S par %s dans le format de sortie
    • en remplaçant l'argument correspondant à c_str par l'adresse du char* associé

    comme c_str contient la longueur de la chaîne, dommage de ne pas la passer à *printf. => %S se transforme en %*s et l'argument c_str en longueur, adresse du char*

    Cette solution qui est plutôt sympa du point de vue théorie peut être un peu casse-tête à mettre en place d'autant plus qu'un objet de ce type ne possède pas réellement de type comme si on était en OO à moins d'un tour de force que je ne connais pas
    Ben le descripteur qui décrit les c_str est à priori une structure à taille fixe.
    Sur la base de cette propriété vous pourriez vous assurer que l'adresse d'un c_str est effectivement celle d'un c_str de différentes façons:
    • les descripteurs sont alloués dans des segments ou dans une zone mémoire connue
    • les descripteurs sont badgés: vous pourriez ajouter avant et après des champs techniques de type 'int' contenant des constantes style 0xACFB

    vous vous appuyez sur ces informations pour coder la fonction bool is_c_str(void*) qui peut par ailleurs effectuer des tests sur la cohérence des valeurs prises par les champs fonctionnels d'un c_str:
    • la longueur est un entier >= 0 (i.e. le champ est signé) inférieure à ?
    • l'adresse n'est pas dans certaines plages ou est dans...

    Bon courage
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Le problème vient de ce que l'adresse de ton objet C_Str est différente de celle de la chaine encapsulée. Ceci empêche d'utiliser les fonctions sur les chaînes standard pour de tels objets (par exemple ici printf).

    Si on essaye de remédier à cet obstacle, il faut que l'objet contienne la chaîne et non pas simplement son adresse et qu'il soit repéré par l'adresse de cette chaine. La chaine ne peut être que le dernier élément de la structure (sinon on ne saurait pas retrouver simplement les autres champs, puisque la chaine est de longueur variable).

    On obtiendrait une définition du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct _C_Str
    {
       size_t len;
       char sz_string[];
    };
    Les fonctions, au lieu d'utiliser l'adresse d'une telle structure devraient utiliser celle du champ sz_string de la structure.
    Ceci permettrait d'utiliser directement un C_Str là où on peut utiliser une chaine standard.

    Une éventualité qui te fait revoir complètement le code déjà écrit !

  12. #12
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 726
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 726
    Par défaut
    Cher Diogene

    la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct _C_Str
    {
       size_t len;
       char sz_string[];
    };
    signifie que le block mémoire dans lequel est stocké la chaîne de caractère est préfixé par sa longueur.

    Ce type de représentation est nécessaire dans la sérialisation (échanges de messages, enregistrements dans fichiers ou BDD) mais discutable pour la gestion de la mémoire dynamique.

    Ce qui n'interdit pas de le faire, mais généralement on lui préfère:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct _C_Str
    {
       size_t len;
       char* sz_string;
    };
    autrement dit une séparation nette entre descripteur et données représentées par celui-ci.

    Ce qui permet de travailler sur les descripteurs indépendamment des objets représentés style:
    Ajout de marqueurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct _C_Str
    {
       long bom;
       size_t len;
       char* sz_string;
       long eom;
    };
    Une validation en fonction de leur placement dans une zone mémoire prédéfinie.
    Voire une utilisation de mécanisme de protection matériels pour en contrôler l'accès.
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #13
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @wiztricks :
    Ce type de représentation est nécessaire dans la sérialisation (échanges de messages, enregistrements dans fichiers ou BDD) mais discutable pour la gestion de la mémoire dynamique...
    Je tente simplement de proposer une solution au problème posé par Franck.H. Et avoir une sorte de compatibilité entre chaîne et C_Str peut apporter un plus pour l'utilisateur de la bibliothèque.
    Rien n'empêche d'avoir d'autres éléments dans la structure pouvu que le tableau soit en queue.

  14. #14
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 726
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 726
    Par défaut
    Cher diogene,

    Citation Envoyé par diogene Voir le message
    @wiztricks :
    Je tente simplement de proposer une solution au problème posé par Franck.H. Et avoir une sorte de compatibilité entre chaîne et C_Str peut apporter un plus pour l'utilisateur de la bibliothèque.
    Rien n'empêche d'avoir d'autres éléments dans la structure pouvu que le tableau soit en queue.
    Quelle que soit la représentation utilisée, la compatibilité s'obtient en récupérant une adresse dans le 'struct' définissant c_str pour le passer à la fonction de la libc.

    Je vous avoue honnêtement que j'ai peine à voir ce que cela change en passant de l'implémentation actuelle (descripteurs) à une représentation 'sérialisable'.

    Sachez que j'apprécie vos interventions: elles sont pertinentes et très enrichissantes. Et là je suis très frustré, car je ne vois pas trop.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  15. #15
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Ce que je veux dire, c'est qu'avec la structure de données utilisées par Frank, il n'est pas possible d'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    C_Str * str = CreerCString(...);
    printf("%s", str);
    Ce qui je pense était le problème évoqué (il n'est pas possible d'avoir comme argument le champ sz_string puisque C_Str doit être un type opaque)
    Alors qu'avec la manière que j'évoque, ceci fonctionne parfaitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int i = 10;
    const char * mes = "azerty";
    C_Str * str = CreerCString(...);
    ...
    printf("%d%s%s\n",i,str,mes);

  16. #16
    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
    J'avoue que la solution de diogene n'est pas mal mais s'il faut réécrire une grosse partie du code déjà en place c'est pas trop ce que je recherche du point de vue qu'il y a quand même encore 1600+ lignes de code (le fichier en fait 3000+ avec commentaires et espaces).

    Même si la maintenance du code reste bien à faire la réécriture risque de poser problème

    Le premier élément d'une structure à part un pointeur, possède la même adresse que la structure elle-même (même une structure allouée dynamiquement) ? Par rapport à la solution proposée par wiztricks.


    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 !

  17. #17
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Citation Envoyé par diogene Voir le message
    Alors qu'avec la manière que j'évoque, ceci fonctionne parfaitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int i = 10;
    const char * mes = "azerty";
    C_Str * str = CreerCString(...);
    ...
    printf("%d%s%s\n",i,str,mes);
    Je n'est pas trop suivi mais il me semble que ça ne marchera pas, puisque la chaine à l'intérieur de str n'est pas en début de structure. Là tu passes un entier pour le %s du printf.

  18. #18
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    ...mais s'il faut réécrire une grosse partie du code déjà en place c'est pas trop ce que je recherche du point de vue qu'il y a quand même encore 1600+ lignes de code (le fichier en fait 3000+ avec commentaires et espaces)...
    Oui, c'est le problème, on change la structure des données et il faut donc tout revisiter. Il faut donc se poser la question : Est-ce que j'en tire suffisamment d'avantages ? C'est possible ; il faut réfléchir à ce qu'on veut faire ensuite et si l'utilisateur gagne de la souplesse dans l'utilisation des C_Str (J'avoue que personnellement, analyser le format pour modifier les arguments ne me plait pas trop)

    Le premier élément d'une structure à part un pointeur, possède la même adresse que la structure elle-même (même une structure allouée dynamiquement) ?
    Oui, quelque soit le type du premier élément

    matafan :
    Je n'est pas trop suivi mais il me semble que ça ne marchera pas, puisque la chaine à l'intérieur de str n'est pas en début de structure. Là tu passes un entier pour le %s du printf.
    Justement, dans cette éventualité, ce n'est pas l'adresse de la structure qui repère le C_Str , mais celle de son champ sz_string.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ou bien, il faut tricher, comme avec les BSTR: La taille (et cie) est stockée avant le pointeur retourné...

    Code C : 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
    typedef struct C_strBuf
    {
    	char chars[1];
    } C_str;
     
    struct C_strInfo
    {
    	size_t length;
    	...
    	/* dernier membre */
    	struct C_strBuf buf;
    };
     
    /* Fonction internes */
    struct C_strInfo * C_str_alloc(size_t nCharsInBuf)
    {
    	struct C_strInfo *ret;
    	size_t fullSize = offsetof(struct C_strInfo, buf)
    	 + offsetof(struct C_strBuf, chars) /* devrait être zéro */
    	 + nCharsInBuf * sizeof (ret->buf.chars[0])
    	 ;
    	return malloc(fullSize);
    }
     
    /* Fonction de conversion:
       Obtient le pointeur qu'on donne à l'utilisateur,
       compatible avec printf(). */
    C_str * C_str_get_buf(struct C_strInfo *pInfo)
    {
    	return &pInfo->buf;
    }
     
    /* Fonction de conversion:
       À partir du pointeur qu'on donne à l'utilisateur,
       compatible avec printf(),
       retrouve le pointeur de la structure complète */
    struct C_strInfo * C_str_get_info(C_str *pBuf)
    {
    	char *pbyBuf = (char*)pBuf;
    	char *pbyInfo = pbyBuf - offsetof(struct C_strInfo, buf);
    	struct C_strInfo *pInfo = (struct C_strInfo *)pbyInfo;
    	return pInfo;
    }
    Tu peux aussi te passer de la structure C_strBuf et retourner directement un char*, mais je pense que le pointeur C_str* est plus parlant pour l'utilisateur.
    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.

  20. #20
    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
    Citation Envoyé par diogene Voir le message
    Oui, c'est le problème, on change la structure des données et il faut donc tout revisiter. Il faut donc se poser la question : Est-ce que j'en tire suffisamment d'avantages ? C'est possible ; il faut réfléchir à ce qu'on veut faire ensuite et si l'utilisateur gagne de la souplesse dans l'utilisation des C_Str (J'avoue que personnellement, analyser le format pour modifier les arguments ne me plait pas trop)
    Mais avec ta solution exit les allocations dynamique non ? Etant donné que ce n'est plus un pointeur qui permet de stocker la chaîne. La question que je me pose sur cette solution c'est où est donc stockée la chaîne... dans la pile ? Si c'est le cas ca risque de poser des problème lorsque je charge de gros fichiers avec (un exemple parmis d'autres)

    Je sais que modifier certaines arguments de la liste variable fait un peu bricolage d'un certain point de vue mais la solution bon, la solution proposer par wiztricks (mise en place d'une valeur fixe qui sert de borne pouvant déterminer que l'argument est un objet C_Str) est une bonne alternative pour le moment.

    Citation Envoyé par diogene Voir le message
    Oui, quelque soit le type du premier élément
    Est-ce que c'est garantit par la norme ou cela peut changer suivant l'OS ?


    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 !

Discussions similaires

  1. Comportement de printf différent en local et distant
    Par xion1024 dans le forum Langage
    Réponses: 2
    Dernier message: 02/04/2008, 12h05
  2. 2 printf identiques affichent resultats différents
    Par Margatthieu dans le forum C
    Réponses: 6
    Dernier message: 13/01/2008, 13h59
  3. Simulation de transmission de paquet entre différent réseaux
    Par MelloW dans le forum Développement
    Réponses: 2
    Dernier message: 12/07/2002, 19h51
  4. fonction printf
    Par ydeleage dans le forum C
    Réponses: 7
    Dernier message: 30/05/2002, 11h24
  5. Réponses: 2
    Dernier message: 17/05/2002, 20h37

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