目录
分支语句
一.if语句
1.if语句使用的基本方法
单分支 | 多分支 |
if(表达式) 语句; 或 if(表达式) 语句1; else 语句2; | if(表达式1) 语句1; else if(表达式2)//多种判断用else if 语句2; else 语句3; //注意在语句前加上适当的空格 |
(1)表达式:表达式是决定选择方向的条件,当表达式结果为真时执行下面的语句,为假时进入其他位置执行下面的语句。
(2)C语言对真假的判断:在C语言中,0表示假,非零表示真。
(3)语句:表示上面表达式为真时所执行的代码。
(4)注意加上空格以保证代码的可读性。
#include<stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age>=18)
printf("成年");
else
printf("未成年");
return 0;
}
(5)当需要执行的语句多于一条时,注意要加上代码块——{}。
#include<stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age>=18)
{
printf("成年\n");
}
else//这是正确的
{
printf("未成年\n");
printf("不能去网吧");
}
//else //将{}去掉
//printf("未成年\n");//else只会对应这条语句
//printf("不能去网吧"); //这条语句无论进入if还是else都会执行
return 0;
}
(6)添加更多的分支时使用else if ()语句
#include<stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age<18)
printf("青少年\n");
else if (age>=18 && age<30)//不能写作18<=age<30
printf("青年\n");
else if (age>=30 && age<40)
printf("壮年\n");
else if (age>=40 && age<60)
printf("中年\n");
else if (age>=60 && age<80)
printf("老年\n");
else
printf("老寿星\n");//老不死(划掉)
return 0;
}
2.悬空else导致的小误会
请看以下代码:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)//a不等于1
if(b == 2)
printf("hehe\n");
else//这个else会对应离他最近的if,也就是if(b == 2)
printf("haha\n");
return 0;
}
输出:不打印
再没有看到后面的注释时,肯定有人会认为a不等于1,进入else打印haha,但实际上是不对的
如果我们,加上{}对代码进行可读性优化
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
{
if(b == 2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
}
return 0;
}
输出:不打印
我们将这个代码改正,使它具有选择的功能
#include<stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
{
if(b == 2)
{
printf("hehe\n");
}
}
else
{
printf("haha\n");
}
return 0;
}
//输出:打印haha
(1)else语句会对应离它最近的那个if语句
(2)选择语句if在使用时,如果我们对else的范围没有操作,else可以省去
(3)对于优化代码我的建议是不管是一条还是多条语句都加上{},这样保证了代码的可读性。
3.代码风格与赋值运算符错误
(1)好的代码风格可以增强代码的可读性,让代码更加清晰明了。
//代码1
if (condition)
{
return x;
}
return y;
//代码2
if(condition)
{
return x;
}
else
{
return y;
}
//这两段代码的实际作用是一样的,当表达式的值为真时返回x,否则返回y
//但是相比而言,第二个代码的表达更加清晰,多写一个else也并不费力
(2)我们再写代码的初期常会遇到一个问题,我们经常会把‘==’符号写作‘=’(这里点名批评我自己😅)
#include<stdio.h>
int main()
{
int a = 0;
if (a = 1)//这个表达式表示把1赋值给a,表达式的值为1,为真,打印hehe
{
printf("hehe\n");
}
if (a = 0)//这个表达式表示把0赋值给a,表达式的值为0,为假,不打印haha
{
printf("haha\n");
}
return 0;
}
//只要一个等于号符的值不为0,程序就可以正常运行
而且这样的错误非常难找,那么我们应当怎样避免这样的错误呢,请看以下代码:
//代码3
int num = 1;
if(num == 5) //只是单纯判断num是不是等于5,少写一个等于号依旧正常运行
{
printf("hehe\n");
}
//代码4
int num = 1;
if(5 == num)
//有判断作用,但少写一个等于号时(5 = num)
//5是一个常量,而num是一个变量,变量的值不能赋给常量,编译器报错
{
printf("hehe\n");
}
if (num%2 == 1)//表达式不需要颠倒,因为表达式本来就不能赋值
{
printf("hehe\n");
}
(3)当我们需要的条件是判断一个变量是否等于某个常量时,通过将变量和常量颠倒的方法就有效避免了这样的低级错误。表达式不需要颠倒。(只适用于判断a == 1这样的条件)
4.两个练习
(1)判断一个数是否为奇数
#include<stdio.h>
{
int num = 0;
scanf("%d",num);
if (num%2)
{
printf("是奇数\n");
}
else
{
printf("不是奇数\n");
}
return 0;
}
(2)输出1到100之间的奇数
#include<stdio.h>
{
int num = 0;
for (num=1; num<=100; num++)
{
if(num%2 == 1)
{
printf("%d ",num);
}
}
return 0;
}
#include<stdio.h>
{
int num = 0;
for (num=1; num<=100; num+=2)//这样也可以就是不是选择结构了
{
printf("%d ",num);
}
return 0;
}
二、switch语句
1.switch语句使用的基本方法
switch语句常常用于多分支的情况。
比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
我们使用if语句就太麻烦了,而switch语句更适合这样的程序。
switch语句的使用如下:
switch(整型表达式)
{
case 整形常量表达式:
语句;
case 整形常量表达式:
语句;
case 整形常量表达式:
语句;
......
}
2.case与break语句在switch语句中的使用
(1)在switch语句中,case语句只表示程序的入口,当输入的值符合case后的常量表达式时,程序会进入这个入口,从上向下执行。加上break就可以跳出switch语句以达到分支的目的。
#include <stdio.h>
int main()
{
int day = 0;
switch(day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
}
return 0;
}
(2)switch语句中几个常量表达式也可以对应一条语句
比如:
输入1-5,输出工作日
输入6或7,输出休息日
#include <stdio.h>
//switch代码演示
int main()
{
int day = 0;
switch(day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
//此时1到5都会从对应的入口进入,向下走执行对应的语句
break;//跳出
case 6:
case 7:
printf("weekend\n");
//此时6到7都会从对应的入口进入,向下走执行对应的语句
break;//跳出
}
return 0;
}
(3)记得在最后一个 case 语句的后面加上一条 break语句。(在使用上最后一条语句可以不加case,但一旦有人想往下面加代码,哪如果变量值等于原来的那个最后的常量值,就会执行至少两次代码)
3.default语句的使用
当表达式的值与每一个case语句都不匹配时,你也想执行一些代码处理数据时,就可以加上default语句
default:
(1)每个switch语句中只能出现一条default子句。
(2)default语句可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。
下面做一个小练习:
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{//switch允许嵌套使用
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
}
输出:m = 5,n = 3
分析:
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)//此时n为1
{
case 1://进入
m++;//m变为3
case 2://继续
n++;//n变为2
case 3://继续
switch (n)//此时n为2
{//switch允许嵌套使用
case 1:
n++;
case 2://进入
m++;//m变为4
n++;//n变为3
break;//跳出case 3:的嵌套switch
}
case 4://继续
m++;//m变为5
break;//跳出外部switch
default:
break;
}
printf("m = %d, n = %d\n", m, n);//m = 5,n = 3
return 0;
}
//输出:m = 5,n = 3
循环语句
一、while循环
while是循环语句中最简单的一个,不常用
1.while循环使用的基本方法
语句使用 |
while(表达式) 循环语句; |
与上面的if语句类似,括号中的表达式是判断循环是否进行的依据。
表达式结果为真时,循环继续进行;为假时,跳出循环。
现在我们使用循环打印1-10的数字
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ", i);
i = i+1;
}
return 0;
}
2.while循环中break与continue的使用方法
(1)break
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)//循环4次后,第5次进入循环时,满足条件
break;//直接跳出循环
printf("%d ", i);
i +=1;
}
return 0;
}
//输出:1 2 3 4
在循环中只要遇到break,就停止后期的所有操作,直接终止循环。而如果存在嵌套循环,只跳出它所在的那个循环。
结论:while中的break是用于永久终止循环的。
(2)continue
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
i +=1;//先将i加1
if(i == 5)//循环3次后,第4次进入循环时,满足条件
continue;//跳过下面的语句并继续循环,就不会打印5
printf("%d ", i);
}
return 0;
}
//输出:2 3 4 6 7 8 9 10 11
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
结论:continue可以跳过下面的语句,在此基础上继续循环。
(3)小练习
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)//循环4次后,第5次进入循环时,满足条件
continue;//跳过下面的语句并继续循环
//跳过i+=1;语句后,i=5的值不会被改变,这就变成了一个死循环
printf("%d ", i);
i +=1;
}
return 0;
}
//输出:1 2 3 4 死循环
3.练习
(1)输入一个字符并打印它
- getchar()与putchar()函数
getchar()函数:从内存缓冲区中找到并拿走输入的一个字符
当你没有输入字符时,getchar函数会先等待输入,当内存缓冲区
putchar()函数:打印一个字符
- 内存缓冲区
我们前面提到getchar函数时从内存缓冲区中拿出一个字符,那这个内存缓冲区又是什么呢?
缓冲区是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
也就是说,输入的内容不会直接进入内存中而是先进入内存缓冲区,再进入内存。
- 什么是EOF
EOF表示end of file(文件结束标志),在计算机中它的它定义是一个-1
#include <stdio.h>
int main()
{
int ch = 0;
//定义一个字符,因为字符在计算机中储存为ASCII码值,所以可以定义为整形
while ((ch = getchar()) != EOF)//当取到输入字符为EOF时,跳出循环
putchar(ch);//putchar用于打印单个字符,打印ch
return 0;
}
//getchar()函数可以在内存缓冲区中读取到一个输入字符
//(ch = getchar())表示把getchar()得到的字符赋给ch这个函数的返回值,它的返回值应该是字符ch对应的ASCII码值
//(ch = getchar()) != EOF 表示函数返回值不是EOF
//注意:我们想向下运行程序需要按回车,回车输入的\n也是一个字符,相当于程序运行了两遍
//getchar先读取到你输入的字符,比如字母a,然后缓冲区中还有一个输入的\n
//相当于getchar先找到你输入的字符进行打印,然后又找到了\n,进行打印
//这个while语句实现了多次输入,而当我们想结束程序跳出循环时,只需要按ctrl+z就会使函数读取到EOF
//输入:a
//输出:a
//
(2)打印字符串中的数字字符
//代码2
#include <stdio.h>
int main()
{
char ch = '\0';//对ch进行初始化,而'\0'的ASCII码为0
while ((ch = getchar()) != EOF)//一个一个读取
{
if (ch < ‘0’ || ch > ‘9’)//相当于把它们的ASCII码值进行比较
continue;//ch为非数字字符进入,跳过putchar
putchar(ch);//为数字字符,不进入if,打印
}
return 0;
}
//输入:abc1dcwrew123
//输出:1123
二、for循环
for循环时我们在c程序中使用最多的一个
1.for循环使用的基本方法
语句使用 |
for(表达式1; 表达式2; 表达式3) 循环语句; |
其中,表达式1负责初始化,用于初始化循环变量;表达式2负责判断,用于判断循环时候终止;表达式3负责调整,用于循环条件的调整。
我们先初始化一个循环变量,例如:i = 1;
然后,我们给出一个判断循环结束的条件,例如:i
最后加上调整的语句对循环变量进行调整,例如:i++
当我们把他们集合起来时,我们就可以用for循环写一个小程序:打印数字1-10
#include<stdio.h>
int main()
{
int i = 0;
for (i=1; i<=>10; i++)
//这里的i被初始化为0,这个省去对程序运行也没有影响,但为了避免出错还是应当加上
{
printf("%d ",i);//当i的值满足i<=10时打印i
//在程序内的语句块执行完成后,程序执行调整语句i++,然后再次判断是否满足循环条件
}
return 0;
}
//输出:1 2 3 4 5 6 7 8 9 10
while循环依旧可用,但for循环更好。
请看以下代码:
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)//循环4次后,第5次进入循环时,满足条件
continue;//跳过下面的语句并继续循环
//跳过i+=1;语句后,i=5的值不会被改变,这就变成了一个死循环
printf("%d ", i);
i +=1;
}
return 0;
}
//输出:1 2 3 4 死循环
我们将它改写为for循环,这个程序就更容易控制,不易出现bug
#include <stdio.h>
int main()
{
int i = 1;
for (i=1; i<=10; i++)
{
if(i == 5)//循环4次后,第5次进入循环时,满足条件
continue;//跳过下面的语句进行调整后继续循环,i不会保持在5的数值上
printf("%d ", i);
}
return 0;
}
//输出:1 2 3 4 6 7 8 9 10
2.break与continue语句的使用
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
break;
printf("%d ",i);
}
return 0;
}
//输出:1 2 3 4
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
continue;//等于5的时候跳过了打印
printf("%d ",i);
}
return 0;
}
//输出:1 2 3 4 6 7 8 9 10
结论:for循环中break与continue语句作用与while循环中相同
3.for循环中需要注意的一些问题
(1)尽量采用前闭后开的写法,但是否需要这样写需要看情况
#include<stdio.h>
int maiin()
{
int i = 0;
//前闭后开的写法,可以清晰地表达出循环的次数
for(i=0; i<10; i++)
{}
//两边都是闭区间
for(i=0; i<=9; i++)
{}
}
//这两种写法都对,需要视情况酌情考虑
(2)不要在语句块内部改变循环变量以防循环失去控制
(3)特殊for循环写法
#include <stdio.h>
int main()
{
//代码1
for(;;)
{
printf("hehe\n");
}
//for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议省略。
//代码2
int i = 0;
int j = 0;
//根据for循环的嵌套,这里会打印100个hehe
for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
printf("hehe\n");
}
}
//代码3
int i = 0;
int j = 0;
//如果省略掉初始化部分,这里只打印10个hehe
for(; i<10; i++)
{
for(; j<10; j++)
{
printf("hehe\n");
}
}
//在第一次进入循环时程序正常工作j=10时跳出循环,没有初始化变量j就会一直保持10,
//从此不会再次进入循环,i从1变到10的过程中只是孤零零地重复了9次,没有操作
//代码4,可以使用多个变量控制循环
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
4.笔试题
//请问循环要循环多少次?
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
//答案:零次,在for循环的判断那里k=0的表达式值本来就为0,0为假不循环
三、do while循环
do while是个比较“愣”的循环语句,语句块至少执行一次,也不常用
1.do while循环使用的基本方法
语句使用 |
do 循环语句; while(表达式); |
其中,表达式判断是否继续循环,循环语句时循环执行的内容。而这个循环为什么说他愣呢?因为它不管条件符不符合它就先干,干完在判断是否需要继续再干一遍。
特点:循环至少执行一次。
#include <stdio.h>
int main()
{
int i = 10;
do//先干,干就完了
{
printf("%d\n", i);
}while(i<10);//判断能不能接着干,不能,跳出
return 0;
}
//输出:10
//
2.do while循环中的break和continue
#include <stdio.h>
int main()
{
int i = 0;
do
{
if(5 == i)
break;
printf("%d ", i);
}while(i<10);
return 0;
}
//输出:1 2 3 4
#include <stdio.h>
int main()
{
int i = 0;
do
{
if(5 == i)
continue;
printf("%d ", i);
}while(i<10);
return 0;
}
//输出:1 2 3 4 6 7 8 9 10
结论:三种循环中break与continue语句的作用完全一致
四、goto语句
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句其实也可以很容易的写出代码。
goto语句也有它的作用,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
…
error:
if(disaster)
// 处理错误情况
用break语句只能跳出一层循环,而goto就可以一次跳出。
不过这东西是有名的bug来源之一,能不用尽量不用。
过后加更分支循环的应用