零基础玩转C语言系列第三章——循环语句

简介: 循环语句

【前言】:循环语句补充的知识点都挺重要的哦,铁汁们要用点心记哦。

一、while语句

while语句

1. while(表达式)
2. {
3.     循环语句;
4. }


【敲黑板】:条件表达式的执行次数比循环体的执行次数多 1次。


循环中的break语句和continue语句:

break语句在循环中的作用:break是永久终止循环

continue语句在循环中的作用:continue是用于终止本次循环的,也就是说本次循环中continue后面的代码不会执行,而是直接跳转到while语句的判断部分


补充1:getchar()

函数原型:

int getchar(void)

 

功能:

在标准输入缓冲区中读取一个字符,返回读到的字符的ASCII码值,如果读取失败,则返回EOF(-1)

问:为什么getchar()返回的是字符的ASCII码值?函数返回值为什么要放到一个int类型的变量中呢?不是应该放在一个char类型的变量中吗?

如:

int ch = 0;
ch = getchar();


答:


  • getchar()返回了字符的ASCII码值,ASCII码值是整数,存放在整型变量中没有任何问题;
  • 这一点也是最重要的一点,getchar()读取失败的时候返回EOF,EOF本质是-1(#define EOF -1),是一个整型值,在一个char类型中,是存储不下的;
  • 再结合getchat()函数的原型,getchar()的返回类型被定义为int, 那么返回数据应该被存放在int变量中

getchar(): 获取/输入一个字符;

putchar(): 输出一个字符

注意哦,这两个函数一次只能操作一个字符,没有scanf(),printf()功能齐全


补充2:输入缓冲区

引入:

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


此时输入缓冲区中放的是abcdef\n,scanf()函数将abcdef读走了,留下了一个\n,所以\n直接被getchar()读取,所以此时ch里面放的是\n,后面不会等到我们确认密码就直接输出确认失败了。



存在的问题:本题输入abcdef,然后按回车键,还没有等到我们输入字符(Y/ N)就直接输出“确认失败”了,那怎么改才能成为我们想要的呢?


在scanf()下面加上一条语句:getchar();目的只有一个,拿走回车键('\n'),



存在的问题:这样改只能保证输入“abcdef”时可以正常执行,但如果输入的是"abcdef hehe"时又会直接输出“确认失败”了,不信你看...


我丢,这什么鬼,怎么又错了!?

注意:

scanf("%s", ...); //scanf()读取字符串的时候遇到空格时就停下来不再读取了

分析上段代码:

#include<stdio.h>
int main()
{
  char input[20] = { 0 };
  printf("请输入密码:>");
  scanf("%s", input);//scanf()只读取了"abcdef"
  getchar();//getchar()读取了一个空格,所以这里就有问题了,这里的getchar()只能拿走一个字符,我们想要的是它能将缓冲区
  //里剩下字符全部拿走,直至拿走'\n'
  printf("请确认密码:(Y / N):>");
  int ch = getchar();
  if (ch == 'Y')
  {
    printf("确认成功\n");
  }
  else
  {
    printf("确认失败\n");
  }
  return 0;
}

是呀,这里的getchar()只能拿走一个字符,我们想要的是它能将缓冲区里剩下的全部拿走,直至拿走'\n',该怎么改?

#include<stdio.h>
int main()
{
  char input[20] = { 0 };
  printf("请输入密码:>");
  scanf("%s", input);//scanf()只读取了"abcdef"
    //清理缓冲区
  int tmp = 0;
  while ((tmp = getchar()) != '\n')
  {
    ;//空语句,什么事都不干,拿字符就行了
  }
  printf("请确认密码:(Y / N):>");
  int ch = getchar();
  if (ch == 'Y')
  {
    printf("确认成功\n");
  }
  else
  {
    printf("确认失败\n");
  }
  return 0;
}

这样就可以了,注意实现上面清理缓冲区的功能哦。

二、for循环

注意:

for循环的风格更胜一筹,使用的频率也最高。

建议:

  • 不可在for循环体内修改循环变量,防止for循环失去控制
  • 建议for语句的循环控制变量的取值采用“前闭后开”的写法

如:

for(i = 10; i < 10; i++)   //前闭后开
for(i = 10; i <= 10; i++)  //前闭后闭(不建议这样写法,但是为了更好地解读也可以用)

一些for循环的变种:

  • for的初始化、判断、调整三个部分都可以省略;
  • 中间的判断部分如果省略就意味着判断恒为真,构成了死循环

所以,如果条件允许,不建议省略哦。

笔试题:

//问:打印了多少次hehe?
#include<stdio.h>
int main()
{
  int i = 0;
  int j = 0;
  for (; i < 3; i++)
  {
    for (; j < 3; j++)
    {
      printf("hehe\n");
    }
  }
  return 0;
}

嘿嘿,想必铁汁心里已经有了自己的答案,看看是不是和正确答案一样呢?

哈哈,说实话,我第一次做这道题目想的是9次,那为什么是3次呢?

看到了吧,所以尽量不要省略for循环里面的表达式。

再加一道笔试题:

int i = 0;
int k = 0;
for(i = 0, k = 0; k = 0; i++, k++)   //k = 0为赋值,0为假,判断表达式恒为假,所以循环执行了0次
{
    k++;
}


三、do...while()循环

do...while循环与前面两个循环不同的是,它的循环体至少执行一次!

do
    循环语句;
while(表达式);

注意:do...while语句使用的场景有限,所以不会经常使用。

四、练习题

练习1:计算n的阶乘

伪代码:

int ret = 1;
int i = 0;
for(i = 1; i <= n; i++)
{
    ret = ret * i;
}


练习2:计算1!+2!+3!+...+n!

在练习1中我们知道了计算n的阶乘的方法,所以计算1!+2!+3!+...+n!就简单多了。

来,先看一个错误示范:

//为了方便测试我在这里就简单计算到1!+2!+3!
#include<stdio.h>
int main()
{
  int i = 0;
  int ret = 1;
  int sum = 0;
  int n = 0;
  for (n = 1; n <= 3; n++)
  {
    for (i = 1; i <= n; i++)
    {
      ret = ret * i;
    }
    sum = sum + ret;
  }
  printf("%d\n", sum);
  return 0;
}

实际上1!+2!+3! = 9, 但是实际上结果是...

结果却是15,这是为什么呢?

因为第二层循环里面的ret是上次留下的值,而我们希望执行完一次计算某数的阶乘后,需要将ret重置为1,然后再计算下一个数的阶乘。

所以,改写代码如下:

//为了方便测试我在这里就简单计算到1!+2!+3!
#include<stdio.h>
int main()
{
  int i = 0;
  int ret = 1;
  int sum = 0;
  int n = 0;
  for (n = 1; n <= 3; n++)
  {
        ret = 1;//注意哦
    for (i = 1; i <= n; i++)
    {
      ret = ret * i;
    }
    sum = sum + ret;
  }
  printf("%d\n", sum);
  return 0;
}


上面的代码虽然是对的但是依然不够高效,时间复杂度是O(N^2),那可不可以只利用一层循环就解决了呢?其实是可以的,因为上面进行了很多次重复计算。


如上面计算1!+2!+3!,就进行了很多次重复计算

1. //ret * 1
2. //ret * 1 * 2
3. //ret * 1 * 2 * 3

所以改写成高效的代码如下:

1. for(n = 1; n <= 3; n++)
2. {
3. //n*(n-1)! = n!
4.     ret = ret * n;
5.     sum = sum + ret;
6. }

【敲黑板】:当我们写出一个算法的时候,千万不要骄傲,好好想想怎么样才可以更加精炼,所以要多学多练!

加油加油!!

 


相关文章
|
1月前
|
C语言
初识C语言2——分支语句和循环语句
初识C语言2——分支语句和循环语句
69 5
|
4月前
|
C语言
【C语言】循环语句
C语言中循环语句的相关知识点
54 2
【C语言】循环语句
|
2月前
|
安全 C语言
C语言循环的使用注意点
在C语言中,合理使用循环对于编写高效、安全的代码至关重要。以下是几点建议:确保循环条件正确以避免无限循环;每次迭代时正确更新循环变量;恰当使用`break`和`continue`控制执行流程;注意嵌套循环中的变量作用域;简化循环体内逻辑;根据需求选择合适的循环类型;注意数据类型以避免溢出;保持良好的缩进和注释习惯;减少重复计算以提升性能;确保循环终止条件明确。遵循这些建议,可以提高代码质量和可维护性。
214 88
|
30天前
|
C语言
【c语言】循环语句
循环结构是C语言中用于简化重复操作的重要工具,主要包括while循环、do-while循环和for循环。while循环是最基本的形式,通过不断检查条件来决定是否继续执行循环体。do-while循环则先执行循环体,再检查条件,至少执行一次。for循环逻辑更复杂,但使用频率最高,适合初始化、条件判断和更新变量的集中管理。此外,循环中还可以使用break和continue语句来控制循环的提前终止或跳过当前迭代。最后,循环可以嵌套使用,解决更复杂的问题,如查找特定范围内的素数。
37 6
|
1月前
|
Serverless C语言
C语言控制语句:分支、循环和转向
C语言控制语句:分支、循环和转向
|
1月前
|
算法 编译器 C语言
【C语言】实现猜数字游戏(分支语句与循环语句的运用)
【C语言】实现猜数字游戏(分支语句与循环语句的运用)
|
1月前
|
C语言
教你快速理解学习C语言的循环与分支
教你快速理解学习C语言的循环与分支
16 0
|
1月前
|
小程序 C语言
初识C语言:走近循环
初识C语言:走近循环
|
2月前
|
C语言
【C语言基础考研向】08判断语句与循环语句
本文介绍了C语言中的关键编程概念:首先解析了关系表达式与逻辑表达式的优先级及计算过程;接着详细说明了`if-else`语句的使用方法及其多分支和嵌套应用;然后讲解了`while`循环与`for`循环的语法和注意事项;最后介绍了`continue`和`break`语句在控制循环中的作用和示例代码。
|
1月前
|
编译器 C语言 C++
【C语言】循环语句(语句使用建议)
【C语言】循环语句(语句使用建议)