1、分支和循环语句
C语言可分为以下五类语句:
1.表达式语句
2.函数调用语句
3.控制语句
4.复合语句
5.空语句
后面学的是控制语句。
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,他们由特定的语句定义符组成,C语言有九种控制语句。(C语言是【结构化】的程序设计语言)
可分为以下三类:
1.条件判断语句也叫分支语句:if语句,switch语句;
2.循环执行语句:do while语句,whlie语句,for语句;
3.转向语句:break语句,goto语句,continue语句,return语句。
2、分支语句
2.1 if
语法结构:第一种:
if(表达式)
语句;
表达式的内容为真,打印语句;为假就不打印。
#include<stdio.h>
int main()
{
if (3 == 5) //3==5为假
printf("hehe\n"); //条件为假,不打印
return 0;
}
结果:
#include<stdio.h>
int main()
{
if (3 == 3) //3==3为真
printf("hehe\n"); //条件为真,打印
return 0;
}
结果:
第二种:
if(表达式)
语句1;
else
语句2;
例子:
#include<stdio.h>
int main()
{
int age = 10;
if (age < 18)
printf("未成年\n");
else
printf("成年\n");
return 0;
}
结果:
#include<stdio.h>
int main()
{
int age = 20;
if (age < 18)
printf("未成年\n");
else
printf("成年\n");
return 0;
}
结果:
另外:如果if语句后面语句1要写多条语句,要用代码块(就是要用一个大括号括起来),不能直接跟;语句2一样。
#include<stdio.h>
int main()
{
int age = 10;
if (age < 18)
{
printf("未成年\n");
printf("不能喝酒\n");
}
else
printf("成年\n");
return 0;
}
结果:
第三种:多分支
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
例子:
#include<stdio.h>
int main()
{
int age = 10;
if (age < 18)
printf("青少年\n");
else if (age >= 18 && age < 28)//不能写成18<=age<28
printf("青年\n");
else if (age >= 28 && age < 40)
printf("中年\n");
else if (age >= 40 && age < 60)
printf("壮年\n");
else if (age >= 60 && age <= 100)
printf("老年\n");
else
printf("老寿星\n");
return 0;
}
结果:
注:这么多分支只会执行一条语句
在C语言中,0表示假,非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;
}
结果:
因为else是和离他最近的if匹配,所以,此时else语句匹配的是if(b==2)这条语句。
如果直接把上面这串代码复制到vs(我使用的编译器)里面,就是这样的。
单如果改成这样,就可以运行出结果,跟第一个if匹配
#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;
}
结果:
代码风格
1、变量的命名(有意义,规范)
2、空格,空行,换行
注:当一个常量和一个变量比较的时候,最好把常量放在左边
#include<stdio.h>
int main()
{
int num = 3;
if (5 == num)//这样如果少了一个等于号,也不会运行下去,会报错拦截下来
//但如果写成if(num==5),这样就算少了一个"=",也不会报错,但会导致一些bug出现
printf("hehe\n");
return 0;
}
练习
1、判断一个数是否为奇数;
2、输出1-100之间的奇数;
2.2 switch
switch语句也是一种分支语句,常用于多分支的情况。
比如:
输入1,输出星期一;输入2,输出星期二;输入3,输出星期三;输入4,输出星期四;
输入5,输出星期五;输入6,输出星期六;输入7,输出星期日;
如果写成if...else if ... else if 的形式太复杂了,用switch语句更简单。
语法介绍:
switch(整型表达式)
{
语句项;
}
整型表达式:表达式的结果是整型
语句项:是一些case语句,如下:
case 整型常量表达式:
语句;
整型常量表达式:这里可以是字符,字符本质上也是个整型,因为字符存储的时候存的是它的ASCII码值,它也是整数。
例子:
#include<stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一\n");
case 2:
printf("星期二\n");
case 3:
printf("星期三\n");
case 4:
printf("星期四\n");
case 5:
printf("星期五\n");
case 6:
printf("星期六\n");
case 7:
printf("星期日\n");
}
return 0;
}
结果:
case只是决定了入口,从case 3:这里进来,但是没告诉他从哪里出去,所以后面的都打印出来了。
switch首先根据后面的整型表达式的值,决定他匹配哪个case语句,就从哪个case语句进去,进去之后,那这个switch语句从哪里跳出去呢,这个地方就有一个专门的跳转语句,叫break。如果星期三这执行完之后不想让他往下走,就给一个break。
#include<stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一\n");
case 2:
printf("星期二\n");
case 3:
printf("星期三\n");
break;//中断,停止的意思
case 4:
printf("星期四\n");
case 5:
printf("星期五\n");
case 6:
printf("星期六\n");
case 7:
printf("星期日\n");
}
return 0;
}
结果:
但如果是输入4,就又不会停下来
如果想停下来,就在每个case语句后面都加break。
#include<stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
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;
}
有时需求变了:
1、输入1-5,输出的是"weekday";
2、输入6-7,输出的是"weekend"
#include<stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("weekday\n");
break;
case 2:
printf("weekday\n");
break;
case 3:
printf("weekday\n");
break;
case 4:
printf("weekday\n");
break;
case 5:
printf("weekday\n");
break;
case 6:
printf("weekend\n");
break;
case 7:
printf("weekend\n");
break;
}
return 0;
}
这样也行,但这种写法有点啰嗦,可以改成下面这样:
#include<stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
}
return 0;
}
结果:
说明:
1、case后面可以不加break,如果逻辑需要时,可以不加break
2、没有break的时候会持续往下走,这样就可以实现多个case匹配同一个执行语句的效果
编程好习惯:
在最后一个case语句的后面加上一条break语句。
(之所以这么写是可以避免出现在以前的最后一个case语句后面忘了添加break语句)
default字句
万一有人输入错了,不是1-7之间的数字,最好提示一下,
#include<stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
default:
printf("选择错误\n");
break;
}
return 0;
}
结果:
练习:
3、循环语句
3.1 while
while语法结构:
while(表达式)
循环语句;
表达式为真,执行循环语句,再执行while语句,表达式为真,执行循环语句...表达式为假,推出while语句,注意,如果表达式一直真,此时while语句就是一个死循环。
执行流程图
打印1-10数字
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i++;
}
return 0;
}
结果:
遇到break
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
break;
printf("%d ", i);
i++;
}
return 0;
}
结果:
break终止整个循环,作用于while循环,不在if语句起作用
遇到continue
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
continue;
printf("%d ", i);
i++;
}
return 0;
}
结果:
后面光标一直在动,死循环了
分析:
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)//当i=5为真时,执行这条语句,
continue;//执行这条语句,会直接跳过本次循环continue后面的代码,此时i=5,
//再进入while循环,又是if语句为真,又是一样,一直死循环
printf("%d ", i);
i++;
}
return 0;
}
再改一下:
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
i++;
if (5 == i)
continue;
printf("%d ", i);
}
return 0;
}
结果:
进入while循环就执行了i++;此时i=2,打印2,后面类推,
不过视频应该更清晰,我有发布,下面是链接
这个怎么打开监视界面我之前有发过,我后面再重新单独发一次
总结:
while循环中的
break是用于永久的终止循环
continue是跳过本次循环后面的代码,直接去判断部分,进行下一次循环的判断
3.2 另加:(具体getchar知识点)
再看几个代码
代码1
补充知识点:getchar和putchar
#include<stdio.h>
int main()
{
int ch = getchar();//getchar():get叫获取,char叫字符,可以获取一个字符
//就是getchar()能获取一个字符,把获取的字符的ASCII码值放到这个ch里面
printf("%c\n", ch);//然后我们就能把ch里面放的值以字符的形式打印出来,方法1
putchar(ch);//getchar叫获取,putchar叫打印,这个跟printf("%c\n", ch)都可以,方法2
return 0;
}
结果:
getchar获取一个字符,从键盘上获取,就是运行之后输入一个字符
getchar和putchar的头文件就是stdio.h
getchar返回的时候如果读取正常,就返回他读到的字符,但如果遇到文件错误或end-of-file(文件的末尾),就返回EOF(文件结束标志),那他本质上什么呢
-1是个整数,那去接收他返回的时候,最好用个整型来接收,如果用char来接收,char是字符类型,字符类型是1个字节,他是放不下一个-1这样一个整数的,所以这里写了个int,既可以放正常读取的ASCII码值,也可以放这个EOF更合适一些
接下来正文:
#include<stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF) //如果这个(ch = getchar())不等EOF,说明这个getchar读取到了正常的字符
putchar(ch);
return 0;
}
结果:
这个为什么会自动换行,我输入了一个a,其实还敲了一个回车,此时输入缓冲区里面有两个字符, 【a \n】两个
当getchar()去获取字符的时候,不是直接在键盘上就读了一个字符,中间还有个缓冲区
当输入a之后,一按回车,这个时候其实就触发了getchar去读,因为我已经把这个放到缓冲区了。
getchar先读一个字符,读到了a,他一次只能读一个字符,一个字符放到ch里面,ch就是a,这个地方a不等与EOF,这个时候就进到了putchar这里,就把a打印,a打印完之后,getchar又读取了一个字符\n,\n是换行,这时候ch就是\n,不等于EOF,这个时候又进到了putchar这里,打印了一个换行,就到下一行来了。
他打印完a之后,这个光标直接就来到了下一行,其实就是因为他打印了一个换行,这个时候打印一个s,这个光标又直接就来到了下一行。(再看具体一点就调试打开监视界面)
停下来就按ctrl+z (就是让get返回一个EOF)
这里的代码适当的修改是可以用来处理缓存区的。
这个有什么用呢,下面举个例子
#include<stdio.h>
int main()
{
//假设密码是一个字符串
char password[20] = { 0 };//给20个字符的一个空间
printf("请输入密码:>");
scanf("%s", password);//因为这个password是个数组名,本来就是个地址,所以这里没有&
//
printf("请确认密码(Y/N):>");
int ret = getchar();
if ('Y' == ret)
{
printf("Yes\n");
}
else
printf("No\n");
return 0;
}
结果:
解析:
但是这个scanf只会拿他该拿的,不会拿这个\n,因为这不是密码,这个时候scanf只是拿走了这个abced,把这个拿走之后放到了password里面,然后接着运行到了getchar,然后这个getchar一看,这缓冲区里面有东西,有个\n,他就拿走了,他看到这个缓冲区里面有东西,他压根没等,直接把\n拿走,拿走之后,他把\n拿走放到 ret 里面去了,因为ret里面是\n,他不等于Y,所以就走了else,打印 No
那这个时候我就希望这个getchar可以停下来(就是让getchar到这个缓冲区里面去看的时候什么都没有,这个时候就会等待了,就是要想办法把这个缓冲区里面的\n去掉)
#include<stdio.h>
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
getchar();//这个getchar就读取了\n,这个缓冲区里面就没有东西了
printf("请确认密码(Y/N):>");
int ret = getchar();
if ('Y' == ret)
{
printf("Yes\n");
}
else
printf("No\n");
return 0;
}
结果:
但这个写法也只是临时凑活一下,下面这样输入就又是错误了
分析:
这个scanf读到空格就不读了,所以scanf读的时候只读了abcdef,然后紧接着过来了getchar(),发现这个缓冲区里面的东西很多,有:[空格] asdfg \n ,但他只拿走了这个[空格],,此时缓冲区里面还有:asdfg \n 。他拿了这个空格之后再一次往下走,那这个getchar发现里面还有这么多,读取了这个asdfg,还是没有等键盘输入,直接就是读取了字符,走了else语句,输出No
所以用getchar();清理缓冲区的时候可能不是一个字符,而是一堆字符
#include<stdio.h>
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
int ch = 0;
while ((ch = getchar()) != '\n')//这个时候读的字符不是\n,就继续读,注意,读一个缓冲区少一个,读一个,缓冲区少一个
//直到getchar读的是\n,把\n也拿走了,放到这个ch里面,\n不等于\n为假,
//说明现在把\n,包括他之前的字符全部清理掉了,此时就可以正常了
{
;
}
printf("请确认密码(Y/N):>");
int ret = getchar();
if ('Y' == ret)
{
printf("Yes\n");
}
else
printf("No\n");
return 0;
}
结果:
当然密码可以有空格
代码2
#include<stdio.h>
int main()
{
char ch = '0';
while ((ch = getchar()) != EOF)
{
if (ch < '0' || ch>'9')
continue;
putchar(ch);
}
//只打印数字字符
return 0;
}
结果:
只打印数字字符
3.3 for
for循环语法
for (表达式1;表达式2;表达式3)
循环语句;
表达式1为初始化部分,用于初始化循环变量的
表达式2为条件判断部分,用于判断循环是否终止
表达式3为调整部分,用于循环条件的调整
执行流程
打印1-10
#include<stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)//这里循环语句只有一条,不用大括号,如果不止一条,就要大括号
printf("%d ", i);
return 0;
}
结果:
遇到break
#include<stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
结果:
当 i 等于5时,遇到break,直接终止了循环,循环不再继续
遇到continue
#include<stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
结果:
continue跳过本次循环代码continue后面的 printf("%d ", i);到for循环的调整部分,i++,这里
注:break只能结束一层循环,只能结束他所在的那个for循环或while循环
一些for循环的变种:
代码1
#include<stdio.h>
int main()
{
//for循环的判断部分省略意味着判断会恒成立,导致代码死循环
for (;;)
{
printf("hehe\n");
}
//for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题
return 0; //结果死循环了
}
结果:
建议:不要随便省略
#include<stdio.h>
int main()
{
for (int i = 0; i < 10; i++)
{
printf("hehe\n");
}
return 0;
}
for (int i = 0; i < 10; i++)中这个 int i = 0,C99语法才支持了这种写法,但如果用某个编译器不支持这个C99语法,这串代码是编不过去的。
另,C++中支持这种写法
代码2
#include<stdio.h>
int main()
{
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j< 3; j++)
{
printf("hehe\n");
}
}
return 0;
}
结果:
代码3
#include<stdio.h>
int main()
{
int i = 0;
int j = 0;
for (; i < 3; i++)
{
for (; j< 3; j++)
{
printf("hehe\n");
}
}
return 0;
}
结果:
分析:
因为当第一次执行循环 for (; i < 3; i++) ,此时 i=0 ,进入循环语句也就是下一条循环语句for ( ; j< 3; j++) ,打印出三次 hehe,这条循环语句执行完成,此时 i=0,j=3 ,然后第二次执行这个语句 for ( ; i < 3; i++) 中的 i++ ,得到 i=1,再次判断 i<3 ,进入 for ( ; j< 3; j++) ,但是因为这里没有初始化(即 j=0 ),所以此时 j 还是等于3,与 j<3 判断不符合,无法执行打印 hehe,第三次与第二次一样的原因。
代码4
使用多于一个变量控制循环
#include<stdio.h>
int main()
{
int x, y;
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
结果:
练习:
请问循环要循环几次
#include<stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
k++;
return 0;
}
3.4 do...while
3.4.1 do语句的语法:
do
循环语句;
while(表达式);
循环语句不止一条时也要加大括号括起来
特点:
循环至少要执行一次,使用场景有限,不是经常使用
3.4.2 执行流程
例子:
#include<stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
}
while (i <= 10);
return 0;
}
结果:
3.4.3 遇到break
#include<stdio.h>
int main()
{
int i = 1;
do
{
if (i == 5)
break;
printf("%d ", i);
i++;
}
while (i <= 10);
return 0;
}
结果:
3.4.4 遇到continue
#include<stdio.h>
int main()
{
int i = 1;
do
{
i++;
if (i == 5)
continue;
printf("%d ", i);
}
while (i <= 10);
return 0;
}
结果:
continue跳过后面语句 printf("%d ", i); ,还是要来到 while (i <= 10); 判断
把 i++放后面
#include<stdio.h>
int main()
{
int i = 1;
do
{
if (i == 5)
continue;
printf("%d ", i);
i++;
}
while (i <= 10);
return 0;
}
结果: 打印出 1 2 3 4 之后死循环了
因为当 i 到等于 5 时,跳过本次循环后面的代码 printf("%d ", i); i++; ,导致后面 i一直没有变化,while判断一直符合,最后死循环。
3.5 练习
写代码:
办法(编程思维)+写代码(按照语法形式去写)
1、计算n的阶乘
2、计算 1!+2!+3!......+10!
3、在一个有序数组中查找具体的某个数字n (讲解二分查找法)
4、编写代码,演示多个字符从两端移动,向中间汇聚。
5、编写代码实现,模拟用户登录情景,并且只能登陆三次。(只允许输入三次密码,如果密码正确则提示登陆成功,如果三次均输入失败,则退出程序)
3.6 goto语句
C语言中提供了可以滥用的goto语句和标记跳转的标号。
从理论上来讲goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是在某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
多层循环这种情况下是达不到目的的,它只能从最内层循环退出到上一层的循环。
goto那就是到哪里去,他有一个跳转的功能,goto语句的执行,会打乱我程序原本有的这个执行流程,容易让代码出现问题。
#include<stdio.h>
int main()
{
again:
printf("hehe\n");
printf("haha\n");
goto again;//跳到前面那个again那里去了,导致hehe和haha一直循环打印
return 0;
}
结果:
goto语句不能跨函数使用
就是没有看到again这个符号,不能跨函数跳转
goto语句真正适合的场景如下:
for(...)
for(...)
{
for(...)
{
if(disaster)//如果灾难发生
goto error;
}
}
...
error:
if(disaster)
//处理错误情况
写一个goto语句的代码,再改造成其他方法
//关机程序
//1、电脑运行起来后,1分钟内关机
//2、如果输入:easy,就取消关机
#include<stdio.h>
#include<string.h>
int main()
{
system("shutdown -s -t 60"); // -s是关机,-t是设计关机,60是表示60秒之后关机。
//这个shutdown -s -t 60就是系统命令,system函数执行系统命令。
// (系统命令就是按win+r输入cmd之后打开的运行框里面输入的指令)
again:
printf("请注意,你的电脑在60秒内关机,如果输入:easy,就取消关机\n");
char input[20] = { 0 };
scanf("%s", input);
if (strcmp(input, "easy") == 0) //strcmp要加头文件string.h
{
system("shutdown -a");// -a 取消关机
}
else
{
goto again;
}
return 0;
}
提示:别输错关机了!!
#include<stdio.h>
#include<string.h>
int main()
{
system("shutdown -s -t 60");
while (1)
{
printf("请注意,你的电脑在60秒内关机,如果输入:easy,就取消关机\n");
char input[20] = { 0 };
scanf("%s", input);
if (strcmp(input, "easy") == 0)
{
system("shutdown -a");
break;
}
}
return 0;
}
4、练习答案
2.1 1、练习
判断一个数是否为奇数;
#include<stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
//判断 奇数,除2余1就叫奇数
if (num % 2 == 1)
printf("奇数\n");
else
printf("不是奇数");
return 0;
}
2.1 2、练习
输出1-100之间的奇数;
要输出1-100之间的奇数,首先要产生1-100之间的数,再判断这个数是否为奇数,是奇数打印,不是奇数就不打印。
利用while循环的循环变量就可以产生1-100之间的数,然后每产生的循环变量,就判断他是不是奇数。
//要输出1-100之间的奇数,首先要产生1-100之间的数,
//再判断这个数是否为奇数,是奇数打印,不是奇数就不打印
#include<stdio.h>
int main()
{
//利用while循环的循环变量就可以产生1-100之间的数,然后每产生的循环变量,就判断他是不是奇数
int i=1;
while (i <= 100)
{
if (i % 2 == 1)
printf("%d ", i);
i++;
}
return 0;
}
结果:
或者这样:
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 100)
{
printf("%d ", i);
i+=2; //此时直接就知道i=1是奇数,所以直接加2也都是奇数,没有用到判断,结果一样
}
return 0;
}
2.2 练习
解析:
#include<stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:m++; //n=1匹配进入,此时m=3,且这条语句后没有加break语句,会接着执行后面的case语句
case 2:n++; // 此时n=2,这条也没有break语句,也会接着执行后面的case语句
case 3:
switch (n) //n=2
{//switch允许嵌套使用
case 1:n++;
case 2:m++; n++;//匹配到这条,此时m=4,n=3
break;//只会中断这个小的嵌套的switch语句
}//整个case 3没有break语句,接着执行后面的case语句
case 4:
m++; //接着前面的执行,此时m=5
break;//有break,中断switch语句
default:
break;//这条不会执行到,因为执行case 4语句,这条语句有break,直接中断了这个switch语句
}
printf("m=%d,n=%d\n", m, n);//最后输出m=5,n=3
return 0;
}
3.3 练习
零次,因为 for (i = 0, k = 0; k = 0; i++, k++)中的标红字体(;k = 0;),是赋值,不是判断,k 一但赋值为 0 ,0为假,这个表达式(标红字体)为假,就不进入循环了,循环0次。
3.5 练习
1、计算n的阶乘
//计算n的阶乘
//1*2*3*...*n
//要产生1到n个数字,用循环产生,把这些数字累计乘在一个数上
#include<stdio.h>
int main()
{
int i = 1;
int n = 0;//n是随便输入的一个值
int ret = 1; //暂时不考虑溢出的问题
scanf("%d", &n);
for (i = 1; i<= n; i++)
{
ret = ret * i;
}
printf("%d\n", ret);
return 0;
}
结果:
溢出结果:(暂时不考虑溢出问题)
2、计算 1!+2!+3!......+10!
#include<stdio.h>
int main()
{
int n = 1; // 1 2 3 4。。。10这几个阶乘
int i = 1; //用来做阶乘的递增的
int ret = 1;//接收阶乘的值
int sum = 0;//将每一个阶乘值相加
for (n = 1; n <= 10; n++)
{
ret = 1;
for (i = 1; i <= n; i++)//这里n=1,就是求1的阶乘,n等于几就是求几的阶乘
{
ret = ret * i;
}
sum = sum + ret;
}
printf("%d\n", sum);
return 0;
}
结果: 4037913
或者这样效率更高
#include<stdio.h>
int main()
{
int n = 1;
int ret = 1;//接收阶乘的计算得到的结果
int sum = 0;//将每一个阶乘值相加
for (n = 1; n <= 10; n++)
{
ret = ret * n; //等式右边的ret就是上一次阶乘的结果,这里就没有重复计算,
//没次都把上一次的值利用起来了
sum = sum + ret;
}
printf("%d\n", sum);
return 0;
}
3、在一个有序数组中查找具体的某个数字n (讲解二分查找法)
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//找7 在一个有序数组中查找具体的某个数字n
int k = 7;
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//用整个数组的大小除以第一个元素大小就是元素个数
for (i = 0; i < sz; i++)
{
if (arr[i] == k)
{
printf("找到了,下标是:%d", i);
break;
}
}
if (i == sz)
{
printf("找不到\n");
}
return 0;
}
但这个效率是比较慢的,没有利用到这个 有序
用二分查找(折半查找)更快
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//找7 在一个有序数组中查找具体的某个数字n
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
while (left<=right) //当left>right时,说明没有元素可以被查找了
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到了,下标是:%d\n", mid);
break;
}
}
if (left > right)
{
printf("找不到\n");
}
return 0;
}
这个时间复杂度是 。
4、编写代码,演示多个字符从两端移动,向中间汇聚。
//要打印这个welcome to home!!!
//##################
//w################!
//we##############!!
//wel############!!!
//......
//welcome to home!!!
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
int main()
{
char arr1[] = "welcome to home!!!";//这个数组里面最后还有个\n,所以是19个
char arr2[] = "##################";
int left = 0;//第一个元素下标
int right = strlen(arr1)-1;//求到了这个arr1里面字符串的长度(不包括\n),注,空格也是字符
//最后一个元素的下标
//另一种方法:int right=sizeof(arr1)/sizeof(arr1[0])-2;
//这个sizeof(arr1)/sizeof(arr1[0])算的是元素个数,包含\n在内,所以后面要-2
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s \n", arr2);
Sleep(1000); //1000毫秒,1秒,这里休息一秒 这里头文件要加windows.h
//清空屏幕
system("cls");//system是个库函数,是用来执行系统命令的,
//这个cls就是系统命令,要包含头文件stdlib.h
left++;
right--;
}
printf("%s \n", arr2);
return 0;
}
5、编写代码实现,模拟用户登录情景,并且只能登陆三次。(只允许输入三次密码,如果密码正确则提示登陆成功,如果三次均输入失败,则退出程序)
#include<stdio.h>
#include<string.h>
//比较两个字符串是否相等,不能使用 == ,而应该使用一个库函数:strcmp,头文件是string.h
//这个strcmp函数的返回值如果等于零,就说明这两个字符串相等
int main()
{
int i = 0;
char password[] = { 0 };
//假设密码是字符串abcdef
for (i = 0; i < 3; i++)
{
printf("请输入密码:>");
scanf("%s", password);//数组名本来就是地址,不需要加&
if (strcmp(password,"abcdef")==0) //比较两个字符串是否相等,不能使用==,
//而应该使用一个库函数:strcmp,这个strcmp函数的返回值如果等于零,就说明这两个字符串相等
{
printf("登陆成功\n");
break;
}
else
{
printf("密码错误\n");
}
}
if (i == 3)
{
printf("三次密码均输入错误,退出程序\n");
}
return 0;
}