微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在检查新行的同时使用 fscanf 从文件中填充结构数组反馈

如何解决在检查新行的同时使用 fscanf 从文件中填充结构数组反馈

我有一个 .txt 文件,其中每一行都像:

id name surname 78 99 101 12 33 44

每一行我都需要填充一个 Student 结构体。 surname 之后的数字必须存储在结构体数组 Lesson 中。第一个数字(例如 78)是一个结构体字段,第二个数字(99)是另一个结构体字段。姓氏后面的对最多可以是 8。我有点困惑,因为我不知道会有多少对,我找到了这个方法,但不确定我检查换行符 (\n) 的方式是否好。

typedef struct Lesson
{
    int hour;
    int time;
}Lesson;

typedef struct Student
{
    int id;
    char name_and_surname[100];
    Lesson lessons[8];
    struct Student *next;
}Student; 

Student s;

while (fscanf(fp,"%d %s %s",&s.id,s.name_and_surname,tmp) == 3)
{
    int i = 0;
    strcat(s.name_and_surname," ");
    strcat(s.name_and_surname,tmp);
    while ((ch = fgetc(fp) != '\n') && fscanf(fp,"%d %d",&s.lessons[i].hour,&s.lessons[i].time) == 2) 
      {
            i++;
      }
       
       //add s to a linked list
}

解决方法

正如我在评论中所说的那样,如果您的输入被组织为每行一条记录并带有可变格式行,那么最好一次读取整行,也许使用 fgets(),然后将结果解析为其字段。解析有许多替代方案,其中包括 sscanf()strtok()strtol()

如果您必须通过fscanf()直接扫描每个字段来完成这项工作,那么这是可能的,但很麻烦。您提出的特定方法并不可靠:它不会识别带有尾随空格的行上的换行符,也不会识别因尾随数字为奇数而格式错误的行。

例如,您可以改用以下内容:

/*
 * Scan one int from file 'fp' into the location pointed to by 'dest',* skipping any leading whitespace other than newlines.
 *
 * Returns:
 *  1   on success
 *  0   if a non-numeric field is found before the next newline
 *  EOF if end of file or end of line is reached without encountering
 *      an input field,or on error
 */
int scan_one_number(FILE *fp,int *dest) {

    // skip leading whitespace,but stop at a newline
    while (1) {
        int c = fgetc(fp);
        
        if (c == EOF || c == '\n') {
            // terminate on error,end-of-file,or end-of-line
            return EOF;
        } else if (!isspace(c)) {
            // a non-whitespace character

            // push it back onto the stream
            if (ungetc(c,fp) != c) {
                // error
                return EOF;
            }

            // break out of the loop
            break;
        } // else it's non-newline whitespace; ignore it
    }

    // attempt to scan a decimal integer
    return fscanf(fp,"%d",dest);
}

这将允许您使用 scanf 一次扫描一个数字,识别行尾和格式错误的输入。

,

我觉得只要你知道Lesson的输入必须是成对的并且不会奇数就可以了。 在这种情况下,您可以用 0 或 null 甚至 -1 左右填充数组课程的末尾。你这样做是因为你可能想在之后打印它。 类似的东西:

for (j = 0; j < i; j++)
{
    s.lessons[j].hour = 0;
    s.lessons[j].time = 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。