当前位置:   article > 正文

C语言-第二章:分支和循环语句

C语言-第二章:分支和循环语句

分支和循环

前置知识

结构
  • 顺序结构

  • 循环结构

语句
  • 定义:C语言中,由一个分号;隔开的就是一条语句

int a =0;
  • 只有一个分号,也是一个语句,叫空语句

分支语句和循环语句

分支语句(选择结构)
举例
  • if

  • switch

if语句
单分支if
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int age = 20;
  7. if (age < 18)
  8. printf("未成年\n");
  9. return 0;
  10. }
  11. 20——什么都不输出
  12. 18——输出未成年
if与else
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int age = 11;
  7. if (age < 18)
  8. printf("未成年\n");
  9. else
  10. printf("成年\n");
  11. return 0;
  12. }
if + else if + else
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int age = 100;
  7. if (age < 18)
  8. printf("未成年\n");
  9. else if (age >= 18 && age < 28)
  10. printf("青年\n");
  11. else if (age >= 28 && age < 50)
  12. printf("壮年\n");
  13. else if (age >= 50 && age < 90)
  14. printf("老年\n");
  15. else
  16. printf("晚年\n"); //最后这个else可以省略,也可以留着
  17. return 0;
  18. }
执行多条语句
  • 如果条件成立,要执行多条语句,就应该使用代码块

  1. #include <stdio.h>
  2. int main()
  3. {
  4. if(表达式)
  5. {
  6. 语句列表1;
  7. }
  8. else
  9. {
  10. 语句列表2;
  11. }
  12. return 0;
  13. }
  • 这里的一对{}就是一个代码块

悬空else
  • else和离它最近的未匹配的if进行匹配

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int a = 0;
  7. int b = 2;
  8. if (a == 1)
  9. if (b == 2)
  10. printf("hehe\n");
  11. else
  12. printf("haha\n");
  13. return 0;
  14. }
  15. //这个没有输出haha,因为else与第二个if匹配,由于第一个if表达式的条件为假,所以没有进入下面的语句
  • 对上述进行改进,输出haha,这样就是一个好代码

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a = 0;
  5. int b = 2;
  6. if(a == 1)
  7. {
  8. if(b == 2)
  9. printf("haha\n");
  10. }
  11. else
  12. printf("haha\n");
  13. return 0;
  14. }

或者什么都不输出

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a = 0;
  5. int b = 2;
  6. if(a == 1)
  7. {
  8. if(b == 2)
  9. printf("hehe\n");
  10. else
  11. printf("haha\n");
  12. }
  13. return 0;
  14. }
if书写形式对比
  • 代码1,代码可读性不是很强

  1. if (condition){
  2. return x;
  3. }
  4. return y;
  5. //条件成立就返回x,不成立就返回y
  • 代码2,更加容易读懂

  1. if(condition)
  2. {
  3. return x;
  4. }
  5. else
  6. {
  7. return y;
  8. }
  • 代码风格

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. #include <stdio.h>
  5. int main()
  6. {
  7. int num = 4;
  8. if (num = 5)
  9. {
  10. printf("呵呵\n");
  11. }
  12. return 0;
  13. }
  14. //会输出呵呵,因为此处=给num赋值,而不判断相等,要判断相等应用 ==
  15. if那里改成if(5 == num)更优,将来判断常量与变量相不相等,应该把常量放到等号左边来判断
练习
判断一个数是否为奇数,输出1-100之间的奇数
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. #include <stdio.h>
  5. int main()
  6. {
  7. int i = 1;
  8. while (i <= 100)
  9. {
  10. if (i % 2 == 1) //或者 if (i % 2 != 0)
  11. printf("%d", i); //%d后面如果加上\n就换行
  12. i++;
  13. }
  14. return 0;
  15. }

也可以这样写

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i = 1;
  5. while (i <= 100)
  6. {
  7. printf("%d", i);
  8. i+=2;
  9. }
  10. return 0;
  11. }
  12. //这就是算法,有的时候为了达到一种目的,我们可以有多种算法
switch语句
前提
  • 不太好的例子

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int day = 0;
  7. scanf("%d,&day");
  8. if (1 == day)
  9. printf("星期1\n");
  10. else if (2 == day)
  11. printf("星期2\n");
  12. else if (3 == day)
  13. printf("星期3\n");
  14. else if (4 == day)
  15. printf("星期4\n");
  16. else if (5 == day)
  17. printf("星期5\n");
  18. else if (6 == day)
  19. printf("星期6\n");
  20. else if (7 == day)
  21. printf("星期7\n");
  22. return 0;
  23. }
  • 优化:当需要判断的选项较多时,使用多个 if 语句会使代码看起来冗长,不易维护。一个更好的方法是使用 switch 语句,可以简化代码并提高可读性。此外,可以添加一个默认情况来处理无法匹配的输入。

杂记
  • switch后面有一个括号,放一个整形表达式,这个整形表达式结果是几,它就从case几进去

  • switch判断,case作为一个入口进去,而从哪里出去,是由break决定的,break用来跳出switch语句

  • default:当你想选择的结构都不符合switch语句,后面的情况不再执行,default可有可无,处理非法,可以加上,后面什么都不写

  • 编程好习惯:在每个switch语句中都放入一条default子句是一个好习惯,甚至可以在后面再加一个break

  • 表达式必须是整形常量表达式

定义

switch语句也是一种分支语句,常常用于多分支的情况,case决定入口,break决定出口

结构
  1. switch(整型表达式)
  2. {
  3. 语句项
  4. }
语句项
  1. //是一些case语句
  2. //如下:
  3. case 整形常量表达式,不能是变量,能是1而不能是n
  4. 语句;
优化后的代码
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int day = 0;
  7. scanf("%d", &day);
  8. switch (day)
  9. {
  10. case 1:
  11. printf("星期1\n");
  12. break;
  13. case 2:
  14. printf("星期2\n");
  15. break;
  16. case 3:
  17. printf("星期3\n");
  18. break;
  19. case 4:
  20. printf("星期4\n");
  21. break;
  22. case 5:
  23. printf("星期5\n");
  24. break;
  25. case 6:
  26. printf("星期6\n");
  27. break;
  28. case 7:
  29. printf("星期7\n");
  30. break;
  31. default:
  32. printf("输入错误\n");
  33. }
  34. return 0;
  35. }
循环语句
  • while

  • for

  • do while

while语句(循环)
例子1
  • 死循环打印hehe

  1. #include<string.h>
  2. int main()
  3. {
  4. while (1)
  5. printf("hehe\n");
  6. return 0;
  7. }
例子2
  • 打印1-10

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int i = 1; //初始化
  7. while (i <= 10) //判断
  8. {
  9. printf("%d ", i);
  10. i++; //调整
  11. }
  12. return 0;
  13. }
break
  • 在上面printf上面加上

  1. if (i==5
  2. break;

当执行到i = 5 时,循环就停止

  • 作用:在循环中只要遇到break,就停止后期所有的循环,直接终止循环,所以while中的break是用于永久终止循环的

continue
  • 如果把break换成continue,按住F10进行调试,就陷入了死循环,卡到4就一直循环,当遇到5时就不往后走了,代码就不执行啦,作用结束本次循环continue后面的部分,回到循环条件处

  • 作用:continue是用于终止本次循环的,也就是本次循环中的continue后边的代码不会执行,而是直接跳转到while语句的判断部分,进行下一次循环的入口判断

语法结构
  • while表达式 循环语句

getchar函数
  • 函数机制:

  • getchar()函数实际上是int getchar(void),所以它返回的是ASCII码,所以只要是ASCII码表里有的字符它都能读取出来。在调用getchar()函数时,编译器会依次读取用户键入缓存区的一个字符(注意这里只读取一个字符,如果缓存区有多个字符,那么将会读取上一次被读取字符的下一个字符),如果缓存区没有用户键入的字符,那么编译器会等待用户键入并回车后再执行下一步 (注意键入后的回车键也算一个字符,输出时直接换行)。

  • 作用:接受键盘输入的字符,会把字符返回来,。下面把接收的字符放到ch里面,然后用putchar打印出来

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int ch = getchar();
  7. putchar(ch);
  8. printf("%c\n", ch);
  9. return 0;
  10. }
  • 在while循环中的应用——代码1

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. int ch = 0;
  7. while ((ch = getchar()) != EOF)
  8. {
  9. putchar(ch);
  10. }
  11. return 0;
  12. }
  13. //这里输ctrl+z可以停下来,-1也可以,因为是EOF的缘故,其他的不行
  14. //这里输EOF也不会停止,因为系统看成是E,O,F
  15. //ctrl+c是结束进程,ctrl+z是输入文件终止符
  16. //EOF - end of file ->-1,文件结束标志
  17. //只要输一个ctrl+z,getchar就能获取一个EOF,放到ch里面去
  • 关于getchar() \n读取问题

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. /*int ch = 0;
  7. while ((ch = getchar()) != EOF)
  8. {
  9. putchar(ch);
  10. }*/
  11. int ret = 0;
  12. char password[20] = {0};
  13. printf("请输入密码:>");
  14. scanf("%s", password);
  15. //scanf把123456给拿走了,里面还有一个\n,就让getchar拿走了
  16. //缓冲区还剩余一个‘\n'
  17. //读取一下'n'
  18. getchar(); //加上这个,把\n干掉
  19. printf("请输入(Y/N):>" );
  20. ret = getchar();
  21. if (ret == 'Y')
  22. {
  23. printf("确认成功\n");
  24. }
  25. else
  26. {
  27. printf("放弃确认\n");
  28. }
  29. return 0;
  30. }
  • while ((ch = getchar()) != '\n')实际应用价值

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. /*int ch = 0;
  7. while ((ch = getchar()) != EOF)
  8. {
  9. putchar(ch);
  10. }*/
  11. int ret = 0;
  12. int ch = 0;
  13. char password[20] = {0};
  14. printf("请输入密码:>");
  15. scanf("%s", password);
  16. //scanf把123456给拿走了,里面还有一个\n,就让getchar拿走了
  17. //缓冲区还剩余一个‘\n'
  18. //读取一下'n'
  19. while ((ch = getchar()) != '\n')
  20. {
  21. ;
  22. } 如果不加这个,当输入123456 abcd就会错误
  23. printf("请输入(Y/N):>" );
  24. ret = getchar();
  25. //ret变量用于存储用户输入的字符,getchar函数用于从输入缓冲区中读取一个字符。
  26. if (ret == 'Y')
  27. {
  28. printf("确认成功\n");
  29. }
  30. else
  31. {
  32. printf("放弃确认\n");
  33. }
  34. return 0;
  35. }
  • chatgpt对上述代码的分析

  1. scanf("%s", password):使用scanf函数读取用户输入的密码,由于%s会读取空格之前的字符,因此如果用户输入的密码中有空格,那么空格后面的内容将被舍弃。
  2. while ((ch = getchar()) != '\n'):使用getchar函数读取输入缓冲区中的换行符,以避免该字符被下一次输入函数读取。
  3. ret = getchar():使用getchar函数读取用户输入的确认信息。
  4. 如果输入123456 abcd,如果没有while ((ch = getchar()) != '\n')这段代码,那么程序会将abcd作为确认信息读取,并将其与Y进行比较,最终输出“放弃确认”。加上该代码段可以避免这种错误。
  5. 综上所述,这段代码的功能是接受用户输入的密码和确认信息,如果用户确认密码,则输出“确认成功”,否则输出“放弃确认”。
  6. 在输入"123456 abcd"时,scanf函数会把"123456"读取到password数组中,但它并不会读取空格或者其他非数字字符。因此,空格字符和"abcd"字符串会留在输入缓冲区中等待下一次输入函数读取。
  7. 在调用getchar函数时,它会从输入缓冲区中读取一个字符,包括空格字符和换行符,然后将其作为整数返回。在这个例子中,如果没有while ((ch = getchar()) != '\n')语句,程序会在下一个getchar函数调用时读取缓冲区中的空格字符,导致程序无法正常运行。
  8. 因此,为了避免这种情况,我们需要在读取确认信息之前调用一次getchar函数来读取输入缓冲区中的换行符,确保确认信息只包含单个字符,从而可以正常比较。
  • 代码2

  1. #include <stdio.h>
  2. int main()
  3. {
  4. while ((ch = getchar()) != EOF)
  5. {
  6. if (ch < '0' || ch >'9'
  7. continue;
  8. putchar(ch);
  9. }
  10. return 0;
  11. }
  12. //只打印字符0-字符9,其他内容不打印
for循环
语法
  1. for(表达式1;表达式2,表达式3)
  2. 循环语句;
  1. 初始化表达式:在循环开始之前执行一次,用于初始化循环控制变量。这个表达式通常用于给循环控制变量赋初始值,例如:int i = 0;。
  2. 条件表达式:在每次循环开始之前,判断循环是否继续执行。如果条件为真,则继续循环;如果条件为假,则跳出循环。例如:i < 10//条件判断部分
  3. 更新表达式:在每次循环结束之后执行,用于更新循环控制变量的值。例如:i++,表示每次循环结束后,i 的值增加 1//调整部分
基本形式

打印1-10的数字

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i = 0;
  5. for (i = 1; i <= 10; i++)
  6. {
  7. printf("%d ", i);
  8. }
  9. return 0;
  10. }
break
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i = 0;
  5. for (i = 1; i <= 10; i++)
  6. {
  7. if (i == 5)
  8. break;
  9. printf("%d ", i);
  10. }
  11. return 0;
  12. }
  13. //输出:1 2 3 4
continue
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i = 0;
  5. for (i = 1; i <= 10; i++)
  6. {
  7. if (i == 5)
  8. continue;
  9. printf("%d ", i);
  10. }
  11. return 0;
  12. }
  13. //输出:1234678910

不会死循环,此处与while不同,下面对比一下while循环,while会死循环,主要区别在开头

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int = 1;
  5. while(i<=10)
  6. {
  7. printf("%d ",i);
  8. i ++;
  9. }
  10. }
建议
  • 不可在for循环体内修改变量,防止for循环失去控制,比如在for循环内加个i =5

  • 建议for语句的循环控制变量的取值采用"前闭后开区间"写法

在判断处最好写成i<10而非i<=9
for循环变种-变种1
  1. #include <stdio.h>
  2. int main()
  3. {
  4. for(;;)
  5. {
  6. printf("hehe\n");
  7. }
  8. return 0;
  9. }
  • for循环的初始化,判断,调整都可以省略,如果判断部分被省略,判断条件就是恒为真

  • 如果不是非常熟练,建议不要随便省略

for循环变种-变种2
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int x,y;
  5. for (x=0,y=0;x<2 && y<5; ++X,y++
  6. {
  7. printf("hehe\n");
  8. }
小问题

下列循环要多少次

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i = 0;
  5. int k = 0;
  6. for(i =0,k=0;k=0;i++,k++)
  7. k++;
  8. return 0;
  9. }
  10. //上面那个不是判断语句,而是把0赋值给了k,表达式结果是k的值,k的结果是0,0为假,那个地方就是假,意味着循环 压根就不进去
  11. //因此循环0次

关于为假不被执行

  1. 在 C 语言中,条件语句(如 ifwhilefor 等)的判断都是基于条件表达式的值。如果该值为零,则视为假,否则视为真。
  2. 这是因为在 C 语言中,零值被视为“假”,非零值被视为“真”,这种约定俗成的规定被称为“真值测试”。
  3. 例如,在条件语句中,如果条件表达式的值为零,则被视为假,执行 else 分支(如果有的话)或跳过整个语句块;如果条件表达式的值为非零值,则被视为真,执行 if 分支(如果有的话)。
  4. 在这个问题中,条件表达式 k = 0 的值为 0,因此被视为假,循环体内的语句不会被执行。而如果条件表达式的值为非零值,就会被视为真,循环体内的语句就会被执行。
do..while()循环
语法
  1. do
  2. 循环语句;
  3. while(表达式);
  4. chatgpt版:
  5. do {
  6. 循环体语句;
  7. } while (循环条件);
举例
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i = 1;
  5. do
  6. {
  7. printf("%d", i);
  8. i++;
  9. }
  10. while (i < 10);
  11. return 0;
  12. }
特点
  • 循环至少执行一次,使用场景有限,不经常使用

练习
计算n的阶乘
  1. #include <stdio.h>
  2. int main() {
  3. int i = 0;
  4. int n = 0;
  5. int ret = 1;
  6. scanf("%d",&n);
  7. for (i = 1; i <= n; i++)
  8. {
  9. ret = ret * i;
  10. }
  11. printf("ret = %d\n", ret);
  12. return 0;
  13. }
计算1!+2!+3!+...+10!
  1. #include <stdio.h>
  2. int main() {
  3. int i = 0;
  4. int n = 0;
  5. int ret = 1;
  6. int sum = 0;
  7. for (n = 1; n <=3;n++)
  8. {
  9. ret = ret * n; //提高效率
  10. //n的阶乘
  11. sum = sum + ret;
  12. }
  13. printf("sum=%d\n", sum);
  14. return 0;
  15. }
在一个有序数组中查找具体的某个数字n,编写int binsearch(int x,intv[],int n);功能:在v[0]<=v[1]<=v[2]<=...<=v[n-1]的数组中查找x
  1. #include <stdio.h>
  2. int main() {
  3. int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  4. int k = 7;
  5. //写一个代码,在arr数组中(有序的)找到7
  6. int i = 0;
  7. int sz = sizeof(arr) / sizeof(arr[0]);
  8. for (i < 0; i < sz; i++)
  9. {
  10. if (k == arr[i])
  11. {
  12. printf("找到了,下标是:%d\n", i);
  13. break;
  14. }
  15. }
  16. if (i == sz)
  17. printf("找不到\n ");
  18. return 0;
  19. }
  20. //输出:找到了
  21. //如果7那里改为17,就找不到
二分查找算法(折半)
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int k = 7;
  5. int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  6. int sz = sizeof(arr) / sizeof(arr[0]); //计算元素个数
  7. int left = 0; //左下标
  8. int right = sz - 1; //右下标
  9. while (left<=right)
  10. {
  11. int mid = (left + right) / 2; //根据下面随时调整
  12. if (arr[mid] > k)
  13. {
  14. right = mid - 1;
  15. }
  16. else if (arr[mid] < k)
  17. {
  18. left = mid + 1;
  19. }
  20. else
  21. {
  22. printf("找到了,下标是:%d\n", mid);
  23. break;
  24. }
  25. }
  26. if (left > right)
  27. {
  28. printf("找不到\n");
  29. }
  30. return 0;
  31. }
  • 上面int mid = (left + right) / 2;这行代码为什么不能写到while外面

  1. 可以将 int mid = (left + right) / 2; 这行代码写到 while 循环的外面,但这样做可能会导致程序的一些问题。因为在循环外面定义的变量 mid 的值只会在循环开始时计算一次,而在循环执行过程中,变量 left 和 right 的值可能会被修改,导致 mid 的值不再是数组中间的位置。这会导致程序无法正确地进行二分查找。
  2. 因此,将 int mid = (left + right) / 2; 这行代码放在 while 循环中,可以确保在每次循环开始时都重新计算数组的中间位置,以确保程序能够正确地进行二分查找。
编写代码,演示多个字符从两端移动,向中间汇聚
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h> //引strlen等字符串函数
  4. #include<windows.h> //引sleep
  5. #include <stdio.h>
  6. #include<stdlib.h> //引system
  7. #include <stdio.h>
  8. int main()
  9. {
  10. char arr1[] = "welcome to bit!!!!!!"; //数组元素个数不给定,用后面字符串去初始化它,字符串要求多少,数组就会开辟多少
  11. char arr2[] = "####################"; //把#换成空格食用效果更佳
  12. int left = 0;
  13. //int right = sizeof(arr1) / sizeof(arr1[0] - 2); //上一个是数组,没有/0,这是个字符串,有,所以减2
  14. int right = strlen(arr1)-1; //下标总是比元素个数少1,strlen遇到/0就停止,所以只需要-1
  15. while (left <= right)
  16. {
  17. arr2[left] = arr1[left];
  18. arr2[right] = arr1[right];
  19. printf("%s\n", arr2);
  20. //休息一秒
  21. Sleep(1000); //
  22. //执行系统命令的一个函数 - cls清空屏幕
  23. system("cls"); //
  24. left++;
  25. right--;
  26. }
  27. printf("%s\n", arr2);
  28. return 0;
  29. }
  30. //好玩捏
编写代码事项,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输如错误,则退出程序)
  • 注意 == 不能用来比较字符串是否相等,应该用strcmp函数

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include<string.h> //引strlen等字符串函数
  4. #include<windows.h> //引sleep
  5. #include <stdio.h>
  6. #include<stdlib.h> //引system
  7. #include <stdio.h>
  8. int main()
  9. {
  10. int i = 0;
  11. char password[20] = { 0 };
  12. for (i = 0; i < 3; i++)
  13. {
  14. printf("请输入密码:>");
  15. scanf("%s", password); //可以直接将数组名传递给scanf函数,而不需要取地址操作
  16. if (strcmp(password , "123456") ==0 )
  17. // ==不能用来比较两个字符串是否相等,应该使用一个库函数-strcmp,若前大于后,返回大于0的值
  18. {
  19. printf("登录成功\n");
  20. break;
  21. }
  22. else
  23. {
  24. printf("密码错误\n");
  25. //下面更人性化一点
  26. Sleep(500); //
  27. system("cls");//
  28. }
  29. }
  30. if (i == 3)
  31. printf("三次密码均错误,退出程序\n");
  32. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/691442
推荐阅读
相关标签
  

闽ICP备14008679号