简单的C程序逐行读取文件 [英] Simple C program to read a file line by line

查看:89
本文介绍了简单的C程序逐行读取文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的是读取文件的整个第一行,但是在第一行之后,仅读取以下行,直到命中空白为止。我的最终目标是通过向用户添加/减去时间来询问用户他们要编辑的行。

What I would like to do is read the whole first line of the file but then after the first line only read the following lines until whitespace is hit. My end goal is to ask the user what line they want to edit by adding/subtracting time to said line.

示例文件

My test file
00:19.1 123456
00:35.4 testing whitespace end

所需的输出

1: My test file
2: 00:19.1
3: 00:35.4

代码:

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

int main()
{
    FILE *fptr1, *fptr2;

    char filechar[40];
    char c[50];
    int line_number = 1;
    int replace_line, temp = 1;

    printf("Please enter a file name: ");
    scanf("%s", &filechar);

    if ((fptr1 = fopen(filechar, "r")) == NULL)
    {
        printf("Error locating desired file");
        exit(1);
    }

    c = getc(fptr1);
    while (c != EOF)
    {
        //printf("%d: %c",line_number, c);
        printf("%s",c);
        c = getc(fptr1);
        //line_number++;
    }
    return 0;
}


推荐答案

在C中,您有面向字符的输入函数(例如 getchar fgetc ),您具有格式化的输入函数(例如 scanf 系列),则您具有面向行的输入函数。 (例如 fgets 和POSIX getline )。当您读取数据的时,面向行的输入函数是完成此任务的合适工具。 (使用 scanf 进行用户输入会遇到很多新的(甚至不是那么新的)C程序员都会陷入的陷阱)

In C you have character oriented input functions (e.g. getchar, fgetc), you have formatted input functions (e.g. the scanf family) and then you have line oriented input functions. (e.g. fgets and POSIX getline). When you are reading lines of data, line oriented input functions are the proper tool for the job. (taking user input with scanf has many pitfalls that new (and even not so new) C programmers fall into)

所有面向行的函数在其填充的缓冲区中读取并包含 '\n'。如果可以在代码中稍后使用换行符,则可以并且应该从结果缓冲区中删除换行符。一个简单的

All line oriented functions read and include the '\n' in the buffer they fill. You can, and should, remove the newline from the resulting buffer if it will be used later on in your code. A simple

size_t n = strlen (buf);
if (buf[n-1] == '\n') 
    buf[--n] = 0;

只需覆盖结尾的'\n'带有终止符的字符。如果您只是立即打印该行而不是将其存储以备后用,则不值得删除换行符(只需在输出 format字符串中考虑它)。

is all you need to overwrite the trailing '\n' with a nul-terminating character. If you are just printing the line immediately and not storing it for later use, then it's not worth removing the newline (just account for it in your output format string).

将这些片段放在一起,您可以阅读每一行,只需将其输出即可处理第一行,对于其余的每一行,从中解析出时间(大概是经过的时间)由 fgets sscanf 读取的完整字符串,并按照您指定的格式格式化输出。例如,

Putting those pieces together, you can read each line, handle the first by simply outputting it, and for each remaining line, parse the time (presumable some elapsed time) from the full string read by fgets with sscanf and format the output as you specify. E.g.

#include <stdio.h>

#define MAXC 64     /* define constants, don't use magic number in code */

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

    char buf[MAXC] = "";    /* buffer to hold each line -- size as reqd */
    int line = 1;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

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

    while (fgets (buf, sizeof buf, fp)) {   /* read each line in file  */
        char et[MAXC] = "";                 /* buffer for holding time */
        if (line == 1)                      /* if 1st line, just print */
            printf ("%d : %s", line, buf);  /* note: \n included by fgets */
        else {
            if (sscanf (buf, "%s", et) != 1) { /* parse up to first whitespace */
                fprintf (stderr, "error: invalid conversion, line %d\n", line);
                return 1;
            }
            printf ("%d : %s\n", line, et); /* output elapsed time only  */
        }
        line++;                             /* increment line count */
    }

    if (fp != stdin) fclose (fp);           /* close file if not stdin */

    return 0;
}

注意:您应防止缓冲区溢出通过在 sscanf 格式字符串中包含 field-width 说明符进行解析(例如 sscanf(buf,%63s,等),那是您所能做的一件事就是在代码中包含幻数,因为无法直接为<$ c指定变量宽度说明符$ c> sscanf -除非您创造性地使用 sprintf 提前创建格式字符串-但这是

note: you should protect against buffer overrun on parse by including a field-width specifier in the sscanf format string (e.g. sscanf (buf, "%63s", et), and that is one place that all you can do is include magic numbers in your code because there is no way to directly specify a variable width specifier for sscanf -- unless you creatively use sprintf to create the format string ahead of time -- but that's for another day..

示例输入文件

$ cat dat/et.txt
My test file
00:19.1 123456
00:35.4 testing whitespace end

示例用法/输出

$ ./bin/et <dat/et.txt
1 : My test file
2 : 00:19.1
3 : 00:35.4

仔细检查一下,如果有什么需要告诉我其他问题。

Look things over and let me know if you have any further questions.

(注意:我将文件名作为程序的第一个参数,或者从 stdin 中读取如果没有给出文件名。 C提供了命令行参数-使用它们。可以根据需要提示输入,否则,只需在命令行:)

(note: I take the filename as the first argument to the program, or read from stdin if no filename is given. C provides for command line arguments -- use them. It's fine to prompt for input if needed, otherwise, its far easier just to specify arguments on the command line :)

这篇关于简单的C程序逐行读取文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆