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 :

écrire dans stdin


Sujet :

C

  1. #1
    Membre éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut écrire dans stdin
    Bonsoir,
    je
    souhaite faire un programme qui peut prendre un paramètre en argument,
    ou le lisant dans stdin (le choix est fait grâce à getopt).
    Le problème que je peux avoir, c'est que je dois traiter soit une
    chaîne, soit un fichier (stdin).
    Alors mon idée était d'écrire dans stdin pour ensuite lire (quoi qu'il
    arrive).
    Sauf que en faisant fprintf(stdin, "nawak"); ça ne marche pas.
    Donc j'ai voulu faire fdopen(stdin, "w+"); pour changer les droits, mais
    apparemment ça me le permet pas (ou je le fais mal).

    Donc comment écrire dans stdin? Ou sinon, sachant que je dois gérer en
    entrée une chaine de caractère ou le fichier stdin, quel est la meilleur
    façon de faire pour ensuite traiter l'information?

    Merci d'avance.

    ps: je suis sur GNU/Linux, et je ne me préoccupe pas le moindre du monde que ça ne marchera pas sur les autres systèmes.

    edit: en regardant la doc, c'est plutôt fdopen(fileno(stdin),"w+"); , mais ça ne change rien.
    en regardant mieux, on peux faire directement fdopen(STDIN_FILENO,"w+");

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 442
    Par défaut
    Bonjour,

    Tu ne peux pas écrire dans « stdin », parce que ça n'a pas de sens. C'est un flux d'entrée. Tant que c'est un vrai fichier, on peut encore s'en sortir mais s'il s'agit d'un flux venant du clavier ou carrément d'une connexion réseau, tu ne peux pas ajouter artificiellement de données sans agir sur la source.

    Il existe quand même une exception : ungetc(), qui permet de « repousser » le dernier caractère lu vers sa source comme si de rien était, mais cela ne t'aidera pas car la man page précise qu'un seul ungetc() est garanti.

    De toutes façons, il s'agit d'une erreur de conception et dans tous les cas, tu n'aurais pas besoin de le faire. Tu souhaites repousser ta chaîne dans ton fichier pour faire en sorte de la lire depuis la même source dans tous les cas. En fait, il faut faire l'inverse : tu seras de toutes façons obligé de déposer les infos stdin dans un buffer en mémoire. Donc soit tu travailles directement sur ta chaîne, soit tu travailles sur le buffer (après avoir effectué l'opération de lecture le cas échéant).

    Si tu ne peux pas travailler directement sur ta chaîne (lecture seule, par exemple), alors tu la copie dans ton buffer avec strncpy() plutôt que remplir celui-ci avec fread(). À l'étape suivante, dans tous les cas, tes données seront dans ce buffer.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Bonsoir,
    je souhaite faire un programme qui peut prendre un paramètre en argument, ou le lisant dans stdin (le choix est fait grâce à getopt).
    Salut
    Un peu du style commande argument ou echo argument | commande. Et ce genre d'appel est même détectable sans passer par getopt...

    Citation Envoyé par dafpp Voir le message
    Donc comment écrire dans stdin? Ou sinon, sachant que je dois gérer en entrée une chaine de caractère ou le fichier stdin, quel est la meilleur façon de faire pour ensuite traiter l'information?
    Stocker stdin ou argv[1] dans un buffer puis traiter le buffer. Une petite fonction dédiée à ce travail est c'est réglé.

    Citation Envoyé par dafpp Voir le message
    ps: je suis sur GNU/Linux, et je ne me préoccupe pas le moindre du monde que ça ne marchera pas sur les autres systèmes.
    Comme c'est pas bien !!! Tu devrais plutôt dire "je suis sur GNU/Linux mais comme je suis très professionnel je voudrais faire quelque chose de vraiment propre et conforme à la norme pour pouvoir facilement faire évoluer mon truc et voire un jour peut-être être porté sur d'autres OS ; ou au-moins pour que ça ne me pête pas à la tronche au bout de 3 mois ; et accessoirement pour qu'on ne puisse pas dire que les dév Linux ne sont que des petits bricolos"...

    Citation Envoyé par dafpp Voir le message
    edit: en regardant la doc, c'est plutôt fdopen(fileno(stdin),"w+"); , mais ça ne change rien.
    en regardant mieux, on peux faire directement fdopen(STDIN_FILENO,"w+");
    Oui, ou bien open(STDIN_FILENO, O_WRONLY) mais quoi qu'il en soit ce n'est pas la fonction utilisée qui est mauvaise mais ce que tu cherches à faire avec. Si stdin n'est pas accessible en écriture, tu ne pourras pas y accéder en écriture. Tout comme tu ne pourras jamais exécuter unlink(".")...
    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 éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Bon buffer quoi qu'il arrive? Ok.
    Donc pour les fichiers je dois faire du setbuf, puis fmemopen et ensuite du simple fgetc?
    donc pareil si c'est une chaine?

    Donc c'est quoi un buffer? C'est un espace mémoire qui est alloué? Il se trouve où?
    Pourqoi pas le faire directement dans un fichier, qu'est ce qui est mieux?

  5. #5
    Membre éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Salut
    Un
    peu du style commande argument ou
    echo argument | commande. Et ce genre d'appel
    est même détectable sans passer par getopt...
    Oui oui, mais il n'y a pas que ça qui sera géré par la commande.
    Si pas d'option '-s', on lit le premier argument, sinon on lit stdin (donc un coup de echo arg | commande et c'est réglé, ya )


    Citation Envoyé par Sve@r Voir le message
    Comme c'est pas bien !!! Tu devrais plutôt dire "je suis sur GNU/Linux
    mais comme je suis très professionnel je voudrais faire quelque chose de
    vraiment propre et conforme à la norme pour pouvoir facilement faire
    évoluer mon truc et voire un jour peut-être être porté sur d'autres OS ;
    ou au-moins pour que ça ne me pête pas à la tronche au bout de 3 mois ;
    et accessoirement pour qu'on ne puisse pas dire que les dév Linux ne
    sont que des petits bricolos"...
    Je ne suis absolument pas un professionnel, je veux faire proprement les choses, et conforme aux normes, mais j'utiliserai bien souvent - et parce que ça m'intéresse et c'est trés utile - les outils de GNU et de GCC (que je ne touche pas encore, mais je sais qu'il a des choses amusantes et très intéressante). Bref, si les autres OS pas libre ne peuvent pas compiler, qu'ils changent d'OS. Vu ce sur ce que ça va servir, ils s'en foutront éperdument.

    Citation Envoyé par Sve@r Voir le message
    Oui, ou bien open(STDIN_FILENO, O_WRONLY) mais
    quoi qu'il en soit ce n'est pas la fonction utilisée qui est mauvaise
    mais ce que tu cherches à faire avec. Si stdin n'est pas accessible en
    écriture, tu ne pourras pas y accéder en écriture. Tout comme tu ne
    pourras jamais exécuter unlink(".")...
    Très bien. Je pensais voir une lueur d'espoir. Mais non, en vain.

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 442
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Bon buffer quoi qu'il arrive? Ok.
    Donc pour les fichiers je dois faire du setbuf, puis fmemopen et ensuite du simple fgetc?
    donc pareil si c'est une chaine?
    Non, juste fread() ou fgets(), c'est suffisant.

    Donc c'est quoi un buffer? C'est un espace mémoire qui est alloué?
    Oui. Par toi. Plus précisément, c'est le terme anglais pour « mémoire tampon ». Ça fait partie des fondamentaux de l'informatique. Une mémoire tampon (à l'image des tampons des wagons d'un train), c'est un espace en mémoire qui permet de compenser les différences de flux quand tu ne peux pas immédiatement renvoyer ce que tu reçois.

    Il se trouve où? Pourqoi pas le faire directement dans un fichier, qu'est ce qui est mieux?
    Parce qu'un « fichier », quand ce n'est pas une boîte à fiches, c'est simplement une suite d'octets enregistrée magnétiquement sur ton disque dur. Il faut bien la lire et, ce faisant, déposer ce que tu lis en mémoire. Et pour ce faire, il faut que tu réserves un peu d'espace pour le faire, et que tu dises à fread() à quel endroit il doit déposer les données qu'il lit.

    « travailler directement sur le fichier » n'est qu'une vue de l'esprit, même lorsque l'on utilise mmap(). Dans tous les cas, les données devront transiter par la mémoire vive.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Bon buffer quoi qu'il arrive? Ok.
    Donc pour les fichiers je dois faire du setbuf, puis fmemopen et ensuite du simple fgetc?
    donc pareil si c'est une chaine?
    Oui. Soit tu lis stdin et tu le stockes son contenu dans une zone mémoire, soit tu recopies argv[1] dans la même zone mémoire. Dans les deux cas tu auras au final une unique zone mémoire à traiter.

    Citation Envoyé par dafpp Voir le message
    Donc c'est quoi un buffer? C'est un espace mémoire qui est alloué? Il se trouve où?
    C'est un terme générique signifiant juste "zone mémoire". Typiquement, en C, un char toto[100] c'est déjà un buffer.
    Le souci, dans ton cas, c'est que les datas n'étant pas connues à l'avance, et étant de tailles variables, tu ne peux pas prévoir un buffer figé et tu dois passer par un buffer évolutif, c'est à dire un buffer qui s'agrandit au fur et à mesure que les datas arrivent. Donc un buffer alloué par malloc() et réalloué au besoin par realloc()...

    Ceci dit, ça n'est pas aussi difficile qu'il n'y parait. Regarde...
    1) la fonction qui lit stdin
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    char *stdin2buf()
    {
        char *buffer=NULL;  // Le buffer de stockage
        char *other=NULL;    // Le buffer de réallocation
        size_t sz_buf=0;   // La taille allouée par malloc()
        size_t nb_car=0;   // Le nb de caractères utiles
        char c;                   // Le caractère lu
     
        // Lecture stdin
        while ((c=fgetc(stdin)) != EOF)
        {
            // A-t-on besoin de mémoire (ce qui est le cas quand le nb de caractères stockés a atteint la taille allouée... ou bien que celle-ci est à 0)
            if (nb_car == sz_buf)
            {
                // Augmentation buffer
                sz_buf+=100
     
                // Reallocation (si le buffer est à NULL, la réallocation se comporte comme une allocation). Ne pas oublier l'espace pour le '\0' final
                other=realloc(buffer, (sz_buf + 1) * sizeof(char));
     
                // Si l'allocation a échoué
                if (other == NULL)
                {
                    // Libération allocation précédente (sans effet sur un buffer NULL)
                    free(buffer);
     
                    // Arrêt fonction
                    return NULL;
                }
     
                // Le buffer peut enfin récupèrer la zone allouée
                buffer=other;
            }
     
            // Stockage du caractère lu
            buffer[nb_car]=c;
            nb_car++;
        }
     
        // Stockage du '\0'
        buffer[nb_car]='\0';
     
        // on renvoie le buffer
        return buffer;
    }

    2) la fonction qui lit argv[x]
    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
    char *argv2buf(char *argv)
    {
        char *buffer=NULL;  // Le buffer de stockage
     
        // Allocation buffer - Ne pas oublier le '\0'
        buffer=malloc((strlen(argv) + 1) * sizeof(char));
     
        // Si l'allocation a échoué, fin fonction
        if (buffer == NULL)
            return NULL;
        }
     
        // Stockage de argv
        strcpy(buffer, argv);
     
        // on renvoie le buffer
        return buffer;
    }

    Et 3) utilisation
    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
    int main(int argc, char *argv[])
    {
        char *buffer;
        if (argc == 0)
        {
            // Stockage stdin
            buffer=stdin2buf()
        }
        else
        {
            // Stockage argv[1]
            buffer=argv2buf(argv[1]);
        }
     
        // Dans les 2 cas, on a une zone mémoire allouée... ou pas
        if (buffer == NULL)
        {
            perror("Erreur malloc()");
            return -1;
        }
     
        // Suite du travail sur buffer...
        ...
     
        // Fin du travail - Libération mémoire
        free(buffer);
        return 0;
    }

    Comme tu vois, un peu long à programmer (penser à tous les cas possibles) mais pas super difficile...


    Citation Envoyé par dafpp Voir le message
    Pourqoi pas le faire directement dans un fichier, qu'est ce qui est mieux?
    C'est possible mais le désavantage d'un fichier c'est que c'est sur disque donc avec des accès très très lent (comparé à la mémoire). Un autre souci à gérer dans ce cas c'est le nom que tu donneras à ton fichier et les collisions possibles. En effet, si tu appelles ton fichier "/tmp/toto" et que tu appelles 2 fois ton programme en parallèle (n'oublie pas que quand on bosse sur Gnu/Linux il faut toujours et impérativement penser "multitâches/multiutilisateurs") les deux processus iront écrire des infos différentes dans le même fichier.
    C'est pourquoi on essaye généralement dans les programmes d'éviter les fichiers externes autant que possibles.
    Accessoirement développer "proprement" te donne aussi ce genre de réflexes qui t'aident à prévoir les soucis possibles suivant tel ou tel choix...

    Citation Envoyé par dafpp Voir le message
    Je ne suis absolument pas un professionnel, je veux faire proprement les choses, et conforme aux normes, mais j'utiliserai bien souvent - et parce que ça m'intéresse et c'est trés utile - les outils de GNU et de GCC (que je ne touche pas encore, mais je sais qu'il a des choses amusantes et très intéressante). Bref, si les autres OS pas libre ne peuvent pas compiler, qu'ils changent d'OS. Vu ce sur ce que ça va servir, ils s'en foutront éperdument.
    J'ai parlé d'être professionnel (sous-entendu "dans la façon de coder") et non d'être "un" professionnel de fait. Même si ce programme ci n'est pas utilisé dans d'autres OS, ça te donne un état d'esprit général, une façon de faire qui transpirera sur tes autres programmes futurs et sur toi-même en tout.
    Accessoirement il existe gcc pour zindow et donc peut-être, un jour...

    Citation Envoyé par dafpp Voir le message
    Très bien. Je pensais voir une lueur d'espoir. Mais non, en vain.
    Mais oui, tu l'as ta lueur. C'est juste que tu n'avais pas pris le bon cap. Ton truc est parfaitement faisable mais sauf que tu as à ta disposition une belle et grande zone mémoire et donc qu'il ne faut pas compter sur stdin qui n'est pas là pour s'y substituer...
    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 éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Non,
    juste fread() ou fgets(), c'est suffisant.
    Donc de quoi on parle quand c'est un stream? C'est une structure qui a comme attribut une donnée qui pointe vers un buffer?
    Mais pour une chaine, faut bien que j'ai quelque chose de type FILE (grâce à fmemopen, non?)

    Citation Envoyé par Obsidian Voir le message
    « travailler directement sur le fichier » n'est qu'une vue de l'esprit,
    même lorsque l'on utilise mmap(). Dans tous les cas, les données
    devront transiter par la mémoire vive.
    Oui je pensais utiliser mmap, mais là dans ce cas ça change rien? Du moins lors de la récupération des données dans le buffer. Après la manipulation se fait directement dans la mémoire vive? (en tout cas avec mmap)

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Donc de quoi on parle quand c'est un stream? C'est une structure qui a comme attribut une donnée qui pointe vers un buffer?
    Mais pour une chaine, faut bien que j'ai quelque chose de type FILE (grâce à fmemopen, non?)
    fmemopen() permet d'utiliser une chaine comme si c'était un fichier. C'est aussi une possibilité. En effet, soit tu pars de stdin (un FILE*) et tu transformes alors argv[1] en FILE* ; soit tu pars de argv[1] (une chaine) et tu transformes alors stdin en chaine. Dans mon post précédent (édité) j'ai choisi cette dernière solution...
    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 éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    fmemopen() permet d'utiliser une chaine comme si c'était un fichier. C'est aussi une possibilité. En effet, soit tu pars de stdin (un FILE*) et tu transformes alors argv[1] en FILE* ; soit tu pars de argv[1] (une chaine) et tu transformes alors stdin en chaine. Dans mon post précédent (édité) j'ai choisi cette dernière solution...
    J'avais répondu à l'autre post- mais la connexion n'a pas voulu savoir.
    Mais dans ce cas, qu'est ce qui est mieux, conseillé? Partir sur du FILE * ou du char *? Et n'est pas préjudiciable si j'alloue du char * pour 1Mo? - par exemple. Et si c'est l'ordre du Go? Est-ce que la machine à la même approche avec FILE * et char *? FILE n'est ce pas une structure qui a comme attribut qui pointe sur un buffer?

    Il est préférable de copier l'argument dans un autre espace mémoire et de ne pas travailler directement dessus? (c'est ce qui est fait dans le code).

    Accessoirement il existe gcc pour zindow et donc peut-être, un jour...
    Mais si je me souviens bien, en regardant sur la doc de gcc, tous les ajouts de gcc sur le langage C ne marche pas forcement sur le gcc de windaube. Je pourrai y regarder de nouveau, mais je ne pense pas me tromper (ou pas)

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Mais dans ce cas, qu'est ce qui est mieux, conseillé? Partir sur du FILE * ou du char *? Et n'est pas préjudiciable si j'alloue du char * pour 1Mo? - par exemple. Et si c'est l'ordre du Go?
    Attention, ton topic parlait d'un simple argument passé au programme. Donc un truc ne dépassant pas quelques octets (à ce propos ma fonction stdin2buf() est d'ailleurs un peu surdimensionnée mais au-moins elle fonctionnera dans la quasi totalité des situations).
    Donc je suis parti de l'hypothèse que la mémoire du programme est suffisemment taillée pour absorber une chaine faisant généralement la taille qu'ont les arguments qu'on passe aux programmes c.a.d. quelques octets.
    Si maintenant tu veux faire absorber et traiter des giga octets de datas, ce n'est plus la même approche.

    Citation Envoyé par dafpp Voir le message
    Est-ce que la machine à la même approche avec FILE * et char *?
    Non. Un char* c'est une adresse pointant sur une zone mémoire. De cette adresse tu peux instantanément récupérer la data correspondante ainsi que dans toute data se situant en deça et au delà (pour peu que tu aies bien prévu que cette zone te soit dédiée)
    Un FILE* c'est une structure dédiée à la gestion des fichiers sur disque. Tu peux aussi récupérer et traiter les octets situés dans ces fichiers mais la façon de faire est totalement différente.
    Et donc soit tu convertis ton stdin en char* et tu auras instantanément accès à chaque octet qui s'y trouve ; soit tu convertis ton argv[1] en FILE* et tu ne pourras alors le gérer que comme un FILE*...

    Citation Envoyé par dafpp Voir le message
    FILE n'est ce pas une structure qui a comme attribut qui pointe sur un buffer?
    La structure FILE contient un buffer servant (en interne) à stocker les octets du fichier. Mais mis à part le nom "buffer" représentant la même chose (une zone mémoire de travail), il n'y a rien de commun entre le buffer dont on parle dans nos posts et le buffer du FILE.
    Ou plutôt en fait si. C'est exactement la même chose (une zone de travail) mais toi tu n'as pas accès au buffer du FILE qui est réservée aux fonctions dédiées à la gestion des fichiers (fgetc, fputc, etc...). Et donc tu es obligé de te créer ton propre buffer pour pouvoir y stocker et traiter des données...

    Citation Envoyé par dafpp Voir le message
    Il est préférable de copier l'argument dans un autre espace mémoire et de ne pas travailler directement dessus? (c'est ce qui est fait dans le code).
    Oui dans mon exemple j'ai préféré recopier le contenu de argv pour avoir au final on a exactement la même chose => une zone mémoire allouée qu'on pourra alors libérer via free().
    Parce que l'autre option, à savoir recopier simplement l'adresse de argv[1] dans buffer, conduira alors à devoir de nouveau faire un test en final pour savoir si le buffer vient de stdin+malloc ou de argv...

    Citation Envoyé par dafpp Voir le message
    Mais si je me souviens bien, en regardant sur la doc de gcc, tous les ajouts de gcc sur le langage C ne marche pas forcement sur le gcc de windaube. Je pourrai y regarder de nouveau, mais je ne pense pas me tromper (ou pas)
    Bien entendu non. Toutes les fonctions spécifiques à Unix (fork/signal/kill/etc) ne sont pas répercutées dans zindow. C'est bien évidemment un frein à la portabilité "totale" entre les deux OS. Et donc bien entendu si ton code a besoin d'utiliser des outils spécifiques POSIX hé bien tant pis. Ceci dit, cela ne t'empêche pas de rester toujours "le plus propre possible" dans tes codes...
    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 éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Attention, ton topic parlait d'un simple argument passé au programme. Donc un truc ne dépassant pas quelques octets (à ce propos ma fonction stdin2buf() est d'ailleurs un peu surdimensionnée mais au-moins elle fonctionnera dans la quasi totalité des situations).
    Donc je suis parti de l'hypothèse que la mémoire du programme est suffisemment taillée pour absorber une chaine faisant généralement la taille qu'ont les arguments qu'on passe aux programmes c.a.d. quelques octets.
    Si maintenant tu veux faire absorber et traiter des giga octets de datas, ce n'est plus la même approche.
    Citation Envoyé par Sve@r Voir le message
    Non. Un char* c'est une adresse pointant sur une zone mémoire. De cette adresse tu peux instantanément récupérer la data correspondante ainsi que dans toute data se situant en deça et au delà (pour peu que tu aies bien prévu que cette zone te soit dédiée)
    Un FILE* c'est une structure dédiée à la gestion des fichiers sur disque. Tu peux aussi récupérer et traiter les octets situés dans ces fichiers mais la façon de faire est totalement différente.
    Et donc soit tu convertis ton stdin en char* et tu auras instantanément accès à chaque octet qui s'y trouve ; soit tu convertis ton argv[1] en FILE* et tu ne pourras alors le gérer que comme un FILE*...
    Donc dans ce cas, si je gère de nombreuses données, un FILE * (dans sa construction)
    sera capable de gérer un fichier lourd, sans que je sois préoccupé par la mémoire utilisé? Tout ça est géré et construit par la manière qu'est géré le stream?

    Citation Envoyé par Sve@r Voir le message
    La structure FILE contient un buffer servant (en interne) à stocker les octets du fichier. Mais mis à part le nom "buffer" représentant la même chose (une zone mémoire de travail), il n'y a rien de commun entre le buffer dont on parle dans nos posts et le buffer du FILE.
    Ou plutôt en fait si. C'est exactement la même chose (une zone de travail) mais toi tu n'as pas accès au buffer du FILE qui est réservée aux fonctions dédiées à la gestion des fichiers (fgetc, fputc, etc...). Et donc tu es obligé de te créer ton propre buffer pour pouvoir y stocker et traiter des données...
    Donc c'est pas un buffer où je pourrai tout lire. C'est x octets fixe, et qui se déplace en mémoire (dans le fichier) quand il en a besoin?

    Citation Envoyé par Sve@r Voir le message
    Oui dans mon exemple j'ai préféré recopier le contenu de argv pour avoir au final on a exactement la même chose => une zone mémoire allouée qu'on pourra alors libérer via free().
    Parce que l'autre option, à savoir recopier simplement l'adresse de argv[1] dans buffer, conduira alors à devoir de nouveau faire un test en final pour savoir si le buffer vient de stdin+malloc ou de argv...
    Oui en effet. Si on veut faire les choses proprement, tout se clarifie.
    Très bien.

    Citation Envoyé par Sve@r Voir le message
    Bien entendu non. Toutes les fonctions spécifiques à Unix (fork/signal/kill/etc) ne sont pas répercutées dans zindow. C'est bien évidemment un frein à la portabilité "totale" entre les deux OS. Et donc bien entendu si ton code a besoin d'utiliser des outils spécifiques POSIX hé bien tant pis. Ceci dit, cela ne t'empêche pas de rester toujours "le plus propre possible" dans tes codes...
    Je tâcherai de faire au mieux. Merci.

  13. #13
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    Donc dans ce cas, si je gère de nombreuses données, un FILE * (dans sa construction)
    sera capable de gérer un fichier lourd, sans que je sois préoccupé par la mémoire utilisé? Tout ça est géré et construit par la manière qu'est géré le stream?
    Oui oui. En fait, le FILE* ce n'est pas "le fichier" mais juste un pointeur vers une zone qui servira à gérer le fichier. Ensuite ce sont les fgetc()/fgets()/fread() qui utilisent cette zone et qui te renvoient un caractère/une chaine/une quantité d'octets pris dans le fichier.

    Citation Envoyé par dafpp Voir le message
    Donc c'est pas un buffer où je pourrai tout lire. C'est x octets fixe, et qui se déplace en mémoire (dans le fichier) quand il en a besoin?
    Oui en fonction de tes fget...(). Mais attention à ne pas utiliser le temre "mémoire" pour parler d'un fichier parce que c'est source de confusion.
    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 éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    C'est note. Tres bien merci.

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

Discussions similaires

  1. Ouvrir et écrire dans un fichier .txt en T-SQL
    Par joul's dans le forum MS SQL Server
    Réponses: 11
    Dernier message: 27/10/2008, 21h04
  2. ouvrir et écrire dans un doc excel
    Par audrey_ dans le forum ASP
    Réponses: 8
    Dernier message: 13/12/2004, 15h38
  3. écrire dans un champs généré dynamiquement
    Par scoder dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 08/12/2004, 10h14
  4. Réponses: 1
    Dernier message: 24/11/2004, 16h54
  5. [JAR] Comment écrire dans un fichier properties dans un jar
    Par Alec6 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 05/10/2004, 15h16

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