C编程:scanf中的字符

3

我在使用scanf读取字符时遇到了问题...程序不允许我输入字符,而是在我输入整数后直接跳到了最后一个else语句并打印printf。

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

#define EG 0.23
#define AG 0.70
#define TG 0.15

main() {
    int posothta;
    char eidos;
    float poso;

    printf("Dwse posothta grammatosimwn: ");
    scanf("%d",&posothta);
    printf("Dwse to eidos grammatoshmou: ");
    scanf("%c",&eidos);

    if(eidos=='E' || eidos=='e'){
        poso=posothta*EG;
        printf("To poso pou plirwnoume einai: %f",poso);
    }else if(eidos=='A' || eidos=='a'){
        poso=posothta*AG;
        printf("To poso pou plirwnoume einai: %f",poso);
    }else if(eidos=='T' || eidos=='t'){
        poso=posothta*TG;
        printf("To poso pou plirwnoume einai: %f",poso);
    }else{
        printf("Kapou exei gine kapoio la9os");
    }   

    return 0;
}

scanf("%d",&posothta); 会将换行符留在缓冲区中,以便下一个 scanf 函数使用。让我找一下重复的内容,这是一个常见的问题。 - Daniel Fischer
你可以始终使用 getchar() 代替 scanf() 来读取单个字符。 - Barath Ravikumar
2个回答

4
当你使用scanf()函数时,它仅仅获取你所要求的值。例如:
scanf("%d",&posothta);

假设我在这里输入了5。实际上,stdin 得到了 2 个字符:'5''\n'(因为我必须按下回车键,这会生成一个换行符)。所以,posothta 中放入了 5,但是那个讨厌的换行符仍然留在那里。下一个scanf() 现在正在寻找一个字符,由于换行符('\n')确实是一个字符,程序不会问任何问题,它只是拾取该换行符并继续执行。
请将您的代码更改为:
scanf(" %c",&eidos);

skip参数可以告诉scanf()函数:“跳过所有的空格字符,然后获取下一个字符”。对于scanf()函数来说,空格字符不仅包括空格,还包括换行符。


这个答案不正确!它或许能工作,但问题是您没有刷新您的键盘缓冲区……请看我的答案。 - One Man Crew
@Grijesh Chauhan 那么为什么要在字符前添加空格?这里的逻辑是什么? - One Man Crew
1
@OneManCrew 格式字符串中的空格(普通空格、换行符、制表符等)匹配输入中的任何空白序列。因此,在此格式前面添加一个空格可以使 scanf 跳过前导空格,特别是上一次扫描留在缓冲区中的换行符。 - Daniel Fischer
@OneManCrew - Daniel Fischer 回答道:现在试试吧! - Grijesh Chauhan
@OneManCrew - 我澄清了答案,现在应该可以理解了。顺便说一句,刷新 stdin 缓冲区会导致未定义的行为。 - Mike
未定义的行为!?!?!?这是 flushall() 的正确用法,在读取缓冲区后清除它! - One Man Crew

0

你需要刷新缓冲区:

printf("Dwse posothta grammatosimwn: ");
scanf("%d",&posothta);
flushall();
printf("Dwse to eidos grammatoshmou: ");
scanf("%c",&eidos);

flushall() 函数:

#include <stdio.h>
int flushall( void );

描述:

flushall()函数清除与输入流相关的所有缓冲区,并写入与输出流相关的任何缓冲区。对输入文件的后续读取操作会导致从关联的文件或设备读取新数据。

调用flushall()函数等效于为所有打开的流文件调用fflush()。

返回值:

打开流的数量。当向文件写入时发生输出错误时,全局变量errno被设置。


flushall() 是什么?它定义在哪里,它是用来做什么的? - Daniel Fischer
@Daniel Fischer,我在我的答案中添加了此函数的描述。 - One Man Crew
基本上,MS的C++默认缓冲流输出,而刷新会导致输出流清空。 - One Man Crew
@Daniel Fischer 只需使用 fflush(NULL); 即可刷新所有打开的输出流(在 stdio.h 中)。 - One Man Crew
@OneManCrew 但问题在于需要从输入流中删除某些内容。 fflush(NULL) 显然不是可移植的,尽管在某些实现中它可能也会刷新输入流。 - Daniel Fischer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接