Discussion: '0' == '\0' ?

  1. #1
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    mars 2009
    Messages
    513
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : mars 2009
    Messages : 513
    Points : 364
    Points
    364
    Billets dans le blog
    3

    Par défaut '0' == '\0' ?

    Bonjour à tous ,
    je voudrais savoir si le fait de remplir une chaîne de caractère par des '0' empêche la fonction printf()
    d'afficher la chaîne entière et l'oblige à n'afficher qu'un seul "0" ,prenant les autres pour des fins de chaîne ('\0') ?

  2. #2
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 369
    Points : 23 006
    Points
    23 006

    Par défaut

    Quelle est la question ?
    '0' n'a rien à voir avec \0, le premier est le caractère 0, le nombre 0, le second est le caractère null, de fin de chaîne.
    printf comme la majorité des fonctions C de traitement de chaînes de caractères s'arrêtera au premier \0.
    Initialiser une chaîne avec des \0 peut être une bonne pratique et éviter des déboires.
    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.

  3. #3
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    mars 2009
    Messages
    513
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : mars 2009
    Messages : 513
    Points : 364
    Points
    364
    Billets dans le blog
    3

    Par défaut

    Ok ,
    J'ai une routine de codage de chaîne de caractères composée de '0' et '1' :
    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
     
    char *codage(char *clairBin) {
        int i,j,cle,binSize,pas;
        char *codon,*codeBin,*codeLimit;
        //
        binSize = strlen(clairBin);
        cle = (binSize/8);
        pas = cle-1;
        //
        codon = malloc(cle+1);
        codon[cle] = '\0';
        //
        codeBin = malloc(binSize+1);
        codeBin[binSize] = '\0';
        for(i=0;i<8;i++) {
            j = 0;
            strncpy(codon,clairBin+(i*cle),cle);
            printf("codon %d : %s\n",i,codon);
            codeLimit = codeBin+((i*cle)+pas);
            //printf("codeLimit = %u\n",codeLimit);
            while(j < cle) {
                switch (codon[j]) {
                    case '0':
                        //printf("%c",codon[j]);
                        codeBin[(i*cle)+j] = codon[j];
                        j++;
                        if(j < cle) {
                            //printf("-%c",codon[j]);
                            *codeLimit = codon[j];
                            codeLimit--;
                            j++;
                        }
                        break;
     
                    default:// '1'
                        //printf("%c",codon[j]);
                        codeBin[(i*cle)+j] = codon[j];
                        j++;
                        break;
                }
            }
        }
        printf("\ncodeBin : %s\n",codeBin);
        return codeBin;
    }
    Le problème c'est que la variable codeBin ne semble contenir qu'un unique caractère alors qu"elle "devrait" être aussi
    longue que la chaîne paramètre de la fonction .
    Est-ce que quelqu'un voit quelque chose car je ne vois plus rien !!!

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    6 407
    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 : 6 407
    Points : 17 901
    Points
    17 901
    Billets dans le blog
    1

    Par défaut

    Bonjour
    Citation Envoyé par exe2bin Voir le message
    Est-ce que qq voit qq chose car je ne voit plus rien !!!
    Me semble déjà que "cle" devrait être plus longue de 1 à cause de la perte dans la division (ben oui, si la chaine d'origine est longue par exemple de 4, alors "cle" vaudra 0 ce qui n'est pas tiptop pour une zone mémoire à réserver). En fait, la bonne formule devrait être cle=(binSize-1)/8 + 1.
    De plus tes strncpy(codon,clairBin+(i*cle),cle)) réécrasent à chaque fois le contenu de "codon". Tu ne pensais pas plutôt à strncat() ???
    Quoi qu'il arrive, fais attention car ces fonctions arrêtent la copie soit quand la fin de la chaine à copier est atteinte ; soit quand elles ont copié "n" caractères. Mais dans ce dernier cas, elles ne positionnent pas de '\0'.

    Citation Envoyé par exe2bin Voir le message
    je voudrais savoir si le fait de remplir une chaîne de caractère par des '0' empêche la fonction printf() d'afficher la chaîne entière et l'oblige à n'afficher qu'un seul "0" ,prenant les autres pour des fins de chaîne ('\0') ?
    printf() n'affiche jamais de '\0' (ni plusieurs, ni même un seul). De plus, elle ne peut pas prendre "les autres" pour des fins de chaine puisqu'elle s'arrête au premier (elle ne verra donc pas "les autres"). Et même pire, si elle continuait après le premier '\0' rencontré pour regarder ce qu'il y a après, comment saurait-elle alors où s'arrêter ???
    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

  5. #5
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    mars 2009
    Messages
    513
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : mars 2009
    Messages : 513
    Points : 364
    Points
    364
    Billets dans le blog
    3

    Par défaut

    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Me semble déjà que "cle" devrait être plus longue de 1 à cause de la perte dans la division (ben oui, si la chaine d'origine est longue par exemple de 4, alors "cle" vaudra 0 ce qui n'est pas tiptop pour une zone mémoire à réserver). En fait, la bonne formule devrait être cle=(binSize-1)/8 + 1.
    De plus tes strncpy(codon,clairBin+(i*cle),cle)) réécrasent à chaque fois le contenu de "codon". Tu ne pensais pas plutôt à strncat() ???
    Quoi qu'il arrive, fais attention car ces fonctions arrêtent la copie soit quand la fin de la chaine à copier est atteinte ; soit quand elles ont copié "n" caractères. Mais dans ce dernier cas, elles ne positionnent pas de '\0'.
    Exact ,mais le truc (pour l'instant ) c'est que aucunes chaîne parvenant à la fonction n'est plus petite que 24 caractères et qq soient leur nombre
    ils sont toujours multiples de 8.
    codon est effectivement écrasé à chaque tour de boucle et cela est bien car son contenu n'a plus d'importance une fois traité.
    Citation Envoyé par Sve@r Voir le message
    printf() n'affiche jamais de '\0' (ni plusieurs, ni même un seul). De plus, elle ne peut pas prendre "les autres" pour des fins de chaine puisqu'elle s'arrête au premier (elle ne verra donc pas "les autres"). Et même pire, si elle continuait après le premier '\0' rencontré pour regarder ce qu'il y a après, comment saurait-elle alors où s'arrêter ???
    As-tu essayé la fonction et si oui peux tu dire pourquoi la chaîne finale contient un seul caractère ?

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    6 407
    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 : 6 407
    Points : 17 901
    Points
    17 901
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par exe2bin Voir le message
    et qq soient leur nombre ils sont toujours multiples de 8.
    Ok. Ta formule fonctionne donc pour ce cas particulier. Mais la mienne fonctionne pour tous les cas...

    Citation Envoyé par exe2bin Voir le message
    codon est effectivement écrasé à chaque tour de boucle et cela est bien car son contenu n'a plus d'importance une fois traité.
    Ok

    Citation Envoyé par exe2bin Voir le message
    As-tu essayé la fonction et si oui peux tu dire pourquoi la chaîne finale contient un seul caractère ?
    Je te sens un peu aggressif. Pourtant j'ai fait des efforts (et je pensais que tu me connaissais un peu là dessus). J'ai effectivement essayé mais ne sachant pas à l'origine tes entrées à 24c, j'avais mis "toto". Et après avoir remplacé ta formule par la mienne ; et remplacé strncpy() par strncat(), j'ai vu "codon" se remplir au fur et à mesure et "codeBin" contenait bien "toto". Donc pour moi c'était bon. C'est pas ma faute si ça ne fonctionne pas.

    Effectivement en mettant "000011110000111100001111" (soit 24 caractères) je n'en ai plus qu'un seul en final. Mais en mettant "abcdefghijklmnopqrstuvwx" ça me ressort tout correctement. Le souci vient donc de la chaine entrée et de son traitement. Et en mettant "111111111111111111111111" ça me ressort aussi tout correctement.
    Accessoirement, pour plus de précision, "codeBin" ne contient pas qu'un seul caractère. Il en contient plein. Si tu n'en vois qu'un seul, c'est parce que le second vaut '\0' et que printf() s'arrête alors à cette valeur.

    Je fais donc quelques essais (à ta place). Avec 8 ou 16 "0" ça va mais avec 24 ou 32 ça ne va plus. Là, je commence à penser au comportement indéterminé surtout avec ton j++ qui se fait tantôt une fois, tantôt deux fois ; et ce codelimit-- lui aussi un peu erratique. Mais c'est certainement de ma faute si je ne comprends pas ce que tu fais car j'ai qu'à lire les nombreux commentaires de ton algo...

    Je laisse ton printf("codon %d : %s\n",i,codon) mais je rajoute printf("i=%d, codon[%d]=%d\n",i, j, codon[j]) juste avant le switch() et printf("i=%d, j=%d, codeBin[%d]=%d\n",i, j, i*cle+j, codeBin[i*cle+j]) juste après et voici ce que ça me sort à l'écran (pour une chaine contenant 24 "0")
    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
    moi@virtualux:/tmp$ make a
    cc     a.c   -o a
    moi@virtualux:/tmp$ ./a
    cle=3
    codon 0 : 000
    i=0, codon[0]=48
    i=0, j=2, codeBin[2]=48
    i=0, codon[2]=48
    i=0, j=3, codeBin[3]=0
    codon 1 : 000
    i=1, codon[0]=48
    i=1, j=2, codeBin[5]=48
    i=1, codon[2]=48
    i=1, j=3, codeBin[6]=0
    codon 2 : 000
    i=2, codon[0]=48
    i=2, j=2, codeBin[8]=48
    i=2, codon[2]=48
    i=2, j=3, codeBin[9]=0
    codon 3 : 000
    i=3, codon[0]=48
    i=3, j=2, codeBin[11]=48
    i=3, codon[2]=48
    i=3, j=3, codeBin[12]=0
    ...etc etc jusqu'à i=7 et j=24...
    codeBin : 0
    x=0
    Donc que remarque-t-on ? Au premier tour de boucle tu remplis codeBin[2]. Mais que contient codeBin[0] et codeBin[1] ??? Et ensuite à chaque tour de boucle chaque codeBin[x] (avec x multiple de 3) vaut 0. Or la valeur 0 (qu'on peut aussi représenter par le caractère '\0') est la valeur qui indique "fin de chaine". Donc toute fonction qui lira ta chaine s'arrêtera au premier 0 (ou '\0') rencontré. Et qu'il se trouve que déjà ce 0 (ou '\0') est positionné au 3° caractère (donc quoi qu'il y ait après printf() n'en lira jamais plus de 2) mais qu'en plus comme tu n'as rien indiqué concernant les deux premiers, il se trouve que cette zone mémoire (qui contient alors n'importe quoi) contient alors ici spécialement (pasdbol) un caractère '\0' et au final donc tu n'en vois plus qu'un seul...

    Citation Envoyé par exe2bin Voir le message
    Est-ce que qq voit qq chose car je ne voit plus rien !!!
    Je pense que tu devrais revoir intégralement ton algo. Ou nous expliquer ce que tu cherches à faire. Surtout avec ce codeLimit qui vient en plus interférer dans le truc...
    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

  7. #7
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    mars 2009
    Messages
    513
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : mars 2009
    Messages : 513
    Points : 364
    Points
    364
    Billets dans le blog
    3

    Par défaut

    Citation Envoyé par Sve@r Voir le message
    Je te sens un peu aggressif. Pourtant j'ai fait des efforts (et je pensais que tu me connaissais un peu là dessus).
    Je m'excuse si j'ai pu te faire penser cela ; ta réputation n'est certes pas à faire sur ce forum et je m'en voudrais
    de te manquer de respect.
    Citation Envoyé par Sve@r Voir le message
    Mais c'est certainement de ma faute si je ne comprends pas ce que tu fais car j'ai qu'à lire les nombreux commentaires de ton algo...
    C'est effectivement de la mienne et j'ajoute que je l'ai un peu fait exprès car je ne tiens pas à renseigner ce code
    que je souhaite obscurcir davantage !
    Citation Envoyé par Sve@r Voir le message
    Donc que remarque-t-on ? Au premier tour de boucle tu remplis codeBin[2]. Mais que contient codeBin[0] et codeBin[1] ??? Et ensuite à chaque tour de boucle chaque codeBin[x] (avec x multiple de 3) vaut 0. Or la valeur 0 (qu'on peut aussi représenter par le caractère '\0') est la valeur qui indique "fin de chaine". Donc toute fonction qui lira ta chaine s'arrêtera au premier 0 (ou '\0') rencontré. Et qu'il se trouve que déjà ce 0 (ou '\0') est positionné au 3° caractère (donc quoi qu'il y ait après printf() n'en lira jamais plus de 2) mais qu'en plus comme tu n'as rien indiqué concernant les deux premiers, il se trouve que cette zone mémoire (qui contient alors n'importe quoi) contient alors ici spécialement (pasdbol) un caractère '\0' et au final donc tu n'en vois plus qu'un seul...
    Là tu m'épates !!!!
    Tes réflexions sont si profondes que tu arrives toujours à mettre le doigt où ça cloche avec les mots
    et la pédagogie qui conviennent.

    Encore merci Sve@r

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    6 407
    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 : 6 407
    Points : 17 901
    Points
    17 901
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par exe2bin Voir le message
    Je m'excuse si j'ai pu te faire penser cela ; ta réputation n'est certes pas à faire sur ce forum et je m'en voudrais de te manquer de respect.
    Bah, ça peut arriver. Et puis parfois moi aussi j'agace certains intervenants selon ma façon de leur répondre...

    Citation Envoyé par exe2bin Voir le message
    JC'est effectivement de la mienne et j'ajoute que je l'ai un peu fait exprès car je ne tiens pas à renseigner ce code que je souhaite obscurcir davantage !
    Tu y es déjà bien arrivé car il t'a obscurci toi aussi. Ce que je te conseille toutefois c'est de commencer par écrire un code simple qui fonctionne puis ensuite seulement de l'obscurcir. Ceci dit, la sécurité d'un protocole ne se fait généralement pas en obfusquant son code source mais plutôt dans sa complexité mathématique. Pour exemple j'ai eu en main le premier source de la fonction "password()" qui permet de générer un mot chiffré à partir d'un mot de passe en clair et qui était utilisée par les premiers Unix (ceux qui chiffraient sur 8 caractères). Ben j'ai jamais su l'inverser. Il y avait des rotations de matrices etc etc c'était horrible.
    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

  9. #9
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    mars 2009
    Messages
    513
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : mars 2009
    Messages : 513
    Points : 364
    Points
    364
    Billets dans le blog
    3

    Par défaut

    Citation Envoyé par Sve@r Voir le message
    Tu y es déjà bien arrivé car il t'a obscurci toi aussi. Ce que je te conseille toutefois c'est de commencer par écrire un code simple qui fonctionne puis ensuite seulement de l'obscurcir. Ceci dit, la sécurité d'un protocole ne se fait généralement pas en obfusquant son code source mais plutôt dans sa complexité mathématique. Pour exemple j'ai eu en main le premier source de la fonction "password()" qui permet de générer un mot chiffré à partir d'un mot de passe en clair et qui était utilisée par les premiers Unix (ceux qui chiffraient sur 8 caractères). Ben j'ai jamais su l'inverser. Il y avait des rotations de matrices etc etc c'était horrible.
    Tu as raison et je suis entièrement d'accord en ce qui concerne le domaine de la cryptographie à clés publiques qui utilise
    des algorithme mathématiques à sens unique ; par contre ,dans la branche à clés privées ,les algorithmes eux-mêmes
    sont les clés et par conséquent il convient de ne pas les divulgués ou de les rendre très difficiles à comprendre (ton
    exemple fait foi) .
    Cela dit en toute modestie car je ne me prétend pas capable d'écrire de tels algorithmes résistants aux tentatives
    de déchiffrement

+ Répondre à la discussion
Cette discussion est résolue.

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