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 :

Commande bash dans un programme en C


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Etudiant
    Inscrit en
    Mai 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 42
    Par défaut Commande bash dans un programme en C
    Bonjour,
    Je suis sous Windows et je voudrais savoir s'il serait possible d'utiliser des commandes bash dans mon programme/
    Exemple :
    J'ai un fichier test.txt contenant :

    Lieu1:AA:aze
    Lieu2:BB:qsd
    Lieu3:CC:wxc
    Lieu4:dd:rty
    Lieu5:ee:fgh
    Lieu6:ff:vbn
    Lieu7:ii:uio
    Lieu8:jj:jkl
    Lieu9:kk:pml

    Cependant, je ne veux sélectionner que la première colonne. Je fais donc en bash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat test.txt  |sed -e 's/:/ /g' | awk '{print $1}'
    Savez-vous comment utiliser cela en C ?
    Merci bien
    @+
    Bapth

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 7
    Par défaut
    'Jour,

    popen(), system(), _exec etc ?

    ou alors:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int size = 0;
    while (*line && *line != ':') {
        line++;
        size++;
    }
    value = strndup(line, size);
    ...
    ...
    free(value);
    'soir

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    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 840
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par bapth Voir le message
    Je suis sous Windows et je voudrais savoir s'il serait possible d'utiliser des commandes bash dans mon programme
    Ben... oui et non. Tu peux parfaitement appeler des instructions bash depuis un code C (system(), execl(), popen(), ...) mais vu que bash n'est pas implémenté sous zindow...

    Citation Envoyé par bapth Voir le message
    Cependant, je ne veux sélectionner que la première colonne. Je fais donc en bash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat test.txt  |sed -e 's/:/ /g' | awk '{print $1}'
    Mouais, beaucoup d'opérations inutiles. Tu peux réduire tout ça en awk -F: '{print $1}' text.txt ou encore plus simplement (car appeler un truc aussi lourd que "awk" pour ça c'est comme utiliser une presse hydraulique pour écraser une noix) cut -f1 -d: test.txt...

    Citation Envoyé par bapth Voir le message
    Savez-vous comment utiliser cela en C ?
    Ah ben si tu veux le coder en C il te faut le coder vraiment. Ouvrir le fichier (fopen), lire les lignes (fgets), chercher un ':' (strchr) et le remplacer par un '\0' (si tu te souviens ce que je t'ai expliqué sur les strings en C) puis afficher la ligne résultante de cette manip (printf)...
    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]

  4. #4
    Membre averti
    Homme Profil pro
    Etudiant
    Inscrit en
    Mai 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 42
    Par défaut
    Bonsoir,
    Désolé j'ai été assez long à répondre mais j'ai pas mal galéré.
    J'ai finalement réussi grâce à tes indications à ne ''print'' que la première colonne. Cependant si je veux ''print'' une autre comment faire ?
    J'avais pensé à indiquer un caractère de début (comme le \0 pour la fin mais je n'en trouve pas ) Du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    while(i < nLignes){
                fgets(chaine, 80, fichier);
                modifier=strchr(chaine,':');
                if (*modifier != NULL){
                    *modifier = '\1';  // le \1 symbolise le début 
                }
                if (*modifier != NULL){
                    *modifier = '\0';  // le \0 symbolise le fin
                }
                printf("\n == %s", chaine); 
                i = i + 1;
            }
    Sinon quand je veux passer mon main() en fonction il y a une segmentation fault que je n'arrive pas à comprendre ... Ca me retourne la tête .

    Je vous mets les 2 codes :

    Code 1 : (Qui fonctionne)
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int Compte_ligne(FILE *fichier){
     
    	int count = 0;
    	int nLignes = 0;
     
    	while((count=fgetc(fichier)) != EOF)
    	{
    		if(count=='\n'){
    			nLignes++;
            }    
    	}
        //nLignes = nLignes + 1;
        count = 1;
     
     
     
    	return nLignes;
    }
     
     
    int main() {
     
        FILE * fichier =  fopen("Fichier/test.txt", "r+");
        char *modifier;
        int i = 0;
     
        char chaine_participant[80];
        if(fichier != NULL){  
     
        int nLignes = Compte_ligne(fichier);
     
        FILE * fichier =  fopen("Fichier/test.txt", "r");
            while(i < nLignes){
                fgets(chaine_participant, 80, fichier);
                modifier=strchr(chaine_participant,':');
                if (*modifier != NULL){
                    *modifier = '\0'; 
                }
                printf("\nParticipant : %s", chaine_participant); 
                i = i + 1;
            }
        }
     
        fclose(fichier);
        return 0;
    }
    Code 2 : (fonction que ne fonctionne pas)
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int Compte_ligne(FILE *fichier){
     
    	int count = 0;
    	int nLignes = 0;
     
    	while((count=fgetc(fichier)) != EOF)
    	{
    		if(count=='\n'){
    			nLignes++;
            }    
    	}
        //nLignes = nLignes + 1;
        count = 1;
     
     
     
    	return nLignes;
    }
     
    void Colonne (FILE *fichier, char *chaine, int nLignes){ // Doit aller avec Compte_ligne
        char *modifier;
        int i = 0;
     
        if(fichier != NULL){  
     
        FILE * fichier =  fopen("Fichier/test.txt", "r+");
            while(i < nLignes){
                fgets(chaine, 80, fichier);
                modifier=strchr(chaine,':');
                if (*modifier != NULL){
                    *modifier = '\0'; 
                }
                printf("\n == %s", chaine); 
                i = i + 1;
            }
        }
    }
     
    int main() {
     
     
        FILE * fichier =  fopen("Fichier/test.txt", "r+");
     
        char chaine_participant[80];
     
        Colonne(fichier, chaine_participant[80],Compte_ligne(fichier));
     
        fclose(fichier);
        return 0;
    }
    Je vous remets le contenue du fichier : (Il n'a aucun sens mais c'est un test )
    Lieu1:AA:aze
    Lieu2:BB:qsd
    Lieu3:CC:wxc
    Lieu4:dd:rty
    Lieu5:ee:fgh
    Lieu6:ff:vbn
    Lieu7:ii:uio
    Lieu8:jj:jkl
    Lieu9:kk:pml

    Voila. J'espère que j'ai été assez clair
    @+
    Bapth
    PS : J'utilise mon carton Jocker pour aujourd'hui

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    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 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bapth Voir le message
    J'ai finalement réussi grâce à tes indications à ne ''print'' que la première colonne. Cependant si je veux ''print'' une autre comment faire ?
    Ah ben je suis allé au plus court évidemment. Tu disais ne vouloir que la première donc j'ai fait simple. Si tu veux refaire l'équivalent complet de cut dans lequel tu peux indiquer des colonnes spécifiques c'est plus compliqué.
    Un point important à piger quand on traite les strings, c'est que t'es pas obligé de toujours partir du début. Une fonction de traitement de string partira du point que tu lui donnes et cherchera le '\0' à partir de ce point. Et donc rien ne t'interdit de jouer sur ce point de départ. Si par exemple j'ai char *toto="Hello", si je fais strlen(toto) j'obtiens 5 mais si je fais strlen(toto+3) je ne lui donne plus l'adresse de départ de toto mais une adresse située 3 rangs plus à droite (si on admet la convention que les adresses vont de la gauche vers la droite en RAM), autrement dit l'adresse du second 'l'. J'en ai le droit (cette adresse fait partie de celles qui m'ont été attribuées), c'est bien l'adresse d'une liste de caractères contenant quelque part plus loin un '\0', c'est ok. La fonction part de là et fait son boulot et me répond 2.
    Tu peux utiliser le même principe avec ton strchr() pour récupérer le premier ':'. Tu as alors l'adresse de ce ':', tu peux alors repartir de là pour chercher le second ':'.

    Sinon il existe la fonction strtok_r() qui ressemble un peu au split() des autres langages. Elle va traiter une chaine selon un séparateur et chaque fois qu'elle trouve le séparateur, le remplace par un '\0' et te renvoie le point de départ. Suffit de mettre ça dans une boucle pour avoir chaque "colonne" de la string.
    Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    #include <string.h>
     
    int main() {
    	char string[]="toto:titi:tata:tutu";
    	char *mem;
    	char *mot;
    	int i;
     
    	for (i=1, mot=NULL; (mot=strtok_r(mot != NULL ?NULL :string, ":", &mem)) != NULL; i++) {
    		printf("mot %d: [%s]\n", i, mot);
    	}
    }
    Alors il y a une petite subtilité: au premier appel, la fonction veut la string de départ. Ensuite, pour qu'elle sache quelle doit "continuer" un travail précédent, elle veut "NULL". Là elle repart de "mem" dans lequel elle a sauvegardé son contexte. Certains font un premier appel avant la boucle avec "string" puis un appel en fin de boucle avec NULL, moi je préfère n'en faire qu'un seul mais en indiquant si je suis au premier appel (symbolisé par "mot" qui vaut NULL) ou aux suivants (où "mot", qui a récupéré le retour de l'appel précédent, ne vaut plus NULL). D'où ce mot != NULL ?NULL :string pour son premier paramètre (j'espère que tu connais l'opérateur ternaire expression ?x :y sinon tu fais une recherche).

    Citation Envoyé par bapth Voir le message
    J'avais pensé à indiquer un caractère de début (comme le \0 pour la fin mais je n'en trouve pas )
    Tu as parfaitement le droit de te définir tes propres conventions. Ton idée d'un second délimiteur '\1' est pas mal (t'as pigé et c'est l'essentiel). Simplement toute fonction "officielle" de traitement ne s'occupera, elle, que du '\0'.

    Citation Envoyé par bapth Voir le message
    Sinon quand je veux passer mon main() en fonction il y a une segmentation fault que je n'arrive pas à comprendre ... Ca me retourne la tête
    Tu as fait l'erreur du débutant. Tu as dit "ma fonction attend un char[80] je lui passe un char[80]. Sauf que char[80] dans une déclaration c'est un tableau, char[80] dans une instruction c'est l'élément indice 80 du tableau (donc un char)
    Remplace Colonne(fichier, chaine_participant[80], Compte_ligne(fichier)) par Colonne(fichier, chaine_participant, Compte_ligne(fichier)). La variable "chaine_participant" c'est bien une adresse, elle sera donc reçue dans le pointeur "chaine" de ta fonction. C'est exactement le même principe que char toto[80]="Hello"; strlen(toto) et non char toto[80]="Hello"; strlen(toto[80]) !!!
    Ceci dit, je ne vois pas l'utilité de ce paramètre qui n'apporte aucune plus value pour l'appelant ou pour la fonction. Il n'a pas été rempli au départ (donc il n'est pas présumé servir de valeur utile quand la fonction le reçoit), la fonction le reçoit mais s'en sert pour apparemment travailler sans y mettre quoi que ce soit qui semblerait déterminant pour l'appelant qui d'ailleurs ne s'en sert pas au retour => il peut donc être supprimé et remplacé par un bête char[80] dans la fonction.

    Attention aussi que Compte_ligne() a lu tout le fichier donc il faut te replacer au début (fseek) quand la fonction se termine (pour que l'utilisateur puisse continuer, lui, à lire le fichier). En réalité, la fonction devrait
    • récupérer la position (ftell)
    • se placer au début (fseek)
    • compter
    • se remettre à la position (fseek)

    ce qui lui permettrait d'être appelée dans toutes les configurations tout en laissant le fichier en l'état.

    Citation Envoyé par bapth Voir le message
    J'utilise mon carton Jocker pour aujourd'hui
    Noté.
    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]

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    On peut aussi utiliser la fonction scanf() dans les cas où le format est garanti, car c'est compliqué de faire des vérifications avec. On peut tout extraire avec une seule commande:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    struct Data {
       char txt1[80];
       char txt2[80];
       char txt3[80];
    };
    struct Data  tab[100];
    int  n = 0;
    FILE*  file = fopen( "nom_du_fichier" , "rt" );
    if ( file ) {
        while ( 3 == fscanf( file , "%[^:]:%[^:]:%[^:] ", tab[n].txt1 , tab[n].txt2, tab[n].txt3 ) ) {
            ++n;  // compter les lignes remplies tant que 3 champs ont été lus
        }
    }

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    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 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dalfab Voir le message
    On peut aussi utiliser la fonction scanf() dans les cas où le format est garanti
    Bien vu. J'ai pas le réflexe scanf() car j'ai tellement été traumatisé par cette fonction quand j'étais petit que je dois faire un blocage mais effectivement, quand on sait s'en servir, on peut faire danser ses strings...
    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]

Discussions similaires

  1. commandes unix dans un programme C
    Par thepinguin dans le forum C
    Réponses: 9
    Dernier message: 19/10/2006, 02h11
  2. utilisation des commandes shell dans un programme C
    Par rasgueados dans le forum Linux
    Réponses: 15
    Dernier message: 03/08/2006, 17h25
  3. commande shell dans un programme
    Par diefo dans le forum C
    Réponses: 3
    Dernier message: 15/08/2003, 13h37
  4. Réponses: 2
    Dernier message: 24/06/2003, 20h31
  5. [langage] Commande DOS dans un programme
    Par Jibees dans le forum Langage
    Réponses: 15
    Dernier message: 23/04/2003, 12h08

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