使用fscanf从文件中读取字符串和整数

时间:2017-12-04 14:51:55

标签: c file

我有这样的结构

struct tm1
{
    char buf[80];
    int val;
} pl;

我想从文件中填充此结构,该文件包含当前时间和一个值。喜欢这个

Mon Dec  4 19:36:23 2017 98

现在我想做fscanf的时间和文件中的值98,并将这些值放在结​​构中(时间应该转到结构成员buf,值即98应该转到结构成员val。)< / p>

现在问题是fscanf在第一个空格处终止,所以为了解决这个问题我尝试了

 fscanf(infile,"%[^\n]",pl.buf);

但是从文件中执行此值后98也将转换为结构成员buf ..

如何在结构成员buf中存储时间,在结构成员val中存储值98?

1 个答案:

答案 0 :(得分:3)

最好使用fgets()来获取输入行。然后可以使用sscanf()来解析输入。

您可以将分配抑制(*)与扫描集指令(%[])结合使用,以忽略日期的第一部分:%*[^0-9] %*d。扫描时间,然后再次使用抑制忽略年份。请注意扫描集中破折号的行为,例如%*[^0-9]是实现定义的,但这通常表现为预期范围。一个完全可移植的替代方案是使用:%*[^0123456789]代替。

以下是一个示例程序:

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

struct tm1
{
    char buf[80];
    int val;
};

int main(void)
{
    struct tm1 p1;

    FILE *fp = fopen("file.dat", "r");
    if (fp == NULL) {
        perror("Unable to open file");
        exit(EXIT_FAILURE);
    }

    char buffer[4096];
    while (fgets(buffer, sizeof buffer, fp)) {
        if (sscanf(buffer, "%*[^0-9] %*d %79s %*d %d", p1.buf, &p1.val) == 2) {
            printf("%s, %d\n", p1.buf, p1.val);
        }
    }

    return 0;
}

节目输出:

19:36:23, 98

更新

我似乎误解了OP的问题。上述解决方案不会将整个日期存储在buf的{​​{1}}字段中。为了存储整个日期,最好在日期和最终值之间设置一些分隔符以帮助解析输入行。如果没有这样的分隔符,上面提到的技术可能仍然有用。

struct指令存储到目前为止从输入流中读取的字符数。这可用于标识示例输入中日期之后的位置。考虑:

%n

此处sscanf(buffer, "%*[^0123456789] %*d %*s %*d%n", &tail) 忽略每个日期组件,并将字符数存储在sscanf()中,这相当于tail中日期之后的字符索引。可以通过扫描再次使用buffer[]来获取最终值:

sscanf()

然后可以在日期之后放置一个空终止符,允许将日期复制到sscanf(buffer + tail, "%d", &p1.val) 的相应字段。

这是另一个示例程序。解析在这里不是防弹,但它应该处理格式良好的数据。请注意,当struct太大时,会跳过该行。这表示日期字符串不适合tail

p1.buf

以下是输入文件示例:

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

struct tm1
{
    char buf[80];
    int val;
};

int main(void)
{
    struct tm1 p1;

    FILE *fp = fopen("file.dat", "r");
    if (fp == NULL) {
        perror("Unable to open file");
        exit(EXIT_FAILURE);
    }

    char buffer[4096];
    while (fgets(buffer, sizeof buffer, fp)) {
        int tail = 0;
        if (sscanf(buffer, "%*[^0123456789] %*d %*s %*d%n", &tail) == 0) {
            if ((unsigned) tail < sizeof p1.buf
                && sscanf(buffer + tail, "%d", &p1.val) == 1) {
                buffer[tail] = '\0';
                strcpy(p1.buf, buffer);
                printf("%s, %d\n", p1.buf, p1.val);
            }
        }
    }

    return 0;
}

以下是程序输出:

Mon Dec  4 19:36:23 2017 98
Tues Dec  5 19:36:28 2017 99
Wed Dec  6 19:36:21 2017 95
Thur Dec  7 19:36:23 2017 89
Fri Dec  8 19:36:20 2017 93
Sat Dec  9 19:36:22 2017 oops! 95
Sun Dec  10 19:36:23 2017 98
Sun               Dec                      10                   19:36:23                     2017 98
Mon Dec  11 19:36:25 2017 97