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

  1. #1
    Candidat au Club
    traitement sur une chaîne, votre aide souhaitée !
    Bonjour à tous .

    Bon ben ces temps-ci, à part se prendre la tête avec nos petits programmes que faire d'autre ?

    Je suis nul en C, je sollicite votre aide pour ce petit programme dont je souhaite qu'il puisse extraire les 6
    derniers caractères d'une adresse MAC sans les ':'. J'ai tenté des sscanf et autres fonctions de traitement des
    chaines mais sans succès. Le programme suivant affiche pour le moment:

    08:60:6e:8c:2a:c7
    08606e8c2ac7

    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
     
    int main()
    {
        FILE* fichier = NULL;
        char chaine[100] = "";
        fichier = fopen("/sys/class/net/enp2s0/address", "r");
     
            if (fichier != NULL)
                {
                        while (fgets(chaine, 100, fichier) != NULL)
                        {
               printf("%s", chaine);
     
               char *p = strtok(chaine, ":");
                          while(p != NULL)
                          {
                                printf("%s", p);
                                p = strtok(NULL, ":");
                            }
                    }
     
                                fclose(fichier);
                                            }
     
    }

  2. #2
    Membre confirmé
    bonjour

    donc tu souhaites obtenir "8c2ac7" ?

    - soit tu commences à traiter ta chaine à 8c :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *c;
    c = chaine;
    c += 9; // pour sauter 08:60:6e:
    // ensuite tu fais tes traitements sur c


    - soit à la fin de ton traitement, tu affiches les 6 derniers
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *c = ta_chaine_resultat;   // car chaine est modifiée par strtok; donc tu dois construire ta_chaine_resultat
    while (*c) c++;
    c -= 6; // récupérer les 6 derniers caractères
    // tu affiches c



    par contre, pour le pseudo code donné ci-dessus, il faut bien tester les longueurs de chaine (= je ne vérifie pas la structure de ton adresse mac, je suppose qu'elle est correcte)

  3. #3
    Rédacteur/Modérateur

    Avec ton format fixe le sscanf est sans doute le plus simple.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const char* mac = "08:60:6e:8c:2a:c7";
    char a[3], b[3], c[3], d[3], e[3], f[3];
    sscanf(mac, "%2s:%2s:%2s:%2s:%2s:%2s", a, b, c, d, e, f);
    printf("%s%s%s%s%s%s", a, b, c, d, e, f);

    Tu peux aussi faire un remove des : dans la chaîne d'origine.
    Un truc du genre
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void remove_char(char* src, char toRemove)
    {
      const int total_length = strlen(src);
      while (char* found = strchr(src, toRemove))
      {
        const int chars_before = found - src;
        const int length_after_char = total_length - chars_before;
        memmove(found, found + 1, length_after_char + 1); // Ajoute 1 pour garder le \0
      }
    }
    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.

  4. #4
    Candidat au Club
    Bonjour,

    Oui c'est exactement cela, du coup j'obtiens:
    08:60:6e:8c:2a:c7
    8c:2a:c7
    8c2ac7

    avec =>
    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
     
     
    int main()
    {
        FILE* fichier = NULL;
        char chaine[100] = "";
        char souschaine[100];
        fichier = fopen("/sys/class/net/enp2s0/address", "r");
        if (fichier != NULL)
                {
                        while (fgets(chaine, 100, fichier) != NULL)
                        {
               printf("%s", chaine );
                                char *c;
                                c = chaine;
                                c += 9;
                                printf("%s", c);
     
               char *p = strtok(c, ":");
                          while(p != NULL)
                          {
                                printf("%s", p);
                                p = strtok(NULL, ":");
                            }
                    }
     
                                fclose(fichier);
                                            }
     
    }


    J'aimerai associer ce résultat à une variable pour la traiter plus loin dans le programme, j'utilise sprintf ?

  5. #5
    Candidat au Club
    Merci pour ta réponse, cela me donne le code suivant qui effectivement me permet de stocker
    les valeurs dans les variables a, b, 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
     
     
    if (fichier != NULL)
                {
                        while (fgets(chaine, 100, fichier) != NULL)
                        {
                                printf("%s", chaine );
     
                                char a[3], b[3], c[3], d[3], e[3], f[3];
                                sscanf(chaine, "%2s:%2s:%2s:%2s:%2s:%2s", a, b, c, d, e, f);
                                printf("%s %s %s", d, e, f);
     
                    }
     
                                fclose(fichier);
                                            }



    Citation Envoyé par Bousk Voir le message
    Avec ton format fixe le sscanf est sans doute le plus simple.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const char* mac = "08:60:6e:8c:2a:c7";
    char a[3], b[3], c[3], d[3], e[3], f[3];
    sscanf(mac, "%2s:%2s:%2s:%2s:%2s:%2s", a, b, c, d, e, f);
    printf("%s%s%s%s%s%s", a, b, c, d, e, f);

    Tu peux aussi faire un remove des : dans la chaîne d'origine.
    Un truc du genre
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void remove_char(char* src, char toRemove)
    {
      const int total_length = strlen(src);
      while (char* found = strchr(src, toRemove))
      {
        const int chars_before = found - src;
        const int length_after_char = total_length - chars_before;
        memmove(found, found + 1, length_after_char + 1); // Ajoute 1 pour garder le \0
      }
    }

  6. #6
    Candidat au Club
    variables statiques ?
    re bonjour,

    Afin de pouvoir utiliser les variables stockées par sscanf() dans une autre fonction je les ai déclarées
    statiques en début de programme:

    static char a[3], b[3], c[3], d[3], e[3], f[3];

    Est-ce une abérration pour vous ou faut-il utiliser des pointeurs ?

    Merci pour votre avis.

  7. #7
    Expert confirmé
    Bonjour.

    Par principe, mais rien n'est interdit, il faut éviter les déclarations en global. C'est à dire en dehors de toute fonction.

    Tu as plusieurs solutions pour résoudre cette difficulté:
    • transmettre à toutes les fonctions les adresses des variables déclarées,
    • regrouper tout ce petit monde dans une structure, déclarer une variable du type de la structure et transmette son adresse aux différentes fonctions,
    • déclarer un tableau char de taille 9 et transmettre son adresse aux différentes fonctions. (il suffit d'indenter un index pour lire les différentes données).

    Il y a sûrement d'autres possibilités.

    [Edit]

    Pour la troisième possibilité voici comment tu peux faire :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     const char* mac = "08:60:6e:8c:2a:c7";
      printf ("mac : %s\n", mac);
     
      char a[3], b[3], c[3], d[3], e[3], f[3];
      char code [10];
      sscanf(mac, "%2s:%2s:%2s:%2s:%2s:%2s", a, b, c, d, e, f);
      printf ("d, e, f : %s, %s, %s\n", d, e, f);
     
      strcat(code, d);
      strcat(code, e);
      strcat(code, f);
      printf("%s\n", code);

    Tu récupères dans code[] les données. Tu peux transmettre ce tableau aux fonctions de traitement. Ainsi, une fois la fonction dans laquelle tu l'as déclaré se termine, il sera aussi détruit. Pas de perte mémoire et un code plus robuste. Les fonctions ne modifient que les données qui leurs sont transmises.
    Utilisation de Glade avec Gtk+ - N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk

  8. #8
    Candidat au Club
    Super, ça avance, merci beaucoup à vous tous pour votre aide.

  9. #9
    Expert éminent sénior
    Bonjour
    Citation Envoyé par netlink1987 Voir le message
    Afin de pouvoir utiliser les variables stockées par sscanf() dans une autre fonction je les ai déclarées
    statiques en début de programme:

    static char a[3], b[3], c[3], d[3], e[3], f[3];

    Est-ce une abérration pour vous ou faut-il utiliser des pointeurs ?
    Un pointeur n'est qu'un outil. Si tu n'en as pas besoin alors il faut pas te forcer. D'autant plus qu'utiliser un pointeur dans un terme aussi vague ça ne veut rien dire (tout comme tu aurais dit "faut-il utiliser l'addition" ça aurait été pareil).
    Car réfléchissons bien: quand on utilise un pointeur (ex char *pt) on est obligé à un moment ou à un autre d'écrire pt=adresse valide (sauf si le pointeur est un paramètre de fonction mais dans ce cas là la copie est faite implicitement lors de l'appel de la fonction). Donc quoi mettre dans pt ?
    • une allocation => char *pt; pt=malloc(3 * sizeof(char)). Ok mais c'est idiot d'utiliser un truc aussi lourd qu'un malloc là où on peut faire la même chose en plus simplement avec un tableau
    • un pointeur qui pointerait alors vers une variable connue (et très probablement celle d'un tableau) => char a[3]; char *pt=a. Ok, mais alors quel est son avantage par rapport à "a" ?

    La seule solution pour laquelle des pointeurs "pourraient" être utilisés, c'est pour les placer au point de départ de chaque partie de l'adresse. Ex pour 08:60:6e:8c:2a:c7, alors un pointeur placé sur la partie de la chaine contenant "08", un autre placé sur le "60" et etc. Mais ça t'obligerait toutefois à remplacer les ":" par des '\0' pour que chaque chaine pointée s'arrête à la fin de sa propre partie. Faisable mais ça implique une modification de la donnée initiale et il peut arriver que ça te desserve plus tard (à réfléchir donc).

    En revanche, pour stocker 6 valeurs de 3 caractères, perso je serais passé par un tableau 2D (char mac[6][3]). Ou alors, si on veut pouvoir expliciter les différentes valeurs tout en pouvant les manipuler ensembles, par une structure (typedef struct {char a[3]; char b[3]; char c[3]; char d[3]; char e[3]; char f[3];} t_mac;). Ce qui permet alors de ne plus avoir besoin de les mettre en global (car en pouvant les manipuler d'un coup, tu peux alors les passer d'un coup à tes différentes fonctions qui en auront besoin). Elle est là l'aberration: utiliser 6 variables indépendantes pour stocker un groupe d'éléments qui vont ensembles.
    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

  10. #10
    Candidat au Club
    Bonjour,

    D'autant que l'on ne peut pas dire que je sois à l'aise avec le C ....

    Si je peux faire simple, je fais simple !

    Merci pour ces explications.

  11. #11
    Rédacteur/Modérateur

    Il faut sans doute initialiser les tableaux avec un \0 final sinon je suis pas sûr que sscanf le rajoute.

    Si tu veux faire simple c'est Python qu'il faut utiliser pour ce truc, pas C, surtout quand on connait pas/mal.
    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.

  12. #12
    Expert éminent sénior
    Citation Envoyé par Bousk Voir le message
    sinon je suis pas sûr que sscanf le rajoute.
    Si, c'est une assurance. Toutes les fonctions de création de chaines rajoutent le '\0' à la fin de la chaine créée. A 2 exceptions près avec strncpy() et strncat() qui remplissent le tableau de destination avec au plus "n" caractères et si "n" est atteint avant la fin de la chaine à copier, ne rajoutent alors pas le \0'.
    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