分支语句
循环语句
goto语句
C语言的3种结构:
顺序结构
选择结构 分支语句(if switch)
循环结构 循环语句(while for do while)
C语言中由一个分号 ;
隔开的就是一条语句
;//空语句
1 + 2;//语句
if语句的语法结构是怎么样?
//1.
if(表达式)
语句;
//2.
if(表达式)
语句1;
else
语句2;
//3.多分支
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
如果表达式的结果为真,则语句执行。
在C语言中如何表示真假?
0表示假,非0表示真。
演示代码:
#include
int main()
{
int age = 20;
if (age >= 18)
printf("成年\n");
return 0;
}
#include
int main()
{
int age = 20;
if (age >= 18)
printf("成年\n");
else
printf("未成年\n");
return 0;
}
#include
int main()
{
int main = 20;
if (age < 18)
printf("青少年\n");
else if (age >= 18 && age < 30)
printf("青年\n");
else if (age >= 30 && age < 50)
printf("中年\n");
else if (age >= 50 && age < 80)
printf("老年\n");
else
printf("老寿星\n");
return 0;
}
错误写法:
int age = 10;
if (18 <= age < 30)//err
{
printf("青年\n");
}
if语句默认控制1条语句
若if语句控制多条语句,则加**{ }
,{ }
是一个代码块**
#include
int main()
{
int age = 20;
if (age > 18)
{
printf("成年\n");
printf("可以谈恋爱\n");
}
return 0;
}
#include
int main()
{
int a = 0;
int b = 2;
if (a == 1)
{
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
}
return 0;//代码不执行
}
结论:
else和最近的if匹配
同时也看出**{ }
**位置的重要性
代码风格非常重要,要养成良好的编码风格!
//代码1
if (condition) {
return x;
}
return y;//条件满足,return x;否则return y
//执行了return x,便不再执行return y
//代码2
if(condition)
{
return x;
}
else
{
return y;//代码1,代码2意思一样,代码2可读性更强
}
//代码3
int num = 1;
if(num == 5)
{
printf("hehe\n");
}
//代码4
int num = 1;
if(5 == num)
{
printf("hehe\n");
}
//代码4更严谨,单个=是赋值的意思,==是判断的意思
常量和变量比较相等的时候
常量放在左边 更好
//判断1个数是否为奇数
#include
int main()
{
int num = 0;
scanf("%d", &num);
//判断
if (num % 2 == 1)//余数为1
{
printf("%d是奇数\n", num);
}
else
{
printf("%d不是奇数\n", num);
}
return 0;
}
//输出1~100之间的奇数
#include
int main()
{
int i = 1;
while (i <= 100)
{
//判断i是否为奇数
//是奇数就打印
if (i % 2 == 1)
printf("%d ", i);
i++;
}
return 0;
}
//version2,省略了判断,并且循环次数减少一半
#include
int main()
{
int i = 1;
while (i <= 100)
{
printf("%d ", i);
i += 2;
}
return 0;
}
switch语句也是一种分支语句。 常常用于多分支的情况。
case—入口;break—出口(break的位置取决于代码实现逻辑)
switch(整型表达式)
{
语句项;
}
语句项是什么?
//是一些case语句:
//如下:
case 整形常量表达式:
语句;
演示代码:
#include
int main()
{
int day = 0;
scanf("%d", &day);//输入
switch (day)
{
case 1://入口
printf("星期1\n");
break;//出口
case 2:
printf("星期2\n");
break;
case 3:
printf("星期3\n");
break;
case 4:
printf("星期4\n");
break;
case 5:
printf("星期5\n");
break;
case 6:
printf("星期6\n");
break;
case 7:
printf("星期天\n");
break;
}
/*if (1 == day)
{
printf("星期1\n");
}
else if (2 == day)
{
printf("星期2\n");
}
else if (3 == day)
{
printf("星期3\n");
}*/
//...
return 0;
}
代码需求变化一下:
- 1-5 工作日
- 6-7 休息日
#include
int main()
{
int day = 0;
scanf("%d", &day);//输入
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
default:
printf("输入数据有误,请输入1-7的数字\n");
break;
}
return 0;
}
break语句的实际效果是把语句列表划分为不同的部分。
注意点:
switch(整形表达式)---//如果定义成float型,语法检查将不通过
{
//语句项;
case 整形常量表达式;//不能是变量
语句;
}
编程好习惯1
在最后一个 case 语句的后面加上一条 break语句。 (之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加
break语句)。
default子句
如果表达的值与所有的case标签的值都不匹配,所有的语句都被跳过程序并不会终止,也不会报错。
因此可以在语句列表中增加一条default子句。
default:
写在任何一个case标签可以出现的位置。
当 switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行。
每个switch语句中只能出现一条default子句。可以出现在语句列表的任何位置。
编程好习惯2
在每个 switch 语句中都放一条default子句是个好习惯,甚至可以在后边再加一个 break 。
default:
break;
练习
#include
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:m++;//m=3,无break,继续向下执行
case 2:n++;//n=2
case 3:
switch (n)//n=2
{//switch允许嵌套使用
case 1:n++;//跳过,不执行
case 2://执行
m++;n++;//m=4,n=3
break;//跳出当前switch语句
}
case 4:
m++;//m=5
break;//跳出当前
default:
break;
}
printf("m = %d, n = %d\n", m, n);//m=5,n=3
return 0;
}
根据switch表达式里的值决定从哪条case语句进入
由if语句
if(条件)
语句;
当条件满足,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。
当我们需要完成这样的例子:同一件事情我们需要完成很多次。那我们怎么做呢?
C语言中给我们引入了:while语句,可以实现循环。
//while 语法结构
while(表达式)
循环语句;
while(1)//为真执行,为假跳出循环
{
//死循环执行
}
实现:
在屏幕上打印1-10数字
#include
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d",i);
i++;
//i = i + 1;
}
return 0;
}
#include
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
break;
printf("%d",i);
i++;
}
//1 2 3 4
//break是永久的终止循环标志
return 0;
}
总结: break在while循环中的作用:
在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
while中的break是用于永久终止循环的。
//代码实例1
#include
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
continue;
printf("%d",i);
i++;
}
//1 2 3 4死循环
//continue作用:跳过本次循环continue后面的部分,来到while判断部分
return 0;
}
//代码实例2
#include
int main()
{
int i = 1;
while (i <= 10)
{
i++;
if (5 == i)
continue;
printf("%d",i);//2 3 4 6 7 8 9 10 11
}
return 0;
}
总结: continue在while循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断
switch语句里不会出现continue关键字
//代码1
#include
int main()
{
int ch = 0;
//ch = getchar();
//putchar(ch);
scanf("%c", &ch);
printf("%c\n", ch);
return 0;
}
循环输入输出
EOF - end of file - 文件结束的标志
getchar读取失败的时候就会返回EOF
//getchar遇到ctrl+z,返回EOF,程序结束执行
#include
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
return 0;
}
实现输入密码,并确认密码两个步骤
scanf函数运行后,输入缓冲区当前无内容,则键盘输入密码例:abcdef\n,其中abcdef是密码,被scanf获取,存入password;
随后getchar运行,输入缓冲区余下的\n被获取,存入变量ch,因此被else语句判为“输入失败”
代码需要实现getchar函数运行前,输入缓冲区为空,等待键盘输入内容
#include
int main()
{
int ch = 0;
char password[20] = {0};
printf("请输入密码>:");
scanf("%s", password);//数组就是地址,无需取地址符
printf("请确认密码(Y/N)>:");
ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
#include
int main()
{
int ch = 0;
char password[20] = {0};
printf("请输入密码>:");
scanf("%s", password);//数组就是地址,无需取地址符
getchar();//作用:拿走\n
//不可取!!!
printf("请确认密码(Y/N)>:");
ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
问题:
getchar一次只能取走1个字符
scanf遇到空格,停止读取
如果密码中间出现空格,且空格后还有多余内容,getchar只会取走空格,将出现运行错误
目的是将输入缓冲区字符清空
scanf()语法中,遇到空格就会停下来
#include
int main()
{
int ch = 0;
char password[20] = {0};
printf("请输入密码>:");
scanf("%s", password);
while((ch = getchar()) !='\n')
{
;//空语句,什么都不干
}
//加while循环,getchar1位1位读取,放入ch变量,直到读到\n,跳出循环
printf("请确认密码(Y/N)>:");
ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
gets()读取带空格输入
#include
int main()
{
char password[20] = {0};
gets(password);
printf("%s",password);
return 0;
}
由ASCII值范围筛选打印结果
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
if (ch < '0' || ch>'9')//只打印数字,过滤其他
{
continue;
}
putchar(ch);
}
return 0;
}
//while循环3部分分离,当代码量较多时,不便于修改和查找
#include
int main()
{
int i = 1;//1.初始化值
while (i <= 10)//2.判断
{
printf("%d ", i);
i++;//3.调整
}
return 0;
}
while循环中存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便
所以,for循环的风格更胜一筹。 for循环使用的频率也最高
for(表达式1;表达式2;表达式3)
循环语句;
表达式1为初始化部分,用于初始化循环变量的。
表达式2为条件判断部分,用于判断循环终止。
表达式3为调整部分,用于循环条件的调整。
使用for循环 在屏幕上打印1-10的数字。
#include
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}//3部分集中
return 0;
}
for循环的执行流程图:
#include
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (5 == i)
break;
printf("%d ", i);
}
return 0;
}
for循环中的continue,跳过continue后边的代码去了调整部分,调整循环变量,不容易造成死循环。
while循环中的continue,跳过continue后边的代码直接去判断部分,容易造成死循环。
#include
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (5 == i)
continue;
printf("%d ", i);
}
return 0;
}
一些建议
- 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
- 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
#include
int main()
{
int arr[10] = { 0 };//0~9
int i = 0;
for (i = 0; i <10; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
变种1
初始化,判断,调整 三个部分都省略了
#include
int main()
{
int i = 0;
for (; ; )
{
printf("hehe\n");//死循环打印hehe
}
int i = 0;
for (i=0; ;i++)
{
printf("hehe\n");//死循环打印hehe
}
return 0;
}
#include
int main()
{
int i = 0;
int j = 0;
for (; i < 10; i++)
{
for (; j < 10; j++)
{
printf("hehe\n");//打印10个hehe
}
//j=10
}
return 0;
}
变种2
#include
int main()
{
int x, y;
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
//请问循环要循环多少次?
#include
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
do
循环语句;
while(表达式);
//打印1-10
#include
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
}
while (i <= 10);
return 0;
}
#include
int main()
{
int i = 1;
do
{
if (i == 5)
break;//输出结果:1 2 3 4;break终止循环
printf("%d ", i);
i++;
}while (i <= 10);
return 0;
}
#include
int main()
{
int i = 1;
do
{
if (i == 5)
continue;//输出结果:1 2 3 4 死循环;跳过continue后面的部分,不执行i++
printf("%d ", i);
i++;
}while (i <= 10);
return 0;
}
循环至少执行一次,使用的场景有限,所以不是经常使用。
1.计算 n的阶乘。
int main()
{
int n = 0;
scanf("%d", &n);//8
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
printf("%d\n", ret);
return 0;
}
2. 计算 1!+2!+3!+……+10!
int main()
{
int n = 0;
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 3; n++)//存在bug
{
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
sum = sum + ret;
}
printf("%d\n", sum);
return 0;
}
//程序可以运行,但是结构是错误的 - 运行时错误
//调试 - 一步一步的执行代码,观察代码是不是按照我们期望的效果来走的,如果发现不是是按照期望的效果在走
//bug就出现了!
//F10 - 单步执行(逐过程)
//F11 - 单步执行(逐语句) - 遇到自定函数,想进入函数,你可以按F11
//改进
#include
int main()
{
int n = 0;
int i = 0;
int ret = 1;
int sum = 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;
}
//1!+2!+3! =
//1 + 2 + 6 = 9
//4!
//5! = 4!*5
//6! = 5!*6
//7! = 6!*7
//原理:n! = (n-1)!*n
//
#include
int main()
{
int n = 0;
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 3; n++)
{
ret = ret * n;
sum = sum + ret;
}
printf("%d\n", sum);
return 0;
}
3.在一个有序数组中查找具体的某个数字n。 编写int binsearch(int x, int v[], int n); 功能:在v[0]
<=v[1]<=v[2]<= ….<=v[n-1]的数组中查找x
数组下标:0~9
在有序数组arr中找7
找到了打印下标,找不到打印:找不到
#include
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
int k = 7;
//求数据的元素个数
// 40 / 4
int sz = sizeof(arr)/sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
if (arr[i] == k)
{
printf("找到了,下标是:%d\n", i);
break;
}
}
if (i == sz)
{
printf("找不到\n");
}
return 0;
}
#include
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//0~9
//在有序数组arr中找7
//找到了打印下标,找不到打印:找不到
//折半查找(二分查找)
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0; //左下标
int right = sz - 1; //右下标
int k = 17; //被查找的数字
while (left<=right) //多次循环
{
int mid = (left + right) / 2;
if (arr[mid] > k)
{
right = mid - 1;
}
else if (arr[mid] < k)
{
left = mid + 1;
}
else
{
printf("找到了,下标是:%d\n", mid);
break;
}
}
if (left > right)
{
printf("找不到\n");
}
return 0;
}
4.编写代码,演示多个字符从两端移动,向中间汇聚。
//hello world!!!!!!!
//##################
//h################!
//he##############!!
//..
//hello world!!!!!!!
#include
#include
#include
#include
int main()
{
char arr1[] = "hello world!!!!!!!";
char arr2[] = "##################";
int len = strlen(arr1);
int left = 0;
int right = len - 1;
while (left<=right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000);//1000毫秒 - 1秒
system("cls");//清空屏幕
//system是库函数,用来执行系统命令的
left++;
right--;
}
printf("%s\n", arr2);
return 0;
}
5.编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,
则退出程序。
两个字符串比较,不能使用==
strcmp()用来比较字符串内容,返回值为0则相同
#include
#include
int main()
{
int i = 0;
char password[20] = {0};
//假设密码是:abcdef
for (i = 0; i < 3; i++)
{
printf("请输入密码:>");
scanf("%s", password);
//if(password == "abcdef")//数组起始地址和字符串地址比较,并非比较内容相同
if (strcmp(password, "abcdef") == 0)
{
printf("登录成功\n");
break;
}
else
{
printf("密码错误!\n");
}
}
if (i == 3)
{
printf("三次密码输入错误,退出程序\n");
}
return 0;
}
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
示例:
#include
int main()
{
again:
printf("hehe\n");//hehe死循环
goto again;
return 0;
}
goto语句不能跨函数调用
#include
void test()
{
again:
}
int main()
{
printf("hehe\n");//不能跨函数调用
goto again;
return 0;
}
goto语言真正适合的场景如下:
for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
…
error:
if(disaster)
//处理错误情况
程序运行起来就倒计时关机,1分钟内,输入:我是猪,就取消关机
goto语句
//关机程序
#include
#include
#include
int main()
{
char input[20] = { 0 };
system("shutdown -s -t 60");
again:
printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
scanf("%s", input);
if (strcmp(input, "我是猪") == 0)
{
system("shutdown -a");
}
else
{
goto again;
}
return 0;
}
while语句
#include
#include
#include
int main()
{
char input[20] = { 0 };
system("shutdown -s -t 60");
while (1)
{
printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
scanf("%s", input);
if (strcmp(input, "我是猪") == 0)
{
system("shutdown -a");
break;
}
}
return 0;
}
猜数字的游戏
生成一个随机数
猜数字(反馈:大、小、对了)
可以反复玩
#include
#include //rand(); srand();头文件
#include //time();头文件
void menu()
{
printf("***************************\n");
printf("******* 1. play ******\n");
printf("******* 0. exit ******\n");
printf("***************************\n");
}
void game()
{
int guess = 0;
//猜数字游戏的逻辑
//1. 生成随机数(1~100)
int ret = rand()%100+1;
//printf("%d\n", ret);
//2. 猜数字
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);//输入猜的数字
if (guess < ret)
{
printf("猜小了\n");
}
else if (guess > ret)
{
printf("猜大了\n");
}
else
{
printf("恭喜你猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
//设置随机数的生成起点
srand((unsigned int)time(NULL));//拿时间戳作为参数,只调用1次
//C语言获得时间戳:time();同时不使用参数,NULL
//time_t-返回类型-拷贝在vs编译器内查看-long long类型
do
{
//打印菜单
menu();
printf("请选择:>");
scanf("%d", &input);//1或0或其它
switch (input)
{
case 1:
game();//调用游戏函数
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
//0 表示假,非0表示真
return 0;
}