gpt4 book ai didi

c - 使用 fscanf 读取制表符分隔的记录

转载 作者:行者123 更新时间:2023-11-30 18:45:50 25 4
gpt4 key购买 nike

数据文件:

Newton  30  United Kingdom  Scientist
Maxwell 25 United Kingdom Mathematician
Edison 60 United States Engineer

读取代码:

#define MAX_NAME    50
#define MAX_COUNTRY 25
#define MAX_PROFILE 20
struct person
{
char *name;
int age;
char *country;
char *profile;
};

struct person pObj;
pObj->name = (char *) malloc(sizeof(MAX_NAME));
pObj->country = (char *) malloc(sizeof(MAX_COUNTRY));
pObj->profile = (char *) malloc(sizeof(MAX_PROFILE));

fscanf(fPtr,"%s\t%d\t%s\t%s\n",pObj->name,&pObj->age,pObj->country,pObj->profile);

我编写了一个程序,使用 fscanf() 将制表符分隔的记录读取到结构中。我也可以通过 strtok()strsep() 函数做同样的事情。但是如果我使用 strtok(),我就被迫使用 atoi() 函数来加载 age 字段。但我不想使用那个atoi()函数。因此,我只是使用 fscanf() 直接从 FILE 流缓冲区读取年龄作为整数。效果很好。但对于某些记录,国家/地区字段为空,如下所示。

Newton  30  United Kingdom  Scientist
Maxwell 25 Mathematician
Edison 60 United States Engineer

当我读取第二条记录时,fscanf() 不会将空字符串填充到国家/地区字段,而是已填充个人资料数据。我们知道 fscanf() 就是这样工作的。但是,即使文件中的国家/地区字段为空,是否有任何选项可以扫描该字段?我可以在不使用 atoi() 年龄函数的情况下执行此操作吗?即,按相应类型读取字段,但不是将所有字段都作为字符串读取。

最佳答案

原始格式

%s 转换规范会跳过输入中的任何空格(空格、制表符、换行符等),然后读取非空格直至下一个空格字符。格式字符串中出现的 \t 会导致 fscanf() 跳过零个或多个空白字符(不仅仅是制表符)。

你有:

fscanf(fPtr,"%s\t%d\t%s\t%s\the n", pObj->name, pObj->age, pObj->country, pObj-profile);

您需要传递一个指向年龄的指针,并且需要在 pObjprofile 之间有一个箭头 -> (请发布可以的代码编译;当出现这样的错误时,它不会激发信心):

fscanf(fPtr,"%s\t%d\t%s\t%s\the n", pObj->name, &pObj->age, pObj->country, pObj->profile);

给定第一行输入:

Newton  30  United Kingdom  Scientist

fscanf() 会将 Newton 读入 pObj->name,将 30 读入 pObj->年龄, union 进入pObj->国家王国进入pObj->个人资料fscanf一般来说,()` 和家人对空白非常随意。大多数转换都会跳过前导空格。

分配 4 个值后,格式末尾有 \the n"。该选项卡会跳过 KingdomScientist 之间的空白,但数据与 he n 不匹配,因此扫描停止 - 这并不是说您更明智。

下一个操作将从上次停止的地方继续,因此下一个 pObj->name 将被分配为 Scientist,然后是 pObj->age 转换将失败,因为 Maxwell 不表示整数。转换在 fscanf() 上停止。

所以问题仍然存在。使用您在问题中显示的代码无法获得您声称的输出。

如果您坚持必须使用 fscanf(),则需要使用扫描集,例如 %24[^\t] 来读取国家。但你最好使用 fgets()或 POSIX 函数 getline()读取整行输入,然后也许使用 sscanf()但更有可能使用标准 C 中的 strcspn()strpbrk() (或者可能是 strtok() 或 — 更好 — POSIX strtok_r() 或 Windows strtok_s() 或非标准 strsep()) 将行拆分为选项卡上的字段。请注意,strtok_r() 等人并不关心字段之间的分隔符(在您的情况下为制表符)有多少次重复;它们不能有空字段。您可以使用 strcspn()strpbrk()strsep() 识别空字段。

<小时/>

清理后的格式

格式字符串已修改为:

fscanf(fPtr,"%s\t%d\t%s\t%s\n", pObj->name, &pObj->age, pObj->country, pObj->profile);

这不会起作用,但现在可以进行调整,使其起作用。

if (fscanf(fPtr," %49[^\t]\t%d\t%24[^\t]\t%19[^\n]", pObj->name, &pObj->age, pObj->country, pObj->profile) != 4)
…handle a format error…

Beware trailing white space in scanf() format strings 。前导空白会跳过前一行留下的任何换行符,并跳过一行上的任何前导空白。 %49[^\t] 最多查找 49 个非制表符;制表符是可选的,并且匹配任何空白序列,但第一个字符将是制表符,除非名称太长。然后它读取一个数字,更多可选的空格(它不一定是制表符,但除非数据格式错误,否则它会是),然后最多 24 个非制表符,再次空格(其中第一个字符将除非存在格式问题,否则为制表符),最多 19 个非制表符。下一个字符应该是换行符,除非存在格式问题。

关于c - 使用 fscanf 读取制表符分隔的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53512597/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com