分支与循环:if和else语句?switch语句?EOF是什么?缓冲区是什么?getchar怎么用?fflush不能用?

简介: 分支与循环:if和else语句?switch语句?EOF是什么?缓冲区是什么?getchar怎么用?fflush不能用?

目录

关于if--else语句:

switch语句的补充:

什么是EOF?

缓冲区是什么?

什么是getchar函数?

fflush没效果?


关于if--else语句:

#include <stdio.h>
int main()
{
  int age = 0;
  scanf("%d", &age);
  if (age < 18)
    printf("少年\n");
  else if (age >= 18 && age < 30)
    printf("青年\n");
  else if (age >= 30 && age < 60)
    printf("中年\n");
  else
    printf("老年\n");
  return 0;
}

image.gif

这是一串正常if--else语句代码,那么和下面这串意思是否相同?

#include <stdio.h>
int main()
{
  int age = 0;
  scanf("%d", &age);
  if (age < 18)
    printf("少年\n");
  if (age >= 18 && age < 30)
    printf("青年\n");
  if (age >= 30 && age < 60)
    printf("中年\n");
  if(age>=60)
    printf("老年\n");
  return 0;
}

image.gif

      答案很显然是相同的,那么区别在于,第一串代码中有if-else搭配使用时,有else判断成功会立即跳出,提高程序运行效率,而第二串代码只会一个一个去试条件是否满足,程序运行效率大大降低,因此可以看出,不写else语句其实也是可以的,但写了会提高运行效率。


switch语句的补充:

#include <stdio.h>
int main()
{
  int day = 0;
  switch (day)
  {
     case 1:
     case 2:
       case 3:
     case 4:
     case 5:
      printf("weekday\n");
      break;
     case 6:
     case 7:
      printf("weekend\n");
    break;
  }
  return 0;
}

image.gif

       当输入1-5时,会输出weekday,而输入6,7时,输出为weekend(应加入default语句判断额外情况,此处只补充知识),由此可以看出,case后可以不加任何语句而进行后续运行的,总结为:

case是switch的入口,进去后会一直循环直到遇到出口,如break,continue等。

编程好习惯:

在最后一个case语句后加上break语句。

可以避免出现在以前的最后一个case语句后面忘了添加break语句。


什么是EOF?

在编程中常常能看到这样的语句:

while(scanf("%d",&a)!=EOF)
 {
 ......
 }
while(ch=getchar!=EOF)
 { 
 ......
 }

image.gif

诸如此类的语句,那么什么是EOF?在C语言库中,我们可以看到官方对其的定义为:

#define EOF -1

image.gif

      那么EOF即可以理解为-1 其实在C语言中,EOF的全称为end of file,是文件结束的标志,每一个文件在结束的末尾都会加上一个EOF。那么应用到scanf或getchar函数(后续会讲解)中,这涉及到它们的返回值问题,scanf在读取成功会返回数据的个数,getchar成功会返回字符的ASCII码值,而共同点是若读取失败会返回EOF。

      因此诸如上述代码语句可以理解为,一直进行输入,若输入失败则会返回EOF,不满足while的条件,循环也就停止了,语句的含义就是不断让用户进行输入,直到跳出循环(也可以输入CTRL+Z主动跳出循环)。


缓冲区是什么?

在C语言的相关书籍中,或多或少都会提及到缓冲区的问题,那么什么是缓冲区?

      缓存区:C语言中的缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

提到这个问题,就需要看这个很经典的问题:看下面这个程序有问题吗?

#include <stdio.h>
int main()
{
  char password[20] = {0};
  printf("请输入密码:>");
  scanf("%s", password);
  printf("请确认密码(Y/N):");
  char input = 0;
  scanf("%c", &input);
  if ('Y' == input)
    printf("确认成功\n");
  else
    printf("确认失败\n");
  return 0;
}

image.gif

提示用户输入密码,输入后确认密码,如果输入Y则输出成功,否则失败。

看似没问题,那么事实上进行运行后会发现以下问题:

image.gif编辑

我们会发现,输入密码后还没输入Y就结束程序了,我们调试看一下原因:

image.gif编辑

调试会发现,password没有任何问题,而input却直接赋予了"\n",这便是缓冲区;

image.gif编辑

       运行程序输入密码时,我们会输入"123456回车",输入回车证明我们输入结束了,可以进行后续操作了;而程序在进行读取时会读取缓冲区中的数据,事先会把"123456回车"放到缓冲区中,而scanf读取的时候只读走了123456,缓冲区中还存在"\n",所以就导致后续的scanf直接把"\n"读走了;因此不会进行赋值。

      那么如何解决这个问题?很简单,在下次scanf前把缓冲区中的数据清除掉就可以了,因此就引入了getchar函数。

什么是getchar函数?

image.gif编辑

这是cplusplus对getchar函数的定义,由此可见它也是一个输入函数。


我们只需要用getchar函数把缓冲区的剩余部分都清除就可以了:

#include <stdio.h>
int main()
{
  char password[20] = {0};
  printf("请输入密码:>");
  scanf("%s", password);
  getchar();
  printf("请确认密码(Y/N):");
  char input = 0;
  scanf("%c", &input);
  if ('Y' == input)
    printf("确认成功\n");
  else
    printf("确认失败\n");
  return 0;
}

image.gif

这样程序就可以运行了,但若输入是"123456空格abc回车",会发现问题又出现了:

image.gif编辑

      这是因为,scanf只读取空格前面的内容,后面的getchar并没有达到清除缓存区的作用,于是有下面这个方法可以根源解决问题:

#include <stdio.h>
int main()
{
  char password[20] = {0};
  printf("请输入密码:>");
  scanf("%s", password);
  while (getchar () != '\n')
  {
    ;
  }
  printf("请确认密码(Y/N):");
  char input = 0;
  scanf("%c", &input);
  if ('Y' == input)
    printf("确认成功\n");
  else
    printf("确认失败\n");
  return 0;
}

image.gif

直接利用while循环读到'\n'为止,于是便可以清除缓存区。


fflush没效果?

       在C语言函数库中,自然是有清除缓存区这样的函数库的,例如fflush函数,但在新版本的vs上,这个函数被取消了,因此无法使用,还是使用循环清除缓存区比较好。

相关文章
|
Apache SQL HIVE
带你读《Apache Kylin权威指南》之二:快 速 入 门
从最早使用大数据技术来做批量处理,到现在越来越多的人要求大数据平台也能够如传统数据仓库技术一样支持交互式分析,随着数据量的不断膨胀、数据平民化的不断推进,低延迟、高并发地在Hadoop之上提供标准SQL查询能力成为必须攻破的技术难题。而Apache Kylin的诞生正是基于这个背景,并成功地完成了很多人认为不可能实现的突破。
|
10月前
|
存储 关系型数据库 MySQL
MySQL MVCC全面解读:掌握并发控制的核心机制
【10月更文挑战第15天】 在数据库管理系统中,MySQL的InnoDB存储引擎采用了一种称为MVCC(Multi-Version Concurrency Control,多版本并发控制)的技术来处理事务的并发访问。MVCC不仅提高了数据库的并发性能,还保证了事务的隔离性。本文将深入探讨MySQL中的MVCC机制,为你在面试中遇到的相关问题提供全面的解答。
785 2
|
12月前
|
存储 Linux 开发工具
掌握版本控制的艺术:Git 技巧深度解析
在软件开发中,版本控制对于代码管理和团队协作至关重要。Git 作为最流行的分布式版本控制系统,凭借其强大的功能和灵活性成为开发者必备工具。本文深入探讨 Git 的高级技巧和最佳实践,包括交互式暂存、撤销提交、合并冲突处理等,帮助你更高效地使用 Git。通过遵循清晰的提交信息、保持提交原子性、利用分支开发等最佳实践,开发者可以更好地管理代码库,提升协作效率。
|
设计模式 Java 开发者
Java中的异常处理与断路器模式
Java中的异常处理与断路器模式
|
算法 索引
链表经典练习题
链表经典练习题
|
弹性计算 网络协议 网络安全
阿里云服务器开通1723端口教程配置安全组规则
阿里云服务器安装PPTP需要1723端口,阿里云服务器默认没有开通1723端口,可以在云服务器安全组中开放1723端口
1201 0
阿里云服务器开通1723端口教程配置安全组规则
|
JavaScript
基于vue的cron表达式组件——vue-crontab插件
基于vue的cron表达式组件——vue-crontab插件
2286 0
|
Java
解决:No appenders could be found for logger
解决:No appenders could be found for logger
717 0
|
C语言
【小朋友的三子棋】
【小朋友的三子棋】
110 0