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.

10 réponses

1 2 3
Avatar
James Kanze
Zulfukar Arslan 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.


Et tu n'as pas d'erreur de compilation ? argv[3] est un pointeur
(char*), et il n'y a pas de conversion implicite de pointeur en
int. Il faut se servir de quelque chose du genre stdtol.

--
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
James Kanze
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.

nombre_de_lignes = (int)strtol(argv[3], NULL,10);
+ éventuellement controle du retour et de errno


Il faut un peu plus quand même. Quelque chose du genre:

char* fin ;
errno = 0 ;
long tmp = strtol( argv[3], &fin, 10 ) ;
if ( errno != 0 || *fin != '' || tmp > INT_MAX || tmp < 0 ) {
// Erreur...
}
nombre_de_lignes = tmp ;

Et évidemment, il faudrait aussi vérifier que argc > 3 avant.

--
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
James Kanze
Harpo wrote:
Zulfukar Arslan wrote:


Ben si comptes mettre un char * dans un entier, c'est normal
tu récupères n'importe quoi.
nombre_de_lignes = (int)strtol(argv[3], NULL,10);
+ éventuellement controle du retour et de errno




Je viens d'essayer. Ca me renvoie tout le temps 0.



T'as du faire une bourde quelque part, le petit programme suivant
marche :


Pas chez moi.

----------
#include <stdio.h>
#include <stdlib.h>
int
main( int argc, char **argv ) {
(void)argc;
printf( "%dn", (int)strtol( argv[1], NULL, 10 ) );
exit( EXIT_SUCCESS );
}
---------
$ gcc -W -Wall -stdÉ9 strtol.c -o strtol
$ ./strtol 421
421


Et ./strtol 1000000000000 ?
Ou ./strtol 1e67 ?
Ou ./strtol -10 ?

C'est peu probable que le programme puisse travailler avec ces
valeurs, mais alors, il faut bien un message d'erreur.

Bingo !


-g -Wall



-g ne devrait pas avoir d'incidence sur les warnings, '-W
-Wall' me semble un bon compromis entre une profusion
d'options et aucune.


On ne doit pas avoir besoin d'une option ; la norme exige un
diagnostique.

--
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
Emmanuel Delahaye
int. Il faut se servir de quelque chose du genre stdtol.

strtol()...


--
A+

Emmanuel Delahaye

Avatar
Emmanuel Delahaye
int. Il faut se servir de quelque chose du genre stdtol.

strtol(), strtod()...


--
A+

Emmanuel Delahaye

Avatar
Pierre Maurette
int. Il faut se servir de quelque chose du genre stdtol.

strtol(), strtod()...

James, Emmanuel,

"C'est le duel effrayant de deux spectres d'airain"

--
Pierre Maurette


Avatar
Harpo
James Kanze wrote:


----------
#include <stdio.h>
#include <stdlib.h>
int
main( int argc, char **argv ) {
(void)argc;
printf( "%dn", (int)strtol( argv[1], NULL, 10 ) );
exit( EXIT_SUCCESS );
}
---------
$ gcc -W -Wall -stdÉ9 strtol.c -o strtol
$ ./strtol 421
421


Et ./strtol 1000000000000 ?


Certes...

Ou ./strtol 1e67 ?


It's a feature !

Ou ./strtol -10 ?


Ca marche.

L'intérêt n'était pas d'écrire un programme bétonné (comme il se doit
pour un programme destiné à tourner) mais de montrer que le problème ne
venait pas de strtol et qu'il y avait un problème dans la manière de
s'en servir.


-g ne devrait pas avoir d'incidence sur les warnings, '-W
-Wall' me semble un bon compromis entre une profusion
d'options et aucune.


On ne doit pas avoir besoin d'une option ; la norme exige un
diagnostique.


Peut-être, mais précise-t-elle la manière de l'appeler (pour qu'il soit
un compilateur C (i.e. conforme à la norme)) ?
Mais je suis d'accord sur le fond, au moins les erreurs et warnings
exigés par la norme devraient être diagnostiqués par défaut.

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


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

warning: unused parameter `argc'.

Et ca marche (stdlib était là), sur un petit code test que je viens
d'ecrire mais pas dans celui ou je voulais qu'il marche. Bizarre!

Bref, c'est pas grave je passe a autre chose.

Merci et bonne journee.



Targeur fou wrote:

Re,


Targeur fou wrote:


Hello,



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.
nombre_de_lignes = (int)strtol(argv[3], NULL,10);
+ éventuellement controle du retour et de errno



Je viens d'essayer. Ca me renvoie tout le temps 0.



As-tu bien inclus <stdlib.h> histoire que le compilo ne s'amuse pas à
essayer de faire semblant de savoir de quelle fonction il s'agit ?
(strtol()) ?


si je fais printf("nombr de lignes %dn", nombre_de_lignes);

il me renvoie "-1073745949". Je pense que la lecture n'est pas bonne.



Si c'est bien le 3ieme arg du programme, y'a pas de raison. C'était
juste la conversion chaine en nombre qui n'était pas faite. A noter
que de bonnes options de compil t'auraient averties de cette conversion
douteuse char * vers int.



-g -Wall



?? Je ne'ai pas la doc de gcc sous la main, mais ca me parait bizare
qu'avec -Wall il ne soit pas verbeux. Mets aussi -stdÈ9 (ou c99, ou
aut' chose) et -W pour voir. Avec le compilo MS CL v12, ce dernier sort
clairement 'int' differs in level of indirection from 'char*'

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char **argv)
{

int entier = 0;
char * nonconvertie = NULL;

/* Doit sortir un joli warning (char* -> int) */
/* entier = argv[0]; */

if (argc!=2) {
fprintf(stderr,"Nb args incorrectn"
"Usage : nom_exe <entier>n");
return EXIT_FAILURE;
}

printf("A convertir : %sn", argv[1]);

entier = (int)strtol(argv[1],&nonconvertie,10);

if ( nonconvertie != NULL) {
printf("Partie non convertie : %sn", nonconvertie);
}

if (errno != 0 ){
puts("Nombre trop grand");
}

if ( !(entier == 0 && strcmp(nonconvertie, argv[1]) == 0) ) {
printf("Entier saisi : %dn", entier);
}

return 0;

}






Avatar
Targeur fou

Salut,

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 q ui 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++. 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 *.

#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;
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
ptrAsInt = p; // §7.18.1.4
p = ptrAsInt; // §7.18.1.4
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'.

A+
Regis



Avatar
Targeur fou

Oups,

[...]

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

#if ( __STDC_VERSION__ < 199901L )
#if !defined(__STDC_VERSION__) || ( __STDC_VERSION__ < 199901L )

#error "Pas une implementation ou une compilation supportant la version
ISO C 1999"
#endif


[...]

1 2 3