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 :

Utiliser une fonction qui concatène une chaine de caractères


Sujet :

C

  1. #1
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2022
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2022
    Messages : 7
    Points : 4
    Points
    4
    Par défaut Utiliser une fonction qui concatène une chaine de caractères
    Bonjour ou Bonsoir !

    Je cherche à afficher une fonction qui passe en arguments 2 chaines de caractères que j'ai préalablement demandées à l'utilisateur de remplir.
    En fait je cherche à ce que la fonction retourne : sudo timeout 2s airodump-ng -c tab[1] --bssid tab[0] wlan0 (avec les valeurs tab[0] et tab[1] remplies)

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    char *concat_afficherclients(char *tab, char *tab2){
    char arg0[200];
    char *sptr=arg0;
    char arg1[200]="sudo timeout 2s airodump-ng";
    char arg2[200]=" -c ";
    char arg3[200]=" --bssid ";
    char arg4[200]=" wlan0";
    strcat(arg0,arg1);
    strcat(arg0,arg2);
    strcat(arg0,tab2);
    strcat(arg0,arg3);
    strcat(arg0,tab);
    strcat(arg0,arg4);
    return sptr;
    }
     
    int main(){
     
     
    // init tab
    char tab[3][18];
     
    //demander a l'utilisateur le bssid 
    printf("Saisir le BSSID du wifi: ");
    scanf("%s",tab[0]);
     
    //demander a l'utilisateur le channel
     
    printf("Saisir le channel du wifi: ");
    scanf("%s",tab[1]);
     
    char* a=concat_afficherclients(tab[0],tab[1]);
    printf("%s",&a);
    Mais le compilateur affiche : ���n�U
    Pourriez-vous m'expliquer mon(es) erreur(s) s'il vous plait ?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 726
    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 726
    Points : 31 046
    Points
    31 046
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par coco545 Voir le message
    Mais le compilateur affiche : ���n�U
    Ce n'est pas le compilateur qui affiche ça, c'est ton programme...

    Citation Envoyé par coco545 Voir le message
    Pourriez-vous m'expliquer mon(es) erreur(s) s'il vous plait ?
    Ta fonction retourne sptr qui contient l'adresse de arg0, variable locale à la fonction et donc qui disparait quand la fonction se termine. Donc tu récupères une adresse qui n'a plus de validité. C'est un UB.

    Citation Envoyé par coco545 Voir le message
    printf("%s",&a)
    Sérieux ???
    Revois ton cours sur printf() et l'affichage des strings...

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    char *concat_afficherclients(char (*tab)[100+1]){
    	char* sptr=malloc((200 + 1) * sizeof(*sptr));
    	if (sptr == NULL) {
    		fprintf(stderr, "Erreur malloc(%lu)\n", (200 + 1) * sizeof(*sptr));
    		return NULL;
    	}
    	sprintf(sptr, "sudo timeout sudo timeout 2s airodump-ng -c %s --bssid %s wlan0", tab[1], tab[0]);
    	return sptr;
    }
     
    int main(){
    	// init tab
    	char tab[3][100+1];
     
    	//demander a l'utilisateur le bssid 
    	printf("Saisir le BSSID du wifi: ");
    	scanf("%s",tab[0]);
     
    	//demander a l'utilisateur le channel
     
    	printf("Saisir le channel du wifi: ");
    	scanf("%s",tab[1]);
     
    	char* a=concat_afficherclients(tab);
    	if (a == NULL) {
    		fputs("erreur concat_afficher()\n", stderr);
    		return -1;
    	}
    	printf("%s\n", a);
    	free(a);
    }
    Mais bon, faire une fonction qui concatène péniblement une bête string que tu aurais pu afficher directement...
    printf("sudo timeout sudo timeout 2s airodump-ng -c %s --bssid %s wlan0", tab[1], tab[0])

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 673
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 673
    Points : 10 683
    Points
    10 683
    Par défaut
    Le langage C n'est pas 1 langage orienté objet (il est procédural) et n'a pas de type "chaine de caractères"
    Juste 1 convention a été utilisée par la bibliothèque standard : c'est 1 tableau de caractères terminé par le caractère sentinelle '\0'.

    Donc c'est à toi de faire le travail
    • pour mettre 1 "chaîne de caractères" il faut la copier : strcpy ou strncpy (<- 2 liens vers la documentation cplusplus.com en anglais)
    • pour concaténer, il faut que la destination soit assez large : strcat (<- lien vers la documentation cplusplus.com en anglais)


    Plus généralement, c'est l'entête string.h (<- lien vers la documentation cplusplus.com en anglais)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *concat_afficherclients(char *tab, char *tab2){
        char arg0[200];
        char *sptr=arg0;
     
    // ..
     
        return sptr;
    }
    On ne retourne pas l'adresse d'1 variable locale

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 673
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 673
    Points : 10 683
    Points
    10 683
    Par défaut
    De toute manière, tu te prends la tête à rien il faut utiliser la fonction sprintf (<- lien vers la documentation cplusplus.com en anglais)


    1 exemple de code :
    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
    #include <stdio.h>
    #include <stdlib.h>
     
     
    char* concat_afficherclients(char* tab1, char* tab2) {
        char* buffer = malloc(128 /* * sizeof(char) */);
     
        if (buffer != NULL) {
            sprintf(buffer, "sudo timeout 2s airodump-ng -c %s --bssid %s wlan0", tab1, tab2);
        }
     
        return buffer;
    }
     
     
    int main()
    {
        char* str;
     
        str = concat_afficherclients("00:1A:C2:7B:00:47", "12");
     
        if (str != NULL) {
            printf("%s\n", str);
            free(str);
        }
     
        str = concat_afficherclients("0123.4567.89AB", "25");
     
        if (str != NULL) {
            printf("%s\n", str);
            free(str);
        }
     
     
        return EXIT_SUCCESS;
    }
    Mais le mieux, c'est de passer le buffer en paramètre et non le retourner

  5. #5
    Membre expérimenté Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    665
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 665
    Points : 1 694
    Points
    1 694
    Par défaut
    Citation Envoyé par coco545 Voir le message
    Bonjour ou Bonsoir !

    Je cherche à afficher une fonction (....)
    Ça va être dur-dur

  6. #6
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2022
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2022
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Bonjour à tous,

    Merci pour vos réponses. En fait, je crois que je me suis mal exprimé. Je ne souhaite pas afficher la phrase. Il faut que je la passe en argument en utilisant la fonction system(). Je ne crois pas qu’il soit donc pertinent de simplement l’afficher.

    Concernant mon cours sur les chaînes de caractères, c’est simple je n’en ai pas. Je suis donc allé voir sur internet pour me renseigner seul mais je savais que mon programme ne pouvait pas être parfait et qu’il contenait des erreurs. C’est pourquoi j’ai demandé de l’aide ici.

    Je ne comprends pas, il faut que j’initialise une chaine de caractère dans le main ?
    Pourquoi aurais-je besoin de strcpy ?
    Et je dois retourner arg0 au lieu de str ?

  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 726
    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 726
    Points : 31 046
    Points
    31 046
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par coco545 Voir le message
    Je ne souhaite pas afficher la phrase. Il faut que je la passe en argument en utilisant la fonction system(). Je ne crois pas qu’il soit donc pertinent de simplement l’afficher.
    Effectivement tu t'étais mal exprimé (en réalité tu ne t'étais même pas exprimé du tout car ton code ne fait que l'afficher).

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char cmd[255+1];
    sprintf(cmd, "sudo timeout sudo timeout 2s airodump-ng -c %s --bssid %s wlan0", tab[1], tab[0]);
    system(cmd);
    ... tout ça dans le main. La fonction reste inutile.

    Citation Envoyé par coco545 Voir le message
    Je ne comprends pas, il faut que j’initialise une chaine de caractère dans le main ?
    Si une fonction doit remplir une chaine, c'est plus pratique pour elle si elle reçoit la chaine à remplir. Elle n'a donc pas à la créer comme foetus et moi l'avons fait via malloc qui est la seule solution dans ce cas (avec toute une gestion d'erreurs sur malloc qui se répercute sur la fonction).

    Citation Envoyé par coco545 Voir le message
    Pourquoi aurais-je besoin de strcpy ?
    Parce que tu ne peux pas utiliser strcat() pour initialiser une chaine (détail auquel je n'avais pas fait attention dans ton code d'origine). strcat() commence par chercher la fin de la chaine à laquelle rajouter ses caractères mais comment trouver la fin d'une chaine qui n'existe pas?
    Ou alors tu commences par écrire arg0[0]='\0'. Ou bien tu définis arg0 ainsi: char arg0[200]="". Dans les deux cas, tu as initialisé manuellement la chaine et là tu peux embrayer avec strcat(). Ce qui ne change rien au problème de fond (fonction qui retourne un pointeur invalide etc).

    Citation Envoyé par coco545 Voir le message
    Et je dois retourner arg0 au lieu de str ?
    Non, dans ton code ça ne change rien. arg0 est un tableau local à ta fonction et si tu retournes arg0 tu ne retournes que son adresse. Or le tableau disparait quand la fonction se termine et tu te retrouves avec une adresse qui ne correspond plus à rien.
    Sur ce point précis c'est assez simple: en C, une fonction ne peut pas retourner un tableau. On peut ruser, encapsuler par exemple le tableau dans une structure et retourner la structure, mais comme le retour se fait par copie, c'est con de copier le potentiel milliard d'octets de la structure (sans compter que la pile explose) alors qu'il est un milliard de fois plus simple de passer le tableau à la fonction (là on ne passe qu'une adresse) qui se charge de le remplir => sprintf() par exemple.

  8. #8
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2022
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2022
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Effectivement tu t'étais mal exprimé (en réalité tu ne t'étais même pas exprimé du tout car ton code ne fait que l'afficher).
    Oui, c’etait une erreur de ma part, je voulais tester en affichant la chaine de caractères pour savoir si la fonction me retournait bien la phrase

    Citation Envoyé par Sve@r Voir le message
    ... tout ça dans le main. La fonction reste inutile.
    En réalité, je voulais utiliser une fonction qui me fasse la concaténation car c’est ce que mon professeur demande.

    Citation Envoyé par Sve@r Voir le message
    Si une fonction doit remplir une chaine, c'est plus pratique pour elle si elle reçoit la chaine à remplir. Elle n'a donc pas à la créer comme foetus et moi l'avons fait via malloc qui est la seule solution dans ce cas (avec toute une gestion d'erreurs sur malloc qui se répercute sur la fonction).
    Si je mets :

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    char *concat_afficherclients(char *tab, char *tab2){
    char arg0[200]=“”;
    char *sptr=arg0;
    char arg1[200]="sudo timeout 2s airodump-ng";
    char arg2[200]=" -c ";
    char arg3[200]=" --bssid ";
    char arg4[200]=" wlan0";
    strcat(arg0,arg1);
    strcat(arg0,arg2);
    strcat(arg0,tab2);
    strcat(arg0,arg3);
    strcat(arg0,tab);
    strcat(arg0,arg4);
    return sptr;
    }
     
    int main(){
     
     
    // init tab
    char tab[3][18];
     
    //demander a l'utilisateur le bssid 
    printf("Saisir le BSSID du wifi: ");
    scanf("%s",tab[0]);
     
    //demander a l'utilisateur le channel
     
    printf("Saisir le channel du wifi: ");
    scanf("%s",tab[1]);
     
    char*a=concat_afficherclients(tab[0],tab[1]);
    printf("%s",a);
    Est-ce mieux ?

    Citation Envoyé par Sve@r Voir le message
    Non, dans ton code ça ne change rien. arg0 est un tableau local à ta fonction et si tu retournes arg0 tu ne retournes que son adresse. Or le tableau disparait quand la fonction se termine et tu te retrouves avec une adresse qui ne correspond plus à rien.
    Sur ce point précis c'est assez simple: en C, une fonction ne peut pas retourner un tableau. On peut ruser, encapsuler par exemple le tableau dans une structure et retourner la structure, mais comme le retour se fait par copie, c'est con de copier le potentiel milliard d'octets de la structure (sans compter que la pile explose) alors qu'il est un milliard de fois plus simple de passer le tableau à la fonction (là on ne passe qu'une adresse) qui se charge de le remplir => sprintf() par exemple.
    Et si je passe un tableau en argument, est-ce que cela change quelque chose ?

    Vous dites que le pointeur est invalide mais je ne comprends pas pourquoi ? Il n’y a pas de solution à ces problèmes ?

  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 726
    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 726
    Points : 31 046
    Points
    31 046
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par coco545 Voir le message
    Citation Envoyé par coco545 Voir le message
    Concernant mon cours sur les chaînes de caractères, c’est simple je n’en ai pas.
    En réalité, je voulais utiliser une fonction qui me fasse la concaténation car c’est ce que mon professeur demande.
    Donc tu as un prof mais pas de cours???

    Citation Envoyé par coco545 Voir le message
    Citation Envoyé par Sve@r Voir le message
    Ce qui ne change rien au problème de fond (fonction qui retourne un pointeur invalide etc).
    Est-ce mieux ?
    Je crois que tu as ta réponse dans mon post précédent. Donc non ce n'est pas mieux. Ok avec ta correction la concaténation se fait parfaitement dans la fonction ; mais tu continues à vouloir retourner un tableau (ou un pointeur sur un tableau) local à la fonction. Et ça tu ne peux pas. C'est pas moi qui te l'interdit, c'est le C !!!

    Citation Envoyé par coco545 Voir le message
    Et si je passe un tableau en argument, est-ce que cela change quelque chose ?
    Oui, car là le tableau n'est pas créé dans la fonction appelée mais dans la fonction appelante. Il continue donc d'exister quand la fonction appelée se termine.

    Citation Envoyé par coco545 Voir le message
    Citation Envoyé par Sve@r Voir le message
    Ta fonction retourne sptr qui contient l'adresse de arg0, variable locale à la fonction et donc qui disparait quand la fonction se termine. Donc tu récupères une adresse qui n'a plus de validité.
    Vous dites que le pointeur est invalide mais je ne comprends pas pourquoi ?
    Ben franchement que peut-on dire de plus explicite? Une variable locale (interne) à une fonction disparait quand la fonction se termine. Donc tu récupères l'adresse d'un truc qui n'existe plus (ou qui a été récupéré par le processeur pour y stocker autre chose).
    C'est comme si je te file la clef d'une voiture située dans un parking pendant que le parking est détruit. Tu as la clef, mais elle ne sert plus à grand chose.

    Citation Envoyé par coco545 Voir le message
    Il n’y a pas de solution à ces problèmes ?
    Ah si, il y en a plein, des bonnes et des mauvaises. foetus et moi t'avons montré (avec en plus des codes full fonctionnels) ou expliqué les bonnes. Maintenant les mauvaises
    • mettre char arg0[200]="" en global
    • remplacer char arg0[200]="" par static char arg0[200]="". Avec "static" la variable n'est pas supprimée donc ton pointeur reste valide. Mais cela ne fait que "marchotter" (ce n'est pas un hasard si toutes les fonctions utilisant du static sont peu à peu remplacées...)
    • mettre char arg0[200]="" dans une structure et retourner la structure

    A partir de là tu restes libre de faire le C que tu veux.

Discussions similaires

  1. [Batch] Utiliser une chaine de caractères comme séparateur dans une boucle For /f
    Par racine carrée dans le forum Scripts/Batch
    Réponses: 3
    Dernier message: 27/06/2020, 23h22
  2. Réponses: 5
    Dernier message: 14/12/2013, 18h10
  3. Fonction qui modifie une chaine de caractère
    Par condor_01 dans le forum Débuter
    Réponses: 7
    Dernier message: 05/11/2007, 18h32
  4. Utiliser une chaine de caractère dans une clause WHERE
    Par DanaX dans le forum SQL Procédural
    Réponses: 5
    Dernier message: 15/05/2007, 12h02
  5. Réponses: 23
    Dernier message: 13/11/2006, 03h33

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