Forum Programmation.c programme c qui émule la commande cat (amélioration)

Posté par  .
Étiquettes : aucune
0
4
déc.
2006
bonsoir tout le monde j'ai revu mon pragramme.
Quand je le compile tout ce passe très bien pas d'erreur mais je lexécute rien qui se passe: je fais ./a.out nom d'un fichier pour voir son contenu [touche enter] puis plus rien. Je suis obliger de faire ctrl-c pour arrêter,je comprend pas très bien.


pourtant l'algo est très simple:
pour tous les paramètres de la ligne de commande
open fichier
tant que pas fini{
read un certain nombre de bytes dans le fichier
write à l'écran les bytes lus
}
close fichier.
voici le code changer:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char*argv[])
{
int i;
int byte_lu;
int d;
char tampon [1024];
int fd;
for (i=0; i<argc; i++)
{
d= open(argv[i],O_RDONLY);
if(d==-1)
{
printf("these file does not exist check the name\n");
exit(1);
}

else
byte_lu=read(d,tampon,1024);
while(byte_lu >0){
fd= write(d,tampon,1024);
} printf("%s",tampon[i]);
}
close (d);
}
quelqu'un à t-il une idée
Bien à vous.
  • # Si je traduit en ~français

    Posté par  . Évalué à 1.

    alors je vois dans le for :
    - ouvrir le fichier en lecture seul
    - si le fichier n'est pas ouvert : afficher un message d'erreur
    - si le fichier est bien ouvert : lire au plus 1024 octets dans tampon (byte_lu)
    - tant que byte_lu>0 : écrire dans le fichier, le contenu du tampon
    - écrire à l'écran une portion du tampon.
  • # alors

    Posté par  (site web personnel) . Évalué à 2.

    printf("%s",tampon[i]);
    Ca sert à quoi à part afficher n'importe quoi à l'ecran et eventuellement planter ?

    fd= write(d,tampon,1024);
    Faut pas ecrire 1024 caractères si tu en as lu moins. Et pourquoi essayes tu de reecrire vers le fichier que tu lis plutot que vers stdout (1) ?
    • [^] # Re: alors

      Posté par  . Évalué à 3.

      printf("%s",tampon[i]);
      Ca sert à quoi à part afficher n'importe quoi à l'ecran et eventuellement planter ?
      Bon, pour le plantage, je crois que ça mérite un peu plus d'explications (autant je préfère ne pas donner de solutions toutes faites la plupart du temps, autant certains points diffciles méritent d'être expliqués)...
      read() lit au plus N octets (*) et les place dans le tampon qu'on lui donne en paramètre. Au contraire des fonctions de la bibiothèque standard dédiées au traitement de chaînes de caractères, read() NE met PAS de caractère '\0' pour terminer la chaîne (c'est une lecture binaire). Au contraire, printf() attend une chaîne de caractères au sens C, i.e. terminée par '\0'. D'où un gros souci potentiel...

      Dans ton cas, la chaîne de format "%s" spécifie qu'on affiche le contenu de tampon[i] (supposé de type char *) sur la sortie standard, jusqu'à soit le premier caractère d'espacement, soit la fin de la chaîne. Donc :
      - si tampon[i] contient une espace, alors printf s'arrète là ;
      - sinon elle continue jusqu'à la fin de tampon[i], et essaye d'aller plus loin. Elle déborde donc le tampon et, au sens de la norme C, cause un comportement indéfini de ton programme.

      En pratique, ce comportement indéfini se traduira très probablement soit par l'affichage de données supplémentaires (qui traînent sur la pile), soit par une erreur de segmentation, soit le premier cas suivi du second.

      (*) Sans aller regarder la doc de plus près, je suppose que c'est le read de POSIX. Dans ce cas on a de plus CHAR_BIT == 8, et on peut donc traduire joyeusement "byte" par "octet" sans se soucier d'architectures ésotériques comme certains mainframes ou DSP.
    • [^] # Re: alors

      Posté par  . Évalué à 0.

      Pardont pour le dérangement mais j'ai juste une petite question:
      comment afficher vers stdout svp?
      car quand je lis le man les arguments qu'on passe à write sont:
      le descripteur de fichier, le tampon et la taille du tampon.
      Bien à vous.
  • # Accolades...

    Posté par  . Évalué à 2.

    En plus de ce qui a déjà été dit (et que j'approuve), je te conseille d'éditer ton code avec un éditeur qui favorise l'indentation automatique... (ou au moins indent pour harmoniser le style sur tous tes fichiers C) :
    /* includes... */
    int main (int argc, char *argv[])
    {
        /* definitions des variables... */
        for (i = 0; i < argc; i++)
        {
            d = open(argv[i], O_RDONLY);
            if (d == -1)
            {
                printf("these file does not exist check the name\n");
                exit(1);
            }
            else
                byte_lu = read(d, tampon, 1024);
            while (byte_lu > 0)
            {
                fd = write(d, tampon, 1024);
            }
            printf("%s", tampon[i]);
        }
        close (d);
    }
    Tu ne remarques rien d'anormal ? (un indice est dans le titre)
    • [^] # Re: Accolades...

      Posté par  . Évalué à 2.

      Je répond ici c'que c'est bien indenté :)

      Toujours le même problème quand dans ton précédent journal : le premier argc == ton prog lui même == a.out ! forcemment, ça doit faire bizare a ton term a chaque fois que t'execute! ==> modifie ton for() pour éviter ça.

      Autrement, l'autre truc vraiment ENORME en plus de tout c'qui à été dis dans l'autre journal, c'est le fd = write(). write() ne renvoie pas un descripteur de fichier (qui d'ailleur n'est pas utiliser), mais un ssize_t (man 2 write). Je serais toi, je bouclerai avec le read comme condition.

      Allé, tant que j'y suis, tu close des fichiers non ouvert et tu continu d'exit au lieu de return.

      Pour moi, t'étais moin loin de la solution dans ta précedente version.
      Essaye de dérouler ton algo dans ta tête et de comprendre précisemment ce qu'il fait. Là on a l'impression que tu fait des trucs sans vraiment comprendre c'que tu fait.

      PS : excuse moi le ton peut être un peu hautain, mais c'est ton deuxième journal et la plupart de tes problèmes ont déjà été répondu dans le précedent.
      • [^] # Re: Accolades...

        Posté par  . Évalué à 2.

        Je répond ici c'que c'est bien indenté :)
        Merci ;)

        En indentant, je voulais juste montrer des choses que d'autres ont fait remarquer, mais qui n'était pas évidentes sur un code "plat". En particulier:
        - le close() est perdu tout seul en-dehors de la boucle principale... On ne fermera donc qu'un fichier au plus ! Le close devrait être en fin du else, dans la boucle.
        - le else ne contient qu'une seule instruction ! Soit il manque les accolades autour de tout le bloc qui suit, soit on se repose sur le fait qu'il y ait un exit dans le if pour ne pas faire de else (les deux styles existent, chacun fait son choix). Mais je penche pour un oubli des accolades (ça arrive à tout le monde).
        - la boucle d'écriture while (byte_lu > 0) ne contient pas le read. Donc, comme dit par ailleurs, boucle infinie.

        Plus que l'utilisation des fonctions read et write, le fait d'avoir mal placé le close par rapport à la boucle sur les paramètres, ou le read par rapport à la boucle de lecture/écriture, montre qu'il y a qu'il faut surtout travailler sur l'algorithmique et la manière de traduire un algorithme en "pseudo-langage" (ou tout formalisme que tu as pu apprendre dans tes cours) vers un programme C.

        Ce ne sont pas des erreurs graves, loin de là ; ce genre d'exercices est justement fait pour les corriger. Mon conseil d'utiliser un éditeur qui fait de l'indentation automatique (ou un outil comme indent) est lié au fait qu'une bonne indentation (et une coloration syntaxique) du code permet de mieux voir les blocs de code, et de repérer les erreurs de ce genre.
  • # Juste un truc qui saute aux yeux

    Posté par  . Évalué à 2.

    Sans lire trop dans le détail, il y a un soucis assez flagrant:

    tu fais:
    while (byte_lu > 0)

    ensuite, dans cette boucle while, la variable byte_lu n'est jamais modifiée.
    tu rentre donc forcément dans une boucle infinie à partir du moment où la valeur
    initiale de byte_lu est supérieur à 0

    Ensuite, il y a aussi le fait que tu réécris ce que tu as lu (la variable tampon), dans le fichier ou tu la lue (le descripteur 'd').

    tu te rapproche plus d'une commande 'cp' que de 'cat'

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.