Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2691 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [C] Compter le nombre de lignes d'un fichier

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] Compter le nombre de lignes d'un fichier

n°1314862
Delantera
Hail Seitan.
Posté le 27-02-2006 à 22:04:35  profilanswer
 

Bonjour,  
 
J'ai cherché partout sur le net mais je trouve pas alors je me permets de poster içi...
 
Je desirerais faire un programme C qui compterai le nombre de lignes d'un fichier mis en paramètre à l'execution, à la manière de la commande Unix wc -l.
Je vous montre ce que j'ai déja fait:
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/stat.h>
  6. #include <errno.h>
  7. #include <time.h>
  8. int main(int argc, char *argv[])
  9. {
  10.   int resopen,l,compt=0;
  11.   char buffer [513];
  12.   if(argc-1!=1)
  13.     {
  14.       printf("le nombre d'arguments est: %d, il devrait être de 1!!!\n            AU REVOIR!!!\n" ,argc-1);
  15.       exit(1);
  16.     }
  17.   if ((resopen=open(argv[1],0))<0)
  18.     {
  19.       perror ("Erreur d'ouverture du fichier" ) ;
  20.       exit (resopen);
  21.     }
  22.   for(;;)
  23.     {
  24.       if (!(l=read(resopen,&buffer,512)))
  25. break ;
  26.       buffer[l]=0;
  27.       printf("%s",buffer);
  28.     }
  29.   if(close(resopen))
  30.     {
  31.       perror("Erreur de fermeture du fichier" );
  32.       exit (2);
  33.     }
  34. }


 
Je sais vraiment pas comment faire, j'ai pensé à faire un compteur mais je sais pas comment parcourir le fichier!
 
Merci de votre aide...  
 
PS: je sais que j'ai pas besoin de toutes ces libs, mais j'ai fait un copier/coller d'un autre prog.
 
:hello:


Message édité par Delantera le 27-02-2006 à 22:17:09
mood
Publicité
Posté le 27-02-2006 à 22:04:35  profilanswer
 

n°1314881
skelter
Posté le 27-02-2006 à 22:39:34  profilanswer
 

te fais pas chier avec les i/o posix (open, read,...), utilise fopen et le type FILE, apres il suffit de boucler sur fgetc et de compter le nombre de caractere ayant la valeur '\n' (le nombre de ligne == le nombre de caractere de fin de ligne)

n°1314926
matafan
Posté le 27-02-2006 à 23:36:09  profilanswer
 

Sauf eventuellement pour la derniere ligne.

n°1314943
skelter
Posté le 27-02-2006 à 23:50:17  profilanswer
 

non, en fait '\n' est un caractere de fin de ligne ou de nouvelle ligne (n -> newline), le compte est toujours bon et si tu fais allusion à un fichier qui se termine par un '\n' ca veut juste dire qu'il se termine par une ligne vide

Message cité 1 fois
Message édité par skelter le 27-02-2006 à 23:50:32
n°1314983
s0d4
Je charge des sacs de sable
Posté le 28-02-2006 à 00:41:11  profilanswer
 

skelter a écrit :

te fais pas chier avec les i/o posix (open, read,...), utilise fopen et le type FILE, apres il suffit de boucler sur fgetc et de compter le nombre de caractere ayant la valeur '\n' (le nombre de ligne == le nombre de caractere de fin de ligne)


 
 
Cependant, cette solution est clairement très couteuse. En gros, tu provoques plein d'I/O caractère par caractère, ce qui est très porc. Le mieux est donc de prendre bloc par bloc de 1024 octets (par exemple) et de parcourir ce buffer (tu lis ensuite la mémoire octet par octet). Ce n'est pas une solution très élégante non plus, mais c'est une des premières idées qui me vient.

n°1314984
chrisbk
-
Posté le 28-02-2006 à 00:43:13  profilanswer
 

mes fesses, memory mapping sur le fichier, parcours de bourrin pour trouver \n et vlan.  
 
cinq lignes de code a tout peter, et peinard niveau perfos

n°1314985
chrisbk
-
Posté le 28-02-2006 à 00:43:40  profilanswer
 

le memory mapping pour les fichiers textes, la solution pour nous, les feneasses

n°1315008
matafan
Posté le 28-02-2006 à 03:43:24  profilanswer
 

skelter a écrit :

non, en fait '\n' est un caractere de fin de ligne ou de nouvelle ligne (n -> newline), le compte est toujours bon et si tu fais allusion à un fichier qui se termine par un '\n' ca veut juste dire qu'il se termine par une ligne vide


Non, je pensais au cas (courant) où la dernière ligne ne se termine pas pas "\n".
 

s0d4 a écrit :

Cependant, cette solution est clairement très couteuse. En gros, tu provoques plein d'I/O caractère par caractère, ce qui est très porc. Le mieux est donc de prendre bloc par bloc de 1024 octets (par exemple) et de parcourir ce buffer (tu lis ensuite la mémoire octet par octet). Ce n'est pas une solution très élégante non plus, mais c'est une des premières idées qui me vient.


C'est justement en gros ce que fait la libc avec fread. D'où le conseil skelter d'utiliser fopen/fread plutôt que open/read. Réinventer la roue et se faire des buffers à la main, c'est stupide.

n°1315027
franceso
Posté le 28-02-2006 à 09:12:48  profilanswer
 

pourquoi pas une boucle sur un fgets() ?

n°1315048
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-02-2006 à 09:55:42  profilanswer
 

s0d4 a écrit :

Cependant, cette solution est clairement très couteuse. En gros, tu provoques plein d'I/O caractère par caractère, ce qui est très porc.


Pas sûr. Sur les systèmes modernes, les fonctions standards sont bufferisées et optimisées, et les I/Os réels sont automatiquement limités au strict minimum. Le premier fgetc() va par exemple appeler read(fd, block, 512), le second va fouiller dans le bloc chargé. etc.
 
Faire des mesures avant de se lancer dans des raisonnements douteux...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
mood
Publicité
Posté le 28-02-2006 à 09:55:42  profilanswer
 

n°1315050
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-02-2006 à 09:57:22  profilanswer
 

matafan a écrit :

Non, je pensais au cas (courant) où la dernière ligne ne se termine pas pas "\n".


Dans ce cas, ce n'est pas une ligne -> poubelle.
 
La prochaine fois, le gars qui écrit le fichier texte fera attention...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1315052
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-02-2006 à 09:59:59  profilanswer
 

franceso a écrit :

pourquoi pas une boucle sur un fgets() ?


Parce qu'on ne connait pas la longueur des lignes à l'avance. Il va falloir appeler strchr() à chaques fois pour savoir si la ligne est complète... Pas efficace. La seule méthode standard efficace est la lecture par bytes et le comptage direct des '\n'. Ensuite la méthode avec mmap() est encore meilleure, mais non standard.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1315061
skelter
Posté le 28-02-2006 à 10:12:43  profilanswer
 

jamais utilisé mais les fonctions setbuf et setvbuf sont standards (c89)

n°1315068
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-02-2006 à 10:20:03  profilanswer
 

skelter a écrit :

jamais utilisé mais les fonctions setbuf et setvbuf sont standards (c89)


Et ? Les reglages par défaut sont, en principe, optimsés pour le système. Les modifier risque de réduire les performances...
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1315071
skelter
Posté le 28-02-2006 à 10:25:57  profilanswer
 

je sais pas, on peut avoir de meilleurs performances avec un buffer plus gros sans rien changer au code ?

n°1315072
chrisbk
-
Posté le 28-02-2006 à 10:27:39  profilanswer
 

ca te dis mon gros buffer dans tes petites performances ?

n°1315076
skelter
Posté le 28-02-2006 à 10:33:38  profilanswer
 

oue de toute facon suffit d'essayer mais moi je m'en fout j'ai jamais utilisé ni meme vos pas portable de file mapping

n°1315078
chrisbk
-
Posté le 28-02-2006 à 10:34:57  profilanswer
 

le file mapping, c'est du bonheur en barre à tartiner. ca te fait genre un gros char * en mémoire (sauf que le \0 a la fin est pas garanti, donc strn* en force) et vlan. En plus sous nux c'est tout con a faire (sous win c'est un peu plus pénible).  

n°1315100
Delantera
Hail Seitan.
Posté le 28-02-2006 à 10:54:19  profilanswer
 

Merci pour vos réponses!
 
En fait je DOIS utiliser les I/O posix bas niveau pour ce programme, c'est un tp et la je sèche vraiment!  
 
Sinon ya pas moyen d'utiliser la commande système wc -l directement dedans?
 
:hello:

n°1315109
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-02-2006 à 10:58:39  profilanswer
 

Delantera a écrit :

En fait je DOIS utiliser les I/O posix bas niveau pour ce programme, c'est un tp et la je sèche vraiment!


C'est nul. C'est quoi cette école ?

Citation :

Sinon ya pas moyen d'utiliser la commande système wc -l directement dedans?


Ben si, avec system()...
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1315148
Delantera
Hail Seitan.
Posté le 28-02-2006 à 11:30:31  profilanswer
 

Ben c pour nous apprendre a utiliser le bas niveau, la suite du TP est en haut niveau :D et pi c un IUT info :)
 
Je vais essayer avec system() alors, merci :)

n°1315152
chrisbk
-
Posté le 28-02-2006 à 11:32:09  profilanswer
 

Emmanuel Delahaye a écrit :

C'est nul. C'est quoi cette école ?


bah entre ca et les profs de C++ qui refusent que leur eleves utilisent la STL et les force a utiliser du char * ... [:el g]

n°1315446
Sve@r
Posté le 28-02-2006 à 16:16:53  profilanswer
 

Delantera a écrit :

Sinon ya pas moyen d'utiliser la commande système wc -l directement dedans?


"wc" n'est pas une commande système, c'est une commande point. Un gars a un jour écrit un pgm en C qui prend 30 lignes et l'a nommé "wc.c" puis l'a compilé. Mais pour répondre à ta question, si vraiment c'est un devoir alors le prof fera un peu plus que d'exécuter ton code, il jettera aussi un oeuil dedans...
 

Delantera a écrit :

En fait je DOIS utiliser les I/O posix bas niveau pour ce programme, c'est un tp et la je sèche vraiment!


 
Méthode bourrin


...
char buf;
unsigned long cptLig=0;
...
while (read(resopen, &buf, 1) > 0)
    if (buf == '\n')
        cptLig++;
...

   


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1315575
Delantera
Hail Seitan.
Posté le 28-02-2006 à 18:51:42  profilanswer
 

C'est pas un devoir mais un TP personnel, je suis pas noté dessus!
 
Merci pour ta réponse, je vais essayer ça!
 
:hello:

n°1315604
Emmanuel D​elahaye
C is a sharp tool
Posté le 28-02-2006 à 19:44:55  profilanswer
 

Delantera a écrit :

C'est pas un devoir mais un TP personnel, je suis pas noté dessus!


Alors profites en pour apprendre à utiliser les fonctions du C et pas les fonctions de quelque obscur système...
 
fgetc()
 
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1315619
Delantera
Hail Seitan.
Posté le 28-02-2006 à 20:23:58  profilanswer
 

Ca marche, merci bien  :D  
Bon si j'ai 3 lignes avec pas de retour à la ligne ça m'en marque que 2 mais ça ira merci :)

n°1315720
Sve@r
Posté le 28-02-2006 à 23:02:12  profilanswer
 

Delantera a écrit :

C'est pas un devoir mais un TP personnel, je suis pas noté dessus!


Ben alors essaye de partir de cette base en l'améliorant. Par exemple, au lieu de lire un caractère à la fois que tu stockes dans un "char", lis-en "n" à la fois que tu stockeras dans un tableau de "char [n]" ("n" pouvant être de la valeur que tu veux mais sans dépasser 32767). Et ensuites, tu balayes ce tableau en utilisant un pointeur (pour t'entrainer à les manipuler) en comptabilisant chaque '\n'. Et sans oublier que ce n'est pas parce que tu lis "n" caractères que t'en auras forcément "n" qui te seront donnés (surtout à la fin du fichier) mais en sachant que la valeur que renvoie "read" est justement le nombre de caractères réellement lus...

Delantera a écrit :

Ca marche, merci bien  :D

 
Evidemment...

Delantera a écrit :

Bon si j'ai 3 lignes avec pas de retour à la ligne ça m'en marque que 2 mais ça ira merci :)


Ben si t'as pas de retour à la ligne c'est que ta ligne n'est pas complète donc ce n'est pas une ligne...
 


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1317523
s0d4
Je charge des sacs de sable
Posté le 03-03-2006 à 02:10:33  profilanswer
 

Emmanuel Delahaye a écrit :


Faire des mesures avant de se lancer dans des raisonnements douteux...


 
Bravo, tu viens d'apprendre ce qu'est le buffer cache dans un noyau. Cependant, ce n'est pas une raison pour coder comme un porc. Si demain tu arrives sur un système qui n'a pas un tel système de cache (embarqué, etc ...), tu seras bien dans la merde. Donc, bien coder, prendre des bonnes habitudes, cela se fait tout le temps.

n°1317540
matafan
Posté le 03-03-2006 à 07:32:38  profilanswer
 

Rien à voir avec un quelconque "buffer cache dans un noyau". Et les fopen, fgetc et autres setvbuf font partie du C ANSI. Si tu veux prendre les gens de haut, fais le plutôt sur un sujet que tu maitrise.

n°1318305
s0d4
Je charge des sacs de sable
Posté le 04-03-2006 à 03:38:01  profilanswer
 

Ah ? tu crois que c'est ta fonction fgets qui va aller bufferiser ce qu'il y a avant/après ce qu'il y a ce que tu souhaites lire ? Non. fgets fait lui un appel système (read), qui lui ensuite va aller voir dans le noyal ce qu'il faut prendre, et le noyal va lire plus de données qu'il n'en faut pour ne pas avoir à lire au prochain read. On appelle ça un cache, et là, en l'occurence, le buffer cache ... C'est ce que notre ami nous expliquait. Et mon post disait que oui, ça permet d'avoir une bonne vitesse d'execution, mais ça ne permettait pas de s'affranchir de bien coder.
 
 
Bon, après, tu peux faire ce que tu veux, hein, penser que finalement, tes fonctions posix de merde font tout et même le café, grand bien te fasse, mais bon, hein, quand même.

n°1318306
matafan
Posté le 04-03-2006 à 04:15:16  profilanswer
 

Perdu. Oui justement, la bufferisation est faite par la libc. Quand tu fais un appel a fgetc, la libc va typiquement appeler read (le sytem call) pour lire un bloc complet de données (généralement 4kB, mais ça peut évidemment varier d'une platefome à l'autre). Les appels ultérieurs à fgetc piochent ensuite dans le buffer de la libc, sans appel à read. L'avantage c'est que ca limite le nombre de system call, qui sont en toujours en eux-même très couteux (sauvegarde du contexte, copyout...).
 
Puisque tu m'a l'air difficile à convaincre, je te suggère d'écrire un petit programe et de vérifier avec strace ce qui se passe quand tu l'exécutes.

n°1318314
Emmanuel D​elahaye
C is a sharp tool
Posté le 04-03-2006 à 08:31:35  profilanswer
 

matafan a écrit :

Perdu. Oui justement, la bufferisation est faite par la libc. Quand tu fais un appel a fgetc, la libc va typiquement appeler read (le sytem call) pour lire un bloc complet de données (généralement 4kB, mais ça peut évidemment varier d'une platefome à l'autre). Les appels ultérieurs à fgetc piochent ensuite dans le buffer de la libc, sans appel à read. L'avantage c'est que ca limite le nombre de system call, qui sont en toujours en eux-même très couteux (sauvegarde du contexte, copyout...).


Absolument. Et la taille de ces fameux buffers de la libc sont gérés par les fonctions standard setbuf() et setvbuf().
 
http://maconlinux.net/linux-man-pages/fr/setbuf.3.html
http://maconlinux.net/linux-man-pa [...] buf.3.html


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1319791
s0d4
Je charge des sacs de sable
Posté le 06-03-2006 à 20:43:18  profilanswer
 

matafan a écrit :

Perdu. Oui justement, la bufferisation est faite par la libc. Quand tu fais un appel a fgetc, la libc va typiquement appeler read (le sytem call) pour lire un bloc complet de données (généralement 4kB, mais ça peut évidemment varier d'une platefome à l'autre). Les appels ultérieurs à fgetc piochent ensuite dans le buffer de la libc, sans appel à read. L'avantage c'est que ca limite le nombre de system call, qui sont en toujours en eux-même très couteux (sauvegarde du contexte, copyout...).
 
Puisque tu m'a l'air difficile à convaincre, je te suggère d'écrire un petit programe et de vérifier avec strace ce qui se passe quand tu l'exécutes.


 
 
Shame on me !
 
Bon, cela dit, je maintiens toujours que c'est pas parce que la libc bufferise comme une grande qu'il faut coder comme un porc :-)

n°1319794
chrisbk
-
Posté le 06-03-2006 à 20:51:54  profilanswer
 

s0d4 a écrit :

Ah ? tu crois que c'est ta fonction fgets qui va aller bufferiser ce qu'il y a avant/après ce qu'il y a ce que tu souhaites lire ? Non. fgets fait lui un appel système (read), qui lui ensuite va aller voir dans le noyal ce qu'il faut prendre, et le noyal va lire plus de données qu'il n'en faut pour ne pas avoir à lire au prochain read. On appelle ça un cache, et là, en l'occurence, le buffer cache ... C'est ce que notre ami nous expliquait. Et mon post disait que oui, ça permet d'avoir une bonne vitesse d'execution, mais ça ne permettait pas de s'affranchir de bien coder.
 
 
Bon, après, tu peux faire ce que tu veux, hein, penser que finalement, tes fonctions posix de merde font tout et même le café, grand bien te fasse, mais bon, hein, quand même.


 
j'adore ce genre de post plein de diplomacie, de pédagogie et surtout, de modestie .... ...... et completement faux [:pingouino]
 
merci donc pour ce grand moment [:dawa]
 

n°1319797
Emmanuel D​elahaye
C is a sharp tool
Posté le 06-03-2006 à 20:56:38  profilanswer
 

s0d4 a écrit :

Shame on me !
 
Bon, cela dit, je maintiens toujours que c'est pas parce que la libc bufferise comme une grande qu'il faut coder comme un porc :-)


Et utiliser les fonctions standard, c'est programmer comme un porc ? Alors groiiink.
http://www.old-hippie.com/sound_fi [...] /1pig1.wav
http://www.haut-rhin.chambagri.fr/IMAGES/productions/porcelet.jpg


Message édité par Emmanuel Delahaye le 06-03-2006 à 20:59:31

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1319800
chrisbk
-
Posté le 06-03-2006 à 21:00:18  profilanswer
 

un vrai codeur recode tout lui meme :o
 
(d'ailleurs j'en chie dans ma pile TCP la)

n°1319908
0x90
Posté le 07-03-2006 à 08:40:53  profilanswer
 

chrisbk a écrit :

un vrai codeur recode tout lui meme :o
 
(d'ailleurs j'en chie dans ma pile TCP la)


 
fait comme tout le monde, utilise celle de BSD  [:0x90]
 
 
 
( et coder propre malgrès les fct déja existantes c'est malin, tu te retrouve avec deux buffers en enfilade, un qui sert a rien, qui bouffe de la mémoire, du code pour le gérer qui sert aussi à rien, et qui est susceptible comme tout bon code de contenir des erreurs. de la propreté qui réduis les perfs tout en rendant le code moins compréhensible, bravo :jap: )


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [C] Compter le nombre de lignes d'un fichier

 

Sujets relatifs
Compter le nombre de fois qu'une expression revientcomment passer d un fichier d une classe a des fichiers d une classe?
lecture de fichier avec sscanfenegistrement fichier
téléchargement fichier audio avec paypalFichier CONF
Fonction : Si un nombre et negatif[debutant C++] [Urgent] Tableau 2D nombre de colonne inconnu
XML XSL et fichier volumineux : 100 Mo 
Plus de sujets relatifs à : [C] Compter le nombre de lignes d'un fichier


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR