从文件读取意外输出

Unexpected output reading from a file

我有一个文本文件想要阅读。该文件包含以下内容:

Asdsf adsfsd
54
asdfa adwfasd
12
asdf adf 
545
asdf asdfasfd
3243
adfasf asdfasdf
324324
asfda asdfasdf
3124
adfa asdfas
432
asdf ad

和我的代码:

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


struct Element {
    int edad;
    char name[50];
};

int main() {
    struct Element aux;
    FILE* fitxer;
    fopen_s(&fitxer, "Text.txt", "r");
    if (fitxer != NULL) {
        while (!feof(fitxer)) {
            fgets(aux.name, 50, fitxer);
            aux.name[strlen(aux.name) - 1] = '[=11=]';
            int ret = fscanf_s(fitxer, "%i", &aux.edad);
            char endl;
            fscanf_s(fitxer, "%c", &endl);
            printf("%d %s \n", aux.edad, aux.name);
        }
        fclose(fitxer);
    }
    else {
        printf("Error: File not found.");
    }    
}

我之前遇到问题是因为我不知道f_scanf不带结束符。现在的问题是文件中有一些字符串被截断了。输出:

54 Asdsf adsfsd
12 asdfa adwfasd
545 asdf adf
3243 asdf asdfasfd
324324 adfasf asdfasdf
3124 asfda asdfasdf
432 adfa asdfas
432 asdf a

例如,在这个例子中,最后一个字母被切掉了。我怀疑它与转换为字符串有关,添加了 '[=14=]' 字符,但我找不到错误。

另外想请问有没有更优雅的方法

aux.name[strlen(aux.name) - 1] = '[=10=]';

你摆脱了 fgets 的一个众所周知的行为:它将整行存储到输出缓冲区 包括 '\n' 字符。

但是如果那个字符不存在怎么办? 你会砍掉最后一个字符。

这正是您阅读文件的 last 行时发生的情况。由于没有尾随 '\n' 字符,因此 fgets 会在到达文件末尾时立即停止。

要修复它,只需检查要替换的字符是否是预期的字符。

像这样:

size_t len = strlen(aux.name);

if(len > 0 && aux.name[len - 1] == '\n')
    aux.name[len - 1] = '[=11=]';

检查 len > 0 避免了长度为 0 的字符串的未定义行为(如果该行的第一个字符是 '[=17=]')。

aux.name[strlen(aux.name) - 1] = '[=10=]';

这一行截取了您用 fgets 读取的字符串中的最后一个字符。对于大多数行,该字符是行尾的 \n。但我假设你的最后一行最后没有换行符。所以你砍掉了实际的最后一个字符。

要解决此问题,您应该只删除等于 '\n' 的最后一个字符。

PS:你最后一次调用 fscanf_s 失败,你最终打印了与前一行相同的数字。不知道是不是故意的

PPS:如果你最后一次调用 fscanf_s 没有失败,你的 while 循环将循环多一次,因为 feof 只有 returns true如果先前的读取由于文件结尾而失败。因此,您可能不想使用 feof,而是直接检查您的读取操作是否失败。

至少3个问题:

错误的文件结尾测试,避免幻数

ref

//while (!feof(fitxer)) {
//    fgets(aux.name, 50, fitxer);
while (fgets(aux.name, sizeof aux.name, fitxer)) {

fscanf_s(fitxer, "%c", &endl); 缺少扩充。

研究 fscanf_s() 如果有兴趣,或者更好,只需使用 fgets() 作为输入。

错误的代码会中断潜在的试用 '\n'

备选方案:1 2

// aux.name[strlen(aux.name) - 1] = '[=11=]';
aux.name[strcspn(aux.name, "\n")] = '[=11=]';