目录
前言
C语句可分为以下五类:
- 表达式语句
- 函数调用语句
- 控制语句
- 复合语句
- 空语句
C语言有9种控制语句
- 条件判断语句也叫分支语句:if语句、switch语句;
- 循环执行语句:do while语句、while语句、for语句;
- 转向语句:break语句、goto语句、continue语句、return语句。
if语句
语法结构分为以下三种:
①if(表达式) 语句;
if(表达式) 语句1; else 语句2;
if(表达式1)//多分支 语句1; else if(表达式2) 语句2; else 语句3;
●C语言中,0表示假,1表示真。如果if内的条件判断为真值,则执行语句,否则不执行或执行else。
●if语句如果不加大括号{},就只能控制一条语句。
●if语句中的else只和最近的if匹配
if语句如何使用呢?写个简单的判断:
#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<50) { printf("中年\n"); } else if(age>=50 && age<80) { printf("老年\n"); } else { printf("老寿星\n"); } }
switch语句
语法结构:
switch(整型表达式) { case 整形常量表达式: 语句;
- 在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。break语句的实际效果是把语句列表划分为不同的分支部分。
- case即入口,整型表达式给出的常量等于多少,就进入对应的case入口
- 如果表达的值与所有的case标签的值都不匹配,就可以定义一个default子句-default:它可以放在任何case可以出现的地方。当switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行。
- 每个switch语句中只能出现一条default子句
- break放在哪里,就在哪里结束switch语句
- switch允许嵌套使用
switch语句的使用:写个简单的判断输入的天数是工作日休息日
int main() { int day = 0; scanf("%d", &day);//3 switch (day) { case 1: case 2: case 3: case 4: case 5: printf("工作日\n"); break; case 6: case 7: printf("休息日\n"); break; default: printf("输入错误\n"); break; } return 0; }
while循环
语法结构:
while(表达式) 循环语句;
- 当while循环在执行过程中遇到break的时候,就永久终止循环
- 当while循环遇到continue的时候,就终止本次循环,本次循环中continue后边的代码不会再执行,然后回到判断部分进行判断是否继续执行循环。
for循环
语法结构:
for(初始化部分; 条件判断部分; 调整部分)
- for循环中也可以出现break和continue,它们的意义和在while循环中是一样的。
- for循环中可以用多个变量控制循环。比如for (x = 0, y = 0; x<2 && y<5; ++x, y++)
for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题
do while循环
语法结构:
do 循环语句; while(表达式);
- 特点:循环至少执行1次,上来就干,所以不是经常使用
- break和continue同样可以在这个循环中使用
goto语句
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
语法结构:
标签: 语句; goto 标签;
- goto语句最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,比如一次跳出两层或多层循环。
- 其余情况一般不常用,完全可以用其他循环替代它
- goto语句不能跨函数跳转!
学习完了这些语句,接下来做一些实战。
二分查找法
- 问题描述:给定一个有序数组int arr[]={1,2,3,4,5,6,7,8,9,10};查找7在数组中的下标,找到了则输出下标,没找到则输出找不到。
- 利用arr[0],arr[1],arr[2]…这样依次去进行数值大小判断,诚然可行,但是这是顺序排列的数组,显然效率不够高,这里就可以引入一个思想:二分查找法。
- 假设你在进行猜数字的游戏,这个游戏不给出任何的提示,只告诉你数值在0~500之间,每次输入不正确,就告诉你这个值是大了还是小了。那怎么整呢?从1开始输入到500,一个个去判断吗?当然不,我们可以取出0~500的中位数,折半变成250,如果这个数大了,那就在左边再次折半变成125,然后125再判断…这样反复的折半,最终总会定位到一个数值。次数显然远远低于一个个去判断。有了这个思路,就简单了。
1.本题中arr中左极端下标left初始值为0,右极端下标right为(sizeof(arr)/sizeof(arr[0]))-1 (注:右极端下标求法是利用所占内存来计算元素个数,元素个数-1就是右极端的下标)
2.中间的下标mid=(left+right)/2=(0+9)/2=4,下标对应值5<7,也就意味着mid左边的值必然小了,则mid左边的值包括mid全部作废。right不动,mid向右边移一位,右移后的mid就当作新的left,即left=mid+1=5
3.新的mid=(left+right)/2=(5+9)/2=7,下标mid对应值8>7,也就意味着mid右边的值包括mid全部作废,则left不动,mid向左移一位,作为新的right,即right=mid-1=6然后继续求新的中间值mid。
4.新的mid=(left+right)/2=(5+6)/2=5,下标mid对应值是6<7,也就意味着mid左边的值包括mid全部作废,则right不动,mid向右边移一位当成新的left,即left=mid+1=6然后继续求新的中间值mid。
5.以上操作实际上就是一个循环。继续执行循环,新的mid=(left+right)/2=(6+6)/2=6,此时left=right,结束循环。
6.在循环的过程中,left始终向右靠近,而right始终向左靠近,当left>right的时候,也就无值可找了。于是跳出循环。这样的描述太过抽象,搭配图解:
于是程序代码如下:
#define _CRT_SECURE_NO_WARNINGS 1; #include <stdio.h> int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; int k; printf("请输入要查找的数值k="); scanf("%d",&k); int sz = sizeof(arr) / sizeof(arr[0]);//求元素数量 int left = 0;//首个下标 int right = sz - 1;//最后一个元素的下标 while (left<=right)//left和right是不断相互靠近的,left>right的时候,就说明已无值可查了 { int mid = (left + right) / 2;//求二分平均值 if (arr[mid] < k)//若arr[mid]比k小,则说明k在mid的右边,那么left就要等于mid+1(因为每次查找完,不应该按mid算,那样就重复了) { left = mid + 1;//left右移 } else if (arr[mid] > k)//若arr[mid]比k大,则说明k在mid的左边, 那么right就要等于mid - 1; { right = mid - 1;//right左移 } else//当arr[mid]=k的时候,就找到了 { printf("找到啦,是下标为%d的元素", mid); break;//找到的时候就结束循环 } } if (left > right)//当left和right交叉以后,也就无值可找了 { printf("找不到"); } return 0; }
字符从两端向中间汇聚
●问题描述:有这样长度相等的两串字符串①welcome my code world②###############
程序执行的时候,先用①中的第一个字符和最后一个字符替换②中的第一个字符和最后一个字符,然后用①中第二个和倒数第二个替换②中对应位置的字符…从两边向中间靠拢,形成一个动态的效果。
●思路:1.首先定义两个字符串数组,利用下标的改变来进行对应的替换。2.定义两个变量作为下标,初始值分别为左右极端下标值。3.然后利用循环,对两个变量进行递增递减,左下标从0依次递增,右下标从右极端依次递减。从而实现左边的字符往右边靠拢,右边的字符往左边靠拢。4.这样循环执行n次,两边同时往中间靠拢,总会有一个界限,当左下标跟右下标交叉的时候,即左下标>右下标的时候,就无值可取了,终止循环。
于是源码如下:#include <stdio.h> #include <string.h> #include <windows.h> #include <stdlib.h> int main() { char arr1[] = "welcome my code world"; char arr2[] = "#####################"; int left = 0;//左极端初始下标 int right = strlen(arr1)-1;//右极端初始下标,strlen()是求字符串长度的函数,由<string.h>给出 while (right >= left)//当右极端值大于左极端值的时候,就说明可以继续向中间靠拢 { arr2[left] = arr1[left];//把字符串数组arr1[]左端的字符赋给arr2[] arr2[right] = arr1[right];//把字符串数组arr1[]右端的字符赋给arr2[] left++;//左下标+1,左端往右边靠拢 right--;//右下标-1,右端往左边靠拢 printf("%s\n", arr2);//输出arr2; Sleep(1000);//休息一秒钟,这个函数由<windows.h>给出,休息一秒钟能让动态效果更明显 system("cls");//清空屏幕,这个函数由<stdlib.h>给出,清空屏幕才有动态的效果。 } printf("welcome my code world");//程序到了循环的最后,会被cls清空屏幕,所以这个要加输出语句 return 0; }
模拟卡密系统
●问题描述:模拟用户输入卡密的程序,预设卡密为:woaixuexi,然后判断输入的内容是否为卡密。最多输错三次,三次以后,就结束程序。
程序较简单,就不写思路了,直接看源码的注释吧#define _CRT_SECURE_NO_WARNINGS 1; #include <stdio.h> #include <string.h> int main() { char arr[20] = {0};//定义一个字符数组存放输入的卡密 int i = 0; for (i=1;i<=3;i++)//给定3次循环 { printf("请输入卡密\n"); scanf("%s", &arr); if (strcmp(arr, "woaixuexi") == 0) { printf("卡密正确,进入系统\n"); break; } else printf("输入错误\n"); } return 0; }
值得一提的是:两个字符串的比较不能使用等号,应该使用strcmp()函数,strcmp判断两个字符串若相等,则返回0。
猜数字游戏实现
●问题描述:
①自动产生一个1~100的随机数②输入一个数字,猜对了,游戏结束。猜错了,就告诉你猜大了还是猜小了,继续猜,直到猜对③游戏可以一直玩,除非退出程序
●思路:①执行程序,就进入游戏菜单,于是需要定义一个菜单函数。用do while语句非常合适,上来就干②输入1开始游戏,输入0结束程序,输入其他的内容就提示输入错误重新输入。于是在do while后面的while的中,就可以用这个输入的1与0来作为条件判断了,1为真,0为假,输入0,while循环就结束。③输入1,则执行游戏,于是我们还需要定义一个游戏函数。游戏函数首先要生成一个1~100的随机数,这是这个程序的关键点。怎样实现它呢?我们需要了解这样一个库函数:rand(),这个函数会返回一个0-32767之间的数字,它定义于头文件<stdlib.h>中。rand是随机数,模上100,得到的余数就是0~99,再加一个1,得到的就是1~100。但是我们发现,这个rand虽然每次生成的随机数不同,但是每次重新执行程序的时候,生成的数值都是固定不变的。玩家玩了第一次之后,关闭程序重新开始游戏,结果第二次的结果还是和第一次一样,这样的游戏玩下去还有什么意思呢?所以我们必须让这个rand每次关闭游戏后重新打开都会生成不一样的数值。于是我们使用库函数:srand(),它也定义于头文件<stdlib.h>中,它的作用是定义rand的随机数变化初始值,也就是说srand决定了rand()的变化。只要srand发生变化,rand()也就发生了变化。那么如何让srand发生变化呢?就要用到时间戳这个东西了,时间戳是1970年1月1日(00:00:00)至当前时间的总秒数,时间在时刻不断的发生变化,那么,我们只需要把时间戳作为srand的参数,那么每次关闭程序,时间都不同,那么rand的初始值也就不同了,于是棘手的问题就会迎刃而解了,时间戳可以用time()获取,time是由库函数<time.h>给出的。值得一提的是,srand应该只设置一次时间戳,如果每次答对了就重新设置一次srand,rand生成的数字加了几十秒然后取模100,可想而知,我们将会得到的初始值是会很相近的,那样随机度极大的减少了。④随机数的问题解决了,然后定义一个死循环,进行可以反复猜测的猜数字。然后就是简单的判断了,如果答对了,就break跳出循环,回到菜单。源码如下:#define _CRT_SECURE_NO_WARNINGS 1; #include <stdio.h> #include<time.h> #include<stdlib.h> void menu()//菜单函数 { printf("**********************\n"); printf("****** 1. play *******\n"); printf("****** 0. exit *******\n"); printf("**********************\n"); } void game()//游戏函数 { //生成随机数 int ret = rand()%100+1; int sum;//sum是输入的数字 while (1)//定义一个死循环,可以反反复复猜数字 { scanf("%d", &sum); if (sum > ret)//判断部分 { printf("输入值过大\n"); } else if (sum < ret) { printf("输入值过小\n"); } else { printf("恭喜你,答对啦\n"); break;//如果输入正确,就跳出本循环,重新执行switch语句 } } } int main() { srand((unsigned int)time(NULL));//时间戳作为srand的参数。srand是rand的初始值,数据类型为无符号整型,这个函数需要要在rand使用前定义。时间戳time(NULL)表示不储存。 int input = 0; do { menu();//打印菜单 printf("请选择:>"); scanf("%d",&input); switch (input) { case 1://输入1则进行游戏 game(); break; case 0://输入0则退出游戏 printf("退出游戏\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input);//如果输入1,则继续执行循环,如果输入0,则为假,结束循环。输入其他,则为真,提示输入错误 }
整蛊关机程序
●引子:如何做一个关机程序来整蛊你的朋友呢?首先要了解cmd命令。
在cmd中,shutdown -s是关机,shutdown -a是取消关机。
如何在C语言中实现cmd命令呢?C语言给出了一个特定的函数system(),这是执行cmd命令的函数,它包含在<stdlib.h>头文件中。有了它,就好整了。
●思路:开始执行程序就直接执行60秒钟关机,然后输出提示:叫爸爸就给你取消关机。如果他输入的是爸爸,就取消关机,这里就需要判断字符串了。判断他输入的字符串是否等于爸爸。两个字符串,要判断他们是否相等,不能使用等号,必须使用strcmp()函数,这个函数由<string.h>头文件给出,全称string comepare,如果strcmp里面的两个字符串相同,就返回一个0。
直接上源码!#define _CRT_SECURE_NO_WARNINGS 1; #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { //60秒后关机 shutdonw -s -t 60 //取消关机 shtudown -a //system() -执行系统命令 char input[20] = { 0 };//用于存放输入的信息 system("shutdown -s -t 60");//60秒后执行关机 again://goto语句的跳转部分 printf("请注意,你的电脑在一分钟内将会关机,叫爸爸,就给你取消关机\n"); scanf("%s", input); if (strcmp(input, "爸爸") == 0)//判断两个字符串是否相等 { system("shutdown -a");//相等则取消关机 printf("\n儿子真乖"); } else goto again;//不相等则跳转到again部分,然后重新判断输入情况 return 0; }
本章完,愿你有所收获,如果再也不能见到你,也祝你早安午安,还有晚安。