#include<stdio.h>
char Name[100];
int Class;
void Display(FILE* p) {
while ((fscanf(p, "Name: %s, Class: %d\n", Name, &Class))!= EOF) {
printf("Name: %s, Class: %d\n", Name, Class);
}
}
void Append(FILE* p) {
for (int i = 0; i < 2; i++) {
printf("Name: ");
scanf("%s", Name);
printf("Class: ");
scanf("%d", &Class);
fprintf(p, "Name: %s, Class: %d\n", Name, Class);
}
}
void Writing(FILE* p) {
for (int i = 0; i < 2; i++) {
printf("Name: ");
scanf("%s", Name);
printf("Class: ");
scanf("%d", &Class);
fprintf(p, "Name: %s, Class: %d\n", Name, Class);
}
}
int main() {
char a;
FILE* p;
do {
int Choice;
printf("Choose a choice\n1 for display\n2 for appending data\n3 for writing\nChoice: ");
scanf("%d", &Choice);
switch (Choice) {
case 1: {
p = fopen("NewFile.txt", "r");
Display(p);
fclose(p);
break;
}
case 2:{
p = fopen("NewFile.txt", "a");
Append(p);
fclose(p);
break;
}
case 3: {
p = fopen("NewFile.txt", "w");
Writing(p);
fclose(p);
break;
}
}
printf("Do you want to continue, y for yes: ");
scanf(" %c", &a);
} while (a == 'y');
}
尝试更换
while ((fscanf(p, "Name: %s, Class: %d\n", Name, &Class))!= EOF)
与
while ((fscanf(p, "%s, %d\n", Name, &Class))!= EOF)
这给了
Name: Name:, Class: 0
Name: ff,, Class: 0
Name: Class:, Class: 0
Name: 5, Class: 0
Name: Name:, Class: 0
Name: gg,, Class: 0
Name: Class:, Class: 0
Name: 8, Class: 0
作为输出..
还尝试不在
fprintf
和 fscanf
函数中写入 Name 和 Class,但仍然不起作用..
将我的评论转化为答案。
您需要阅读scanf() 格式字符串中尾随空格的影响是什么?。一般来说,在
scanf()
格式字符串中尾随空格是一个坏主意;用户必须预测下一个输入需要什么。几乎所有转换说明符都会跳过前导空格(换行符、空格、制表符等)。三个例外是 %c
、%[…]
(扫描集)和 %n
。
但是,除了格式字符串中的尾随空格之外,您还有其他问题。
您还遇到一个问题,即您正在从
scanf()
检查 EOF,但如果在成功转换任何输入之前无法理解输入,它将返回 0。它返回成功扫描的项目数。因此,您应该测试您是否获得了预期的输入数量。例如:
while ((fscanf(p, "Name: %s, Class: %d\n", Name, &Class)) == 2)
您可能需要从
fscanf()
捕获值来区分错误和 EOF。如果返回 1 或 0,您可能需要读取到下一个换行符。 (另请参阅下面有关读取行然后解析它们的建议。)
你也有
"%s, %d\n"
- 但这肯定会失败,因为当下一个字符是空格(或 EOF)时 %s
停止扫描,然后扫描不会得到逗号(因为输入中的字符是空白),因此扫描停止。
使用如下格式字符串:
" %99[^,], %d"
前导空格跳过空格;
99
可防止缓冲区溢出。 [^,]
扫描集查找除逗号之外的任何内容。
另请参阅远离
scanf()
的初学者指南。
scanf()
系列函数的正确使用非常棘手。通常,最好的(或者至少是好的)技术是读取一行数据(例如使用 fgets()
或 POSIX getline()
,然后使用 sscanf() 解析该数据。这样做的一个主要优点是你可以报告触发错误的整行,而不仅仅是 scanf()
未转换的内容。有时,更多临时解析工具是合适的。scanf()
函数不一定安全地处理太大的整数或太小——向函数提供这样的数字会调用未定义的行为。