fscanf重复字符

djmepvbi  于 2022-12-22  发布在  其他
关注(0)|答案(2)|浏览(113)

当用fscanf从文本文件中读取数据时,下一列的数据会被追加到字符串数据中。如何只获取该列的数据?
输入文件:student.txt

Donald 23 KOR CE
Mitchell 24 USA EE
John 22 KOR CE

输出:

Donald 23 KORCE CE
Mitchell 24 USAEE EE
John 22 KORCE CE

在第一行的数据中,国家应该是KOR,但结果却是KORCE
我的代码到目前为止:

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

#define MAX_LINE_LENGTH 100

typedef struct
{
  char name[20];
  int age;
  char country[3];
  char dept[2];
} STUDENT;

int main()
{
  int i = 0;
  STUDENT student[15];

  // Initialize the student array
  for (i = 0; i < 15; i++) {
    memset(student[i].name, 0, sizeof(student[i].name));
    student[i].age = 0;
    memset(student[i].country, 0, sizeof(student[i].country));
    memset(student[i].dept, 0, sizeof(student[i].dept));
  }

  // Open the file for reading
  FILE *fp = fopen("student.txt", "r");
  if (fp == NULL)
  {
    puts("Error: Could not open file 'student.txt'");
    return 1;
  }

  // Read the file line by line
  char line[MAX_LINE_LENGTH];
  while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) {
    // Parse the line and fill the structure
    if (sscanf(line, "%s %d %s %s\n", student[i].name, &student[i].age, student[i].country, student[i].dept) != 4) {
      printf("Error: Invalid data in file 'student.txt'\n");
      return 1;
    }

    // Print the structure
    printf("Name: %s\n", student[i].name);
    printf("Age: %d\n", student[i].age);
    printf("Country: %s\n", student[i].country);
    printf("Dept: %s\n", student[i].dept);

    i++;
  }

  // Close the file
  fclose(fp);

  return 0;
}

我希望国家/地区名称正常读取为3个字符。

e5nszbig

e5nszbig1#

没有宽度会导致未定义的行为

数据对于student[i].country[3]来说太大,导致缓冲区溢出,因为格式缺少宽度来防止溢出。"%s"width 需要比缓冲区大小小1。回想一下"%s"在存储输入文本后附加了一个 *null字符 *。如果OP使用 * width *,这个问题很快就会暴露出来。
格式末尾的"\n"几乎没有什么用处。

// sscanf(line, "%s %d %s %s\n", 
sscanf(line, "%19s %d %2s %1s", 
    student[i].name, &student[i].age, 
    student[i].country, student[i].dept)

当然,虽然OP需要更大的缓冲区(1倍)。

替代错误检测

使用"%n"来保存扫描偏移量,如果它已经走了那么远的话。它还可以检测 * 部门 * 后面是否有垃圾文本。

while (i < 15 && fgets(line, MAX_LINE_LENGTH, fp) != NULL) {
    int n = 0;
    sscanf(line, "%19s %d %2s %1s &n", 
        student[i].name, &student[i].age, student[i].country,
        student[i].dept, &n);
    if (n == 0 || line[n]) {
      printf("Error: Invalid data <%s> in file 'student.txt'\n", line);
      return 1;
    }
    ...
  }

"%d"中使用 width(如"%3d")将年龄范围限制在-99到999之间也是合理的,这将有助于捕获一些病态值并防止溢出。
输入数据是邪恶的。在没有经过审查之前不要相信它。
关于U. S. names的一些见解

e5njpo68

e5njpo682#

谢谢你的建议。但是很抱歉你建议的方法没有解决问题。将“国家[3]”调整为“国家[10]”解决了问题,但是我仍然不知道为什么。

相关问题