将这一行文本读入一个结构的最简单方法? [英] Easiest way to read this line of text into a struct?

查看:67
本文介绍了将这一行文本读入一个结构的最简单方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文本文件,其数据格式为:

I have a text file with data in the form:

Lee AUS 2 103 2 62 TRUE
Check AUS 4 48 0 23 FALSE
Mills AUS 8 236 0 69 FALSE

我需要将每一行都放入一个类似的结构中,但是我想避免使用固定长度的数组(据我所知,fgets的问题):

I need to each line into a struct like, however I'd like to avoid using fixed length arrays (the problem with fgets as far as I can tell):

struct Data
{
    char *sname;
    char *country;
    int *a;
    int *b;
    int *c;
    int *d;
    char *hsisno;
};

我是C语言的新手.我应该使用fscanf还是fgets?

I am very new to C. Should I use fscanf, or fgets?

推荐答案

fscanf代表文件扫描格式化",而用户数据与您的未格式化大致相同.可以得到.

fscanf stands for "file scan formatted" and user data is about as unformatted as you can get.

对于绝对不能控制读取内容的数据,切勿使用裸露的"%s"格式字符串.

You should never use naked "%s" format strings on data where you don't have absolute control over what can be read.

最好的解决方案是使用fgets读取一行,因为这可以防止缓冲区溢出.

The best solution is to use fgets to read a line since this allows you to prevent buffer overflow.

然后,一旦您知道行的大​​小,那就是您需要的每个字符串的最大大小.将sscanf用于您的内心世界,以获取实际字段.

Then, once you know the size of your line, that's the maximum size of each string that you will require. Use sscanf to your heart's content to get the actual fields.

最后一件事.为整数使用int*类型可能有点浪费,因为您知道它们已经具有特定的最大大小.我会使用非指针变量,例如:

One final thing. It's probably a bit wasteful having int* types for the integers, since you know they have a specific maximum size already. I'd use the non-pointer variant, something like:

struct Data {
    char *sname; char *country;
    int a; int b; int c; int d;
    char *hsisno;
};


通过示例,这是一些安全的代码:


By way of example, here's some safe code:

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

// Here's all the stuff for a linked list of your nodes.

typedef struct sData {
    char *sname; char *country; char *hsisno;
    int a; int b; int c; int d;
    struct sData *next;
} Data;
Data *first = NULL; Data *last = NULL;

#define MAXSZ 100
int main (void) {
    char line[MAXSZ], sname[MAXSZ], country[MAXSZ], hsisno[MAXSZ];
    int a, b, c, d;
    FILE *fIn;
    Data *node;

    // Open the input file.

    fIn = fopen ("file.in", "r");
    if (fIn == NULL) {
        printf ("Cannot open file\n");
        return 1;
    }

    // Process every line.

    while (fgets (line, sizeof(line), fIn) != NULL) {
        // Check line for various problems (too short, too long).

        if (line[0] == '\0') {
            printf ("Line too short\n");
            return 1;
        }

        if (line[strlen (line)-1] != '\n') {
            printf ("Line starting with '%s' is too long\n", line);
            return 1;
        }

        line[strlen (line)-1] = '\0';

        // Scan the individual fields.

        if (sscanf (line, "%s %s %d %d %d %d %s",
            sname, country, &a, &b, &c, &d, hsisno) != 7)
        {
            printf ("Line '%s' didn't scan properly\n", line);
            return 1;
        }

        // Allocate a new node to hold data.

        node = malloc (sizeof (Data));
        if (node == NULL) {
            printf ("Ran out of memory\n");
            return 1;
        }

        node->sname = strdup (sname);
        node->country = strdup (country);
        node->a = a;
        node->b = b;
        node->c = c;
        node->d = d;
        node->hsisno = strdup (hsisno);
        node->next = NULL;
        if (first != NULL) {
            last->next = node;
            last = node;
        } else {
            first = node;
            last = node;
        }
    }

    fclose (fIn);

    // Output the list for debugging.

    node = first;
    while (node != NULL) {
        printf ("'%s' '%s' %d %d %d %d '%s'\n",
            node->sname, node->country, node->a, node->b,
            node->c, node->d, node->hsisno);
        node = node->next;
    }

    return 0;
}

将读取文件并将其存储在链接列表中.它输出:

which reads in your file and stores it in a linked list. It outputs:

'Lee' 'AUS' 2 103 2 62 'TRUE'
'Check' 'AUS' 4 48 0 23 'FALSE'
'Mills' 'AUS' 8 236 0 69 'FALSE'

最后,如预期的那样.

我对在不受控制的数据上使用*scanf函数的陷阱做了一系列完整的回答(在上面的搜索框中输入user:14860 fgets),其中一些问题(此处

I've done a whole series of answers on the pitfalls of using *scanf functions on non-controlled data (enter user:14860 fgets into the search box above), some of which (here, here and here, for example) include a perennial favourite function of mine, getLine, for safer user input.

这篇关于将这一行文本读入一个结构的最简单方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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