Is there a way to find the line number of the current line being read from a file?

孤街醉人 提交于 2020-01-01 19:10:18

问题


1) Is there a way in C that we could find the line number of a line that we are reading from a file.

2) I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.


回答1:


1)Is there a way in C that we could find the line number of a line that we are reading from a file.

Not unless you count the lines from the beginning of the file. You can't just position yourself arbitrarily in a file and know what line of text you're on, unless there is information in the file itself telling you, or you have created an index of sorts by a previous pass over the file. The usual approach is to accumulate a line count as you process lines from the file.

2)I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.

No. You must run through the whole the file and count the number of lines. Any external tools (such as wc) are doing exactly this. You need to be aware of different line-ending styles. Depending on what functions you are using to read the file, you may or may not have automatic newline translation.




回答2:


You can count the line endings as they go by. Of course, line endings vary depending on platform. UNIX uses \n, Mac uses \r (or at least they used to), and Windows uses \r\n.

You could look at the source code to wc (a standard UNIX utility that counts lines, characters, etc. in a file). Here's OpenBSD's wc source.




回答3:


I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.

You can use popen along with the command

wc -l filename

or the command

sed -n '$=' loop.c

To know more, read how th popen function is used. Here is an example

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

int main(void)
{
    FILE* p;
    int a;
    char str[10];

    p = popen("sed -n '$=' loop.c", "r");
    fgets(str, 10, p);                
    a = atoi(str);

    printf("%d", a);
}



回答4:


1) Is there a way in C that we could find the line number of a line that we are reading from a file.

Yes and no. As others have said, there is no mechanism, by file positions alone that you can find the line number you are reading at any given point in time while reading a file. That doesn't mean you cannot easily track which line you are currently reading and write a conditional to apply to any given line. For instance, a simple way to read from a file (or by default stdin) and track the current as well as find the total number of lines could be something similar to the following:

#include <stdio.h>

#define MAXS 256

int main (int argc, char **argv)
{
    char line[MAXS] = {0};  /* line buffer for fgets */
    long long unsigned index = 0;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    while (fgets (line, MAXS, fp))
    {
        printf (" line[%3llu] : %s", index++ + 1, line);
    }
    if (fp != stdin) fclose (fp);
    printf ("\n total : %llu lines\n\n", index);

    return 0;
}

Use/Output

$ ./bin/fgets_min_count dat/captnjack.txt
 line[  1] : This is a tale
 line[  2] : Of Captain Jack Sparrow
 line[  3] : A Pirate So Brave
 line[  4] : On the Seven Seas.

 total : 4 lines

2) I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.

Depending on the size of the file and number of lines you need to count, minimizing the number of reads can greatly improve the efficiency of your count. For lack of better words, you can read the entire file into a buffer in a single read (for all files of INT_MAX bytes or less) or in a limited number of INT_MAX sized reads an then simply count the '\n' characters (testing/adjusting for text without a '\n' (either as the first line, or last without a POSIX line-end).

The code is just slightly longer to account for the size limitations for fread:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>  /* for INT_MAX */

char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp);
long buf_lines (char *s, long len);

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

    char *filebuf = NULL;
    long fplen = 0, nlines = 0;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open */
        fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
        return 1;
    }

    /* read entire file into filebuf*/
    if (!read_file_into_buf (&filebuf, &fplen, fp)) return 1;
    if (fp != stdin) fclose (fp);

    nlines = buf_lines (filebuf, fplen); /* count lines */

    printf ("\n total : %ld  lines read (from '%s')\n\n", 
            nlines, argc > 1 ? argv[1] : "stdin");

    free (filebuf);

    return 0;
}

/** read file from 'fp' into 'filebuf', update 'fplen'.
 *  memory is allocated for filebuf sufficient to hold
 *  contents of 'fp'. returns pointer to 'filebuf' on
 *  success, NULL otherwise. reads at most INT_MAX bytes
 *  at a time from file.
 */
char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp)
{
    if (!fp) return NULL;

    size_t nbytes = 0, readsz = 0;
    long  bytecnt = 0;

    fseek (fp, 0, SEEK_END);
    if ((*fplen = ftell (fp)) == -1) {  /* get file length */
        fprintf (stderr, "error: unable to determine file length.\n");
        return NULL;
    }
    fseek (fp, 0, SEEK_SET);  /* allocate memory for file */
    if (!(*filebuf = calloc (*fplen, sizeof **filebuf))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return NULL;
    }

    /* read entire file into filebuf reading a
     * maximum of INT_MAX bytes at a time */
    readsz = *fplen > INT_MAX ? INT_MAX : *fplen;
    while ((nbytes = fread ((*filebuf + bytecnt),
        sizeof **filebuf, readsz, fp))) {

        bytecnt += nbytes;

        if (nbytes != readsz) fprintf (stderr, "warning: short read.\n");
        if (bytecnt == *fplen) break;

        readsz = *fplen - bytecnt > INT_MAX ? INT_MAX : *fplen - bytecnt;
    }
    if (bytecnt != *fplen) {
        fprintf (stderr, "error: file read failed.\n");
        return NULL;
    }

    return *filebuf;
}

/** count lines in buffer
 *  (line with non-POSIX line end counted as 1)
 */
long buf_lines (char *fb, long len)
{
    long i = 0, lns = 0;
    for (;;) {
        if (fb[0] == '\n') lns++;
        if (++i == len) { if (fb[0] != '\n') lns++; return lns; }
        if (fb[1] == '\n') lns++;
        if (++i == len) { if (fb[1] != '\n') lns++; return lns; }
        if (fb[2] == '\n') lns++;
        if (++i == len) { if (fb[2] != '\n') lns++; return lns; }
        if (fb[3] == '\n') lns++;
        if (++i == len) { if (fb[3] != '\n') lns++; return lns; }
        fb += 4;
    }
}

Use/Output

$ ./bin/fread_file_count dat/captnjack.txt

 total : 4  lines read (from 'dat/captnjack.txt')


来源:https://stackoverflow.com/questions/34868792/is-there-a-way-to-find-the-line-number-of-the-current-line-being-read-from-a-fil

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!