Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

compter le nombre de lignes d'un fichier

24 réponses
Avatar
Zulfukar Arslan
Bonjour a tous,

J'ai une petite appli en C qui doit connaitre le nombre de lignes de
deux fichiers avant de faire des calculs. Comment connaitre ce nombre de
lignes?

Merci.

AZ.

4 réponses

1 2 3
Avatar
Harpo
Zulfukar Arslan wrote:


Je suis surpris. J'ai rajouté les options de compilation -W -Wall
-stdÈ9. Voila ce qu'il me dit:

warning: unused parameter `argc'.


C'est probablement parce que tu ne l'utilises pas.

En accord avec la solution qui m'a été proposée sur ce forum alors que
je n'avais qu'une solution peu satisfaisante, voilà :

Le compilo te signale aimablement que ta fonction (ici main()) n'utilise
pas un des arguments qui lui est confié, cela peut être très utile pour
un certain nombre de raisons, 2 au hasard :
. Si une fonction n'utilise pas un de ses arguments, il n'est parfois
pas utile de le lui donner.
. Cela ne vaut pas dans le cas de la fonction main() ou de callbacks
dont on n'exploite pas nécessairement toutes les possibilités,
l'interface eétant faite pour un cas plus général.
. Si cela ne faisait pas dépasser le nombre de raisons que je me suis
octroyées, cela pourrait aussi vouloir dire que tu pioches des
arguments sans t'être assuré de leur présence., par exemple, tu
référence argv[3] sans avoir vérifié que le tableau d'arguments a 4
postes.

Lorsque tu as vérifié que tu as tout prévu, le problème est de faire
disparaître ce warning qui peut hérisser les gens qui installent le
logiciel à partir des sources.

Amha, il n'y a pas de bonne solution, mais il y en a de moins mauvaises
que d'autres.
1 - changer le options de compile lorsqu'on livre un logiciel, je ne
m'étendrai pas sur le coté sournoisement pernicieux de cette solution.
2 - Avoir recours à un petit 'hack', avant je mettais :
argc = argc; # ou autre argument que argc
au début de la fonction en espérant vaquement que le compilateur ne
génère aucun code exécutable.
Maintenant, grâce à un conseil qui m'a été donné ici-même, je mets :
(void)argc;
C'est plus subtil, car il y a référence à la variable sans qu'il n'y ait
d'affectation, il devient assez probable que même le compilateur le
plus balourd ne génère aucun code.

Cette solution, si bonne qu'elle soit, n'est pas parfaite du fait
qu'elle inhibe un warning qui pourrait se montrer utile par la suite,
après des modification du code, elle pourrait se montrer intéressante.
C'est quand même la meilleure solution que j'ai trouvée, donc je
l'utilise, je mets '(void)my_arg;' le plus près possible du haut de la
déclaration de la fonction.

--
http://patrick.davalan.free.fr/

Avatar
Antoine Leca
En news:,
Targeur fou va escriure:
Oups,
#if ( __STDC_VERSION__ < 199901L )
#if !defined(__STDC_VERSION__) || ( __STDC_VERSION__ < 199901L )



Mieux :

#if ( __STDC_VERSION__-0 < 199901L )

Avec un préprocesseur pré-ANSI (qui va remplacer le symbole inconnu par
rien), tu te retrouves avec

#if ( -0 < 199901L )

et tu es alors dépendant
1) du support de #if
2) du support des parenthèses dans #if
3) du support des constantes longues dans #if
4) de l'absence de bogues à ce niveau
qui en général sont tous de bon paris.

#if __STDC_VERSION__-0 < 199901

peut être très légèrement meilleur, mais c'est vraiment marginal.
Pour bétonner plus, il faut passer par #ifndef __STDC_VERSION__ #if, mais je
trouves cela lourd au final...

+0 aurait été moins bon, car l'opérateur + unaire est une invention ANSI.


Je suis d'accord que defined est plus largement supporté que la convention
de remplacer au niveau des expression #if un symbole inconnu du
préprocesseur par 0, mais formellement ce sont deux « inventions » du comité
ANSI, et tous les compilateurs conformes C89 non C95 doivent interpréter ta
première proposition comme

#if ( 0 < 199901L )

avec l'effet voulu.


Je ne doute pas que la pratique puisse enseigner d'autres résultats, disons
de pseudo-conformité. :-)


Antoine


Avatar
James Kanze
Targeur fou wrote:

Targeur fou wrote:



Merci pour toutes ces astuces. J'avais pensé aussi à les
donner en argument en utilisant "wc -l fichier" mais j'ai un
probleme pour lire ces arguments. A l'interieur du programme
j'ecris:





int nombre_de_lignes;





nombre_de_lignes = argv[3]; // j'ai déja deux autres parametres
qui sont




les deux fichiers.





Ben si comptes mettre un char * dans un entier, c'est normal
tu récupères n'importe quoi.




Ce qui serait normal, c'est que le code ne se compile pas.



Je ne suis pas d'accord avec toi sur ce point, on n'a pas le
typage fort de C++.


Ce n'est pas une question d'un avis personel. C'est la norme C
qui l'interdit. Et même avant la norme... La conversion
implicite d'un int en pointeur n'a jamais fait partie de C --
K&R (ed. 1) dit à peu près la même chose que la norme C. (C-à-d
qu'il faut que la conversion soit explicite, et qu'elle n'est
autorisée qu'avec un type entier assez grand pour contenir un
pointeur -- qui pourrait ne pas exister.)

On peut même avec certaines implémentations C99 stocker la
valeur d'un pointeur dans un entier de façon sûre avec les
types intptr_t et uintptr_t (stdint.h) via un pointeur de type
void *.


Sauf qu'il faut toujours que la conversion soit explicite. Comme
c'était déjà le cas en K&R.

#if !defined( __STDC__)
#error "Pas une implementation ou une compilation conforme ISO C"
#endif


#if ( __STDC_VERSION__ < 199901L )
#error "Pas une implementation ou une compilation supportant la version
ISO C 1999"
#endif


#include <stdio.h>
#include <stdint.h>


int main(void)
{
intptr_t ptrAsInt = 0;


Tu as dû oublier un #ifdef INTPTR_MAX quelque part. En C99,
l'existance d'intptr_t n'est pas garantie, et on est censé la
tester avant de s'en servir.

void * p = NULL;
char * src = "hello";
char * dst = NULL;


puts(src);


// Une facon idiote de faire dst = src; pour exemple
p = src; // §6.3.2.3


Pas de problème ici.

ptrAsInt = p; // §7.18.1.4


Il faut une conversion explicite ici. Au moins si tu as un
compilateur C.

p = ptrAsInt; // §7.18.1.4


De même.

Voir §6.5.4/3 : "Conversions that involve pointers, other than
where permitted by the constraints of 6.5.16.1, shall be
specified by means of an explicit cast." Ou §14.4 du K&R1 :
«@Certain conversions on pointers are permitted but have
implementation-dependant aspects. They are all specified by
means of an explicit type-conversion operator. » Ça, c'est 1978,
et ça n'a pas changé depuis. (Mais ailleurs, K&R 1 avoue que
certains compileurs anciens l'acceptaient. Il a donc bien existé
en C, mais a été enlevé avant 1978. Alors, si tu as du code
écrit avant 1978, il se peut que tu le vois.)

dst = p; // §6.3.2.3


puts(dst);


return 0;
}


Par contre, il est bien dit dans §7.18.1.4 de ma n1124 que les
types intptr_t et uintptr_t sont optionnels. Je n'ai trouvé
nulle part le moyen de savoir si ces types étaient présents ou
non dans une implémentation C99 donnée, à part bien sûr se
faire jeter à la compil'.


Pour un type <t> définit dans §7.18.1, si le type est présent,
<t>_MAX et <t>_MIN (voir §7.18.2) doivent être définis, sinon
non.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34




Avatar
Targeur fou

Salut,

Targeur fou wrote:

Targeur fou wrote:

Merci pour toutes ces astuces. J'avais pensé aussi à les
donner en argument en utilisant "wc -l fichier" mais j'ai un
probleme pour lire ces arguments. A l'interieur du programme
j'ecris:

int nombre_de_lignes;

nombre_de_lignes = argv[3]; // j'ai déja deux autres parametr es
qui sont




les deux fichiers.


Ben si comptes mettre un char * dans un entier, c'est normal
tu récupères n'importe quoi.


Ce qui serait normal, c'est que le code ne se compile pas.


Je ne suis pas d'accord avec toi sur ce point, on n'a pas le
typage fort de C++.


Ce n'est pas une question d'un avis personel. C'est la norme C
qui l'interdit. Et même avant la norme... La conversion
implicite d'un int en pointeur n'a jamais fait partie de C --
K&R (ed. 1) dit à peu près la même chose que la norme C. (C-à-d
qu'il faut que la conversion soit explicite, et qu'elle n'est
autorisée qu'avec un type entier assez grand pour contenir un
pointeur -- qui pourrait ne pas exister.)


Oui, je ne voulais pas dire qu'il s'agissait de ton avis, mais que le
compilateur arrive malgré tout à compiler un tel code, en sortant
juste un warning du style "assignment makes pointer from integer" ou
vice-versa. C'est ce qui est piégeux lorsque c'est la chose que l'on
ne souhaite pas faire comme l'OP et qui fait que l'on récupère
ensuite n'importe quoi sans savoir d'où ça vient, du moins si on ne
prête pas attention aux warnings. Tandis, qu'en C++, clairement,
l'utilisateur se fait jeter à la compilation.

On peut même avec certaines implémentations C99 stocker la
valeur d'un pointeur dans un entier de façon sûre avec les
types intptr_t et uintptr_t (stdint.h) via un pointeur de type
void *.


Sauf qu'il faut toujours que la conversion soit explicite. Comme
c'était déjà le cas en K&R.


Je dirais oui pour ne pas avoir de warnings, mais est-ce un UB pour
autant d'après la norme ?

#if !defined( __STDC__)
#error "Pas une implementation ou une compilation conforme ISO C"
#endif

#if ( __STDC_VERSION__ < 199901L )
#error "Pas une implementation ou une compilation supportant la version
ISO C 1999"
#endif

#include <stdio.h>
#include <stdint.h>

int main(void)
{
intptr_t ptrAsInt = 0;


Tu as dû oublier un #ifdef INTPTR_MAX quelque part. En C99,
l'existance d'intptr_t n'est pas garantie, et on est censé la
tester avant de s'en servir.


C'est cela que je cherchais et que je n'avais pas trouvé.

void * p = NULL;
char * src = "hello";
char * dst = NULL;

puts(src);

// Une facon idiote de faire dst = src; pour exemple
p = src; // §6.3.2.3


Pas de problème ici.

ptrAsInt = p; // §7.18.1.4


Il faut une conversion explicite ici. Au moins si tu as un
compilateur C.

p = ptrAsInt; // §7.18.1.4


De même.

Voir §6.5.4/3 : "Conversions that involve pointers, other than
where permitted by the constraints of 6.5.16.1, shall be
specified by means of an explicit cast." Ou §14.4 du K&R1 :
«@Certain conversions on pointers are permitted but have
implementation-dependant aspects. They are all specified by
means of an explicit type-conversion operator. » Ça, c'est 1978,
et ça n'a pas changé depuis. (Mais ailleurs, K&R 1 avoue que
certains compileurs anciens l'acceptaient. Il a donc bien existé
en C, mais a été enlevé avant 1978. Alors, si tu as du code
écrit avant 1978, il se peut que tu le vois.)

dst = p; // §6.3.2.3

puts(dst);

return 0;
}

Par contre, il est bien dit dans §7.18.1.4 de ma n1124 que les
types intptr_t et uintptr_t sont optionnels. Je n'ai trouvé
nulle part le moyen de savoir si ces types étaient présents ou
non dans une implémentation C99 donnée, à part bien sûr se
faire jeter à la compil'.


Pour un type <t> définit dans §7.18.1, si le type est présent,
<t>_MAX et <t>_MIN (voir §7.18.2) doivent être définis, sinon
non.



OK, c'est noté.

A+
Regis





1 2 3