从文件读取意外输出
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=]';
我有一个文本文件想要阅读。该文件包含以下内容:
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=]';