使用 fscanf 无限输出

问题描述 投票:0回答:1
#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,但仍然不起作用..

c
1个回答
0
投票

将我的评论转化为答案。

您需要阅读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()
函数不一定安全地处理太大的整数或太小——向函数提供这样的数字会调用未定义的行为。

© www.soinside.com 2019 - 2024. All rights reserved.