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 :

Créer une fonction qui permet l'insertion de variables dans une chaîne à la manière de sprintf


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut Créer une fonction qui permet l'insertion de variables dans une chaîne à la manière de sprintf
    Hello,

    Je chercher le moyen, de la même manière que sprintf, d'avoir la possibilité d'insérer les valeurs de variables multiples dans une chaîne de caractères tel que par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    log_add( "header.h", "function.c", "T0 :: x = %zu > p_sz", x);
    Je suis allé regarder le code de sprintf mais ça semble coton quand on commence à aller voir les autres fonctions appelées.

    En gros, j'ai essayé de faire ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char* test( const char* format, ...)
    {
      va_list arg;
      int done;
      va_start (arg, format);
      char *s = NULL;
      done = __vsprintf_internal (s, -1, format, arg, 0);
      va_end (arg);
      return s;
    }
    Le truc c'est que le compilo ne trouve pas la définition__vsprintf_internal qui semble déclarée dans libioP.h qui malgré l'inclusion n'est pas trouvé également.
    J'ai chopé le header en question mais le problème se cascade avec d'autres headers xD. Plutôt prévisible.

    Une idée ou une autre façon pour m'en sortir plus simplement ?

    Merci d'avance.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  2. #2
    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 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Pourquoi recoder une fonction qui ferait le même travail ? Pourquoi ne pas utiliser snprintf() en interne ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut
    Tout simplement parce que je ne vois pas comment je peux arriver à ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    log_add( "header.h", "function.c", "T0 :: x = %zu > p_sz, i = %d", x, i);
    avec snprintf.

    J'ai besoin que ma fonction ait pour forme ce prototype :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void log_add( const char* hea, const char* fun, const char* msg, ... );
    Je veux bien utiliser snprintf mais je ne vois pas comment l'utiliser pour répondre à mon besoin dans ce cas.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  4. #4
    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 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Quelle est la sortie attendue de ta fonction ? Tu peux donner un exemple d'utilisation ?

    Perso, j'ai déjà fait un logger en C++ (lightweight sur embarqué) qui utilisait du snprintf() en interne, c'est pour que je propose d'aller dans cette direction si c'est possible

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Les fonctions de logging sont souvent des macros pour pouvoir avoir des variadic macro, embarquer des infos supplémentaires comme le nom du fichier, la ligne, ...
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut
    Actuellement, j'ai ceci pour logger les erreurs ou tout du moins signaler un comportement suspect :

    Je déclare une variable f_log en variable globale dans le main pour pouvoir l'exploiter. Je sais ce que vous pensez des variables globales, n'en dites pas plus =)

    log.c
    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
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include "log.h"
     
    log_t* f_log;
     
    static size_t str_length( const char* p )
    {
        size_t sz = 0;
        if ( p )
            while ( *p != '\0' )
                p++, sz++;
     
        return sz;
    }
     
    static char* str_copy( const char* p )
    {
        char* p_out = NULL;
        if ( p )
        {
            size_t p_sz = 0;
            if ( ( p_sz = str_length(p) ) > 0 )
            {
                if ( ( p_out = malloc( (p_sz+1)*sizeof(*p_out) ) ) )
                {
                    size_t i;
                    for ( i = 0 ; i< p_sz ; i++ )
                        p_out[i] = p[i];
     
                    p_out[i] = '\0';
                }
            }
            else
            {
                if ( ( p_out = malloc( (p_sz+1)*sizeof(*p_out) ) ) )
                    p_out[0] = '\0';
            }
        }
        return p_out;
    }
     
    log_t* log_create( void )
    {
        log_t* p = NULL;
        if ( ( p = malloc( sizeof(*p) ) ) )
        {
            p->hea = NULL;
            p->fun = NULL;
            p->msg = NULL;
            p->sz = 0;
        }
        return p;
    }
     
    void log_destroy( log_t** p )
    {
        if ( p )
        {
            if ( (*p)->hea && (*p)->fun && (*p)->msg )
            {
                for ( size_t i=0 ; i<(*p)->sz ; i++ )
                {
                    if ( (*p)->hea[i] )
                        free( (*p)->hea[i] );
     
                    if ( (*p)->fun[i] )
                        free( (*p)->fun[i] );
     
                    if ( (*p)->msg[i] )
                        free( (*p)->msg[i] );
                }
                free( (*p)->hea );
                free( (*p)->fun );
                free( (*p)->msg );
            }
            free( (*p) );
        }
    }
     
    bool log_add( const char* hea, const char* fun, const char* msg )
    {
        bool c = false;
        if ( hea && fun && msg )
        {
            log_t* a = NULL; //Testing pointer for the reallocation of f_log
            if ( f_log )
            {
                a = f_log; size_t sz_new = a->sz+1;
                char** b = NULL; //Testing pointer for reallocation of the string
                if ( ( b = realloc( (a->hea), sz_new*sizeof( *a ) ) ) )
                {
                    a->hea = b;
                    if ( ( a->hea[sz_new-1] = str_copy(hea) ) )
                    {
                        if ( ( b = realloc( (a->fun), sz_new*sizeof( *a ) ) ) )
                        {
                            a->fun = b;
                            if ( ( a->fun[sz_new-1] = str_copy(fun) ) )
                            {
                                if ( ( b = realloc( (a->msg), sz_new*sizeof( *a ) ) ) )
                                {
                                    a->msg = b;
                                    if ( ( a->msg[sz_new-1] = str_copy(msg) ) )
                                    {
                                        a->sz = sz_new;
                                        f_log = a;
                                        c = true;
                                    }
                                }
                                else log_destroy(&a);
                            }
                            else log_destroy(&a);
                        }
                        else log_destroy(&a);
                    }
                    else log_destroy(&a);
                }
                else log_destroy(&a);
            }
            else log_destroy(&a);
        }
        return c;
    }
     
    void log_display( log_t* p )
    {
        if ( p )
        {
            for ( size_t i=0 ; i<p->sz ; i++ )
                printf("\n%20s - %20s - %50s", p->hea[i], p->fun[i], p->msg[i]);
        }
    }
    log.h
    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
    #ifndef LOG_H
    #define LOG_H
     
    typedef struct
    {
        char** hea;
        char** fun;
        char** msg;
        size_t sz;
    }log_t;
     
    extern log_t* f_log;
     
    log_t* log_create  ( void );
    void   log_destroy ( log_t** p );
    void   log_display ( log_t* p );
    bool   log_add     ( const char* hea, const char* fun, const char* msg );
     
    #endif
    Exemple d'utilisation dans une fonction :

    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
     
    i_2D_t* i_2D_create( size_t x, size_t** y  )
    {
        i_2D_t* st = NULL;
        if ( ( st = malloc( sizeof( *st ) ) ) ) //T0
        {
            if ( x > 0 )
            {
                if ( ( st->da = i_2D_create_( x, y ) ) ) //T1
                {
                    st->y = (*y);
                    st->x =   x ;
                    bool s0 = false; bool s1 = false;
                    if ( !((s0 = sz_search_limit( st->y, x, &st->y_min, 0 )) && (s1 = sz_search_limit( st->y, x, &st->y_max, 1 ))) ) //T2
                    {
                        if ( !s0 ) { log_add("ptr.h", "i_2D_create", "T2 :: s0 = false"); }
                        if ( !s1 ) { log_add("ptr.h", "i_2D_create", "T2 :: s1 = false"); }
                        i_2D_destroy( &st );
                    }
                }
                else
                {
                    log_add("ptr.h", "i_2D_create", "T1 :: st->da is NULL");
                    i_2D_destroy( &st );
                }
            }
            else
            {
                st->da = NULL;
                st->y  = NULL;
                st->x  =    0;
                st->y_min = 0;
                st->y_max = 0;
            }
        }
        else log_add("ptr.h", "i_2D_create", "T0 :: st is NULL");
        return st;
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  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 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par darkwall_37 Voir le message
    Je sais ce que vous pensez des variables globales, n'en dites pas plus =)
    Ce n'est pas que nous. Je crois que c'est une idée répandue chez tous les dev du monde que global = emmerdements en cascade.

    Toutefois on ne te reprochera jamais d'utiliser une globale si tu dis "ok je sais que c'est la merde mais j'y ai bien réfléchi et je pense qu'on ne peut pas faire autrement". D'autant plus que si tu ne peux pas les éviter, tu peux au-moins limiter les emmerdements qui y sont liés.

    Quels sont réellement les défauts qu'on reproche aux globales ? Grosso-modo il n'y en a que deux:
    1) si la globale part en couilles, impossible de déterminer assez facilement qui l'a modifiée. En effet, toutes les fonctions y ont accès sans avoir besoin de la déclarer. On ne peut pas balayer le code et voir d'un coup d'oeuil qui y accèdera ou pas. Accessoirement c'est aussi un reproche qu'on peut éventuellement faire au C99 qui autorise désormais la définitions de variables n'importe où dans un bloc par opposition au C traditionnel qui imposait toutes les variables en début de bloc ce qui aidait là aussi à avoir une vue d'ensemble mais bon, c'est probablement moins grave car en début de bloc ou pas, les variables locales sont limitées à la fonction donc en général on les retrouve plus facilement (c'est d'ailleurs probablement la réflexion qu'ont dû se faire ceux qui ont été à l'origine de la modif) donc bon, on peut oublier ce détail.
    2) si on crée une locale qui porte le même nom, on se prive de l'accès à la globale

    Comment éviter ces soucis des globales ? ben tout simplement en déclarant la globale dans les fonctions qui l'utilisent. Ce n'est pas nécessaire mais ce n'est pas interdit non plus. En déclarant dans la fonction la globale en extern on la montre non pas au compilo (ok on la lui montre aussi mais lui il s'en fout il la connaissait déjà) mais surtout aux autres lecteurs du code. Et en la déclarant dans la fonction, on ne court pas le risque d'en déclarer une autre du même nom.

    Donc pour ton log.c:

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    log_t* f_log;
    bool log_add( const char* hea, const char* fun, const char* msg )
    {
        extern log_t* f_log;
        ...
    }

    Citation Envoyé par darkwall_37 Voir le message
    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
    static char* str_copy( const char* p )
    {
        char* p_out = NULL;
        if ( p )
        {
            size_t p_sz = 0;
            if ( ( p_sz = str_length(p) ) > 0 )
            {
                if ( ( p_out = malloc( (p_sz+1)*sizeof(*p_out) ) ) )
                {
                    size_t i;
                    for ( i = 0 ; i< p_sz ; i++ )
                        p_out[i] = p[i];
     
                    p_out[i] = '\0';
                }
            }
            else
            {
                if ( ( p_out = malloc( (p_sz+1)*sizeof(*p_out) ) ) )
                    p_out[0] = '\0';
            }
        }
        return p_out;
    }
    Mis à part que je ne comprends pas pourquoi tu clones strdup() (ni pourquoi tu clones aussi strlen()), si tu réfléchis bien tu verras que tester p_sz > 0 ou pas est totalement inutile. Et si tu inverses le tout premier test qui vérifie "p", tu peux lui faire alors retourner NULL directement et gagner un niveau d'indentation pour le reste de la fonction.
    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
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut
    Je clone pour me réapproprier adapter à mon besoin et dans le cas de malloc(0), il y a des cas ou celui ci ne renvoi pas NULL. Pourquoi ? Bonne question, j'ai tenté de me renseigner et après différentes lecture, je préfère m'affranchir de cette possibilité car c'est un comportement indésirable. Même s'il faut faire un test supplémentaire. Je pense que ce sont des ennuis en moins. De plus, à mon sens, malloc(0) ne veut rien dire et ne devrait pas être possible.

    Merci pour la correction du placement de la variable f_log avec l'utilisation d'extern.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    et dans le cas de malloc(0), il y a des cas ou celui ci ne renvoi pas NULL. Pourquoi ? Bonne question, j'ai tenté de me renseigner et après différentes lecture, je préfère m'affranchir de cette possibilité car c'est un comportement indésirable. Même s'il faut faire un test supplémentaire.
    J'ai bien précisé "si tu réfléchis bien" !!!

    Déjà quand p_sz vaut 0 tu fais un malloc de 1, pas de 0 (et c'est compréhensible vu que tu vas quand-même y mettre '\0').
    Plus globalement, dans les deux cas ton malloc est strictement identique. Donc avoir deux instructions identiques dans le "if" et dans le "else" implique qu'on les sorte du if/else.
    Ensuite la boucle de recopie de de "p" dans "p_out" va de 0 à p_sz exclu donc si p_sz vaut 0, cette boucle ne se fera pas donc "i" restera à 0 donc p_out[i]='\0' sera identique à p_out[0]='\0' donc là aussi on peut sortir cette instruction des deux parties de l'alternative.
    Donc bref tu peux virer carrément le test entier, le résultat sera le même.

    Citation Envoyé par darkwall_37 Voir le message
    Même s'il faut faire un test supplémentaire. Je pense que ce sont des ennuis en moins.
    simple is better than complex (philosophie Python mais qui pourrait avoir sa place ici). Un test inutile c'est du code en plus inutile, du temps de compilation inutile et de la lecture inutile quand on veut détailler ce qui se passe. Rien que ça ça ne peut pas entrainer des ennuis en moins. Ce sera au mieux des ennuis pareil que sans test et au pire des ennuis en plus...
    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]

  10. #10
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut
    Effectivement, je te l'accorde ici, c'est inutile.
    Ceci fait bien la même chose.
    Je n'exclue pas qu'il y ait effectivement des redondances du genre.
    Je n'ai pas vraiment pris le temps de repasser sur ces fonctions pour optimiser ce qu'il y a éventuellement à optimiser.
    C'est effectivement une erreur de factorisation, pour autant le code n'est pas "cassé" et ça fera partie de l'optimisation post "production".
    Il doit y en avoir d'autres... ^^


    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
     
    static char* str_copy( const char* p )
    {
        char* p_out = NULL;
        if ( p )
        {
            size_t p_sz = 0;
            if ( ( p_out = malloc( ++p_sz*sizeof(*p_out) ) ) )
            {
                for ( size_t i=0 ; i<p_sz ; i++ )
                    p_out[i] = p[i];
     
                p_out[i] = '\0';
            }
        }
        return p_out;
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par darkwall_37 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
    13
    14
    15
    16
    static char* str_copy( const char* p )
    {
        char* p_out = NULL;
        if ( p )
        {
            size_t p_sz = 0;
            if ( ( p_out = malloc( ++p_sz*sizeof(*p_out) ) ) )
            {
                for ( size_t i=0 ; i<p_sz ; i++ )
                    p_out[i] = p[i];
     
                p_out[i] = '\0';
            }
        }
        return p_out;
    }
    Là ça ne va plus du tout. Je t'ai dit que le test était inutile, pas que p_sz l'était !!!

    Donc là maintenant p_sz est toujours à 0 puis il passe à 1 (même si la chaine d'origine est vide ou qu'elle contient 500c !!!). Tu fais donc un malloc de 1 puis tu copies cet unique octet dans p_out puis tu rajoutes '\0' dans p_out[1] (p_out a été alloué à 1 donc ses indices sont [0] uniquement).

    Bref exemple raté d'une factorisation où il y avait juste à supprimer le test p_sz > 0 et la partie "else".
    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]

  12. #12
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut
    Au temps pour moi!

    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
     
    static char* str_copy( const char* p )
    {
        char* p_out = NULL;
        if ( p )
        {
            size_t p_sz = str_length( p );
            if ( ( p_out = malloc( (p_sz+1)*sizeof(*p_out) ) ) )
            {
                size_t i;
                for ( i=0 ; i<p_sz ; i++ )
                    p_out[i] = p[i];
     
                p_out[i] = '\0';
            }
        }
        return p_out;
    }
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  13. #13
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Mouais. Le ++p_sz est bien pensé mais malheureusement tu l'exploites mal et associé à ce p_out[i]='\0' final ça provoque une monumentale erreur. C'est dommage.
    Imaginons une chaine de 10c (donc 10c + le '\0'). Donc p_sz passe à 11 et tu alloues 11 (ok). Puis tu boucles sur i de 0 inclus à 11 exclu (donc de 0 à 10 ok) mais en fin de boucle, n'oublie pas que i est passé à 11.
    Puis tu remplis p_out[11] avec '\0' (rappel il a été alloué à 11 donc ses indices s'arrêtent à 10 et en plus avec l'instruction p_out[10]=p[10] tu as déjà copié le '\0'). Dommage, c'est l'instruction inutile de ta fonction et qui détruit tout.

    Sinon tu peux utiliser pleinement les pointeurs pour éviter les indirections (perso je pense que ça ralenti le code alors que d'autres ici disent que les optimisations du compilateur peuvent rattrapper ça mais bon, si on veut éviter d'avoir à se poser ces questions...)

    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
    static char* str_copy( const char* p ) {
     
        if ( p == NULL) return NULL;
     
        char* p_out;
        if ( ( p_out = malloc(str_length(p) + 1) * sizeof(*p_out) ) ) )  {
            char *tmp=p_out;
            while (1) {
                    *tmp = *p;
                    if (*p == '\0') break;
                    p++;
                    tmp++;
            }
        }
        return p_out;
    }
    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]

  14. #14
    Membre confirmé
    Homme Profil pro
    Etudiant administrateur systèmes et réseaux
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Etudiant administrateur systèmes et réseaux

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 467
    Points
    467
    Par défaut
    Oui je me suis rendu compte de ma connerie après avoir validé le post.
    Pas concentré dans le train et sur le tel, les deux mélangés, j'y suis plus ^^


    Merci pour l'opti du code !
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

Discussions similaires

  1. [XL-2013] Créer une fonction qui permet de compter des données complexe.
    Par RabiK33 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 06/04/2016, 11h58
  2. Réponses: 1
    Dernier message: 19/05/2015, 12h21
  3. Réponses: 3
    Dernier message: 23/05/2012, 15h03
  4. fonction qui permet de vérifier qu'une chaine est un double
    Par celiaaa dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 20/12/2006, 13h35
  5. cherche une fonction qui permet de faire une recherche
    Par vbcasimir dans le forum Langage
    Réponses: 7
    Dernier message: 01/09/2005, 17h24

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