web-dev-qa-db-fra.com

compter le nombre de lignes dans un fichier texte

Je lis les lignes d'un fichier texte et je me demande si c'est une bonne façon de faire? J'ai dû écrire la fonction numberoflines pour diminuer le number_of_lines variable de un, car dans la boucle while, chaque ligne lue ajoute 2 à la variable number_of_lines.

#include <iostream>
#include <fstream>
using namespace std;

int number_of_lines = 0;

void numberoflines();
int main(){
    string line;
    ifstream myfile("textexample.txt");

    if(myfile.is_open()){
        while(!myfile.eof()){
            getline(myfile,line);
            cout<< line << endl;
            number_of_lines++;
        }
        myfile.close();
    }
    numberoflines();

}

void numberoflines(){
    number_of_lines--;
    cout<<"number of lines in text file: " << number_of_lines << endl;
}

Y a-t-il une autre meilleure façon plus facile?

21
silent

Votre hack de décrémenter le compte à la fin est exactement cela - un hack.

Il est de loin préférable d’écrire correctement votre boucle pour qu’elle ne compte pas deux fois la dernière ligne.

int main() { 
    int number_of_lines = 0;
    std::string line;
    std::ifstream myfile("textexample.txt");

    while (std::getline(myfile, line))
        ++number_of_lines;
    std::cout << "Number of lines in text file: " << number_of_lines;
    return 0;
}

Personnellement, je pense que dans ce cas, le code de style C est parfaitement acceptable:

int main() {
    unsigned int number_of_lines = 0;
    FILE *infile = fopen("textexample.txt", "r");
    int ch;

    while (EOF != (ch=getc(infile)))
        if ('\n' == ch)
            ++number_of_lines;
    printf("%u\n", number_of_lines);
    return 0;
}

Edit: Bien sûr, C++ vous permettra également de faire quelque chose de similaire:

int main() {
    std::ifstream myfile("textexample.txt");

    // new lines will be skipped unless we stop it from happening:    
    myfile.unsetf(std::ios_base::skipws);

    // count the newlines with an algorithm specialized for counting:
    unsigned line_count = std::count(
        std::istream_iterator<char>(myfile),
        std::istream_iterator<char>(), 
        '\n');

    std::cout << "Lines: " << line_count << "\n";
    return 0;
}
51
Jerry Coffin

Je pense que votre question est, "pourquoi est-ce que je reçois une ligne de plus que le fichier?"

Imaginez un fichier:

line 1
line 2
line 3

Le fichier peut être représenté dans ASCII comme ceci:

line 1\nline 2\nline 3\n

(Où \n est un octet 0x10.)

Voyons maintenant ce qui se passe avant et après chaque appel getline:

Before 1: line 1\nline 2\nline 3\n
  Stream: ^
After 1:  line 1\nline 2\nline 3\n
  Stream:         ^

Before 2: line 1\nline 2\nline 3\n
  Stream:         ^
After 2:  line 1\nline 2\nline 3\n
  Stream:                 ^

Before 2: line 1\nline 2\nline 3\n
  Stream:                 ^
After 2:  line 1\nline 2\nline 3\n
  Stream:                         ^

Maintenant, vous penseriez que le flux marquerait eof pour indiquer la fin du fichier, non? Nan! Cela est dû au fait que getline définit eof si le marqueur de fin de fichier est atteint "pendant son fonctionnement" . Étant donné que getline se termine lorsqu'il atteint \n, le marqueur de fin de fichier n'est pas lu et eof n'est pas marqué. Ainsi, myfile.eof() renvoie false et la boucle effectue une autre itération:

Before 3: line 1\nline 2\nline 3\n
  Stream:                         ^
After 3:  line 1\nline 2\nline 3\n
  Stream:                         ^ EOF

Comment réparez-vous ceci? Au lieu de rechercher eof(), voyez si .peek() renvoie EOF:

while(myfile.peek() != EOF){
    getline ...

Vous pouvez également vérifier la valeur de retour de getline (transtypage implicite en bool):

while(getline(myfile,line)){
    cout<< ...
5
strager

En C, si vous implémentez la ligne de décompte, elle ne faillira jamais . Oui, vous pouvez obtenir une ligne supplémentaire s'il y a un "ENTER KEY" généralement à la fin du fichier.

Le fichier peut ressembler à quelque chose comme ça:

"hello 1
"Hello 2

"

Code ci-dessous

#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "file1.txt"

int main() {

    FILE *fd = NULL;
    int cnt, ch;

    fd = fopen(FILE_NAME,"r");
    if (fd == NULL) {
            perror(FILE_NAME);
            exit(-1);
    }

    while(EOF != (ch = fgetc(fd))) {
    /*
     * int fgetc(FILE *) returns unsigned char cast to int
     * Because it has to return EOF or error also.
     */
            if (ch == '\n')
                    ++cnt;
    }

    printf("cnt line in %s is %d\n", FILE_NAME, cnt);

    fclose(fd);
    return 0;
}
0
ashish