3种结构、3种语句
C语言是【**结构化】**的程序设计语言
顺序结构
选择结构:
(分支语句)
if、switch
循环结构:
while、for、do while
分支语句:
- if
- switch
循环语句:
- while
- for
- do while
goto语句
什么是语句
C语句可分为以下5类:
- 表达式语句,如:
3 + 5;
- 函数调用语句,如:
printf("hehe\n");
- 控制语句(此篇介绍)
- 复合语句
- 空语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句
可分为以下三类:
- 条件判断语句(分支语句):if语句、switch语句
- 循环执行语句:do while语句、while语句、for语句
- 转向语句:break语句、goto语句、continue语句、return语句
分支语句(选择结构)
if语句
语法
单分支
if (表达式)//为真执行,为假不执行
语句;
双分支
//写法1
if为 (表达式)
语句1;
else
语句2;
//写法2
if为 (表达式1)
语句1;
else if (表达式2)
语句2;
多分支
if (表达式1)
语句1;
else if (表达式2)
语句2;
else if (表达式3)
语句3;
......
else if (表达式n)
语句n;
else
语句n+1;
示例
单分支
if (age >= 18)
printf("成年\n");
双分支
//写法1
if (age >= 18)
printf("成年\n");
else
printf("未成年\n");
//写法2
if (age >= 18)
printf("成年\n");
else if (age < 18)
printf("未成年\n");
多分支
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 if (age >= 80 && age < 100)
printf("老年\n");
else
printf("老寿星\n");
注意:
if (18 <= age <30)
为错误写法,因为程序会先判断18 <= age的真假,真1假0,再判断1或0<30的真假,导致结果始终为真,无法满足预期效果- if、else、else if后面若不加代码块
{ }
只能跟一条语句**(整个if、else if、else算一条语句)**,好习惯是不论后面跟几条语句都加上{ }
- 如果全写成
if
,可以实现预期效果,但是每个if
语句都参与判断,共判断6次;而原写法判断为真之后就不再判断,所以只需判断1~5次,可以提高运行效率
悬空else
//不规范写法
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else
printf("haha\n");
//规范写法
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else
printf("haha\n");
else
与最近的if
匹配
代码风格很重要:可以通过套代码块、加空格、初始化的习惯提高代码可读性,可以阅读《高质量C++/C编程》前3章
luint a = 0;
int b = 2;
if(a == 1)
{
if(b == 2)
{
printf("hehe\n");
}
}
else
{
printf("haha\n");
}
switch语句
switch语句也是一种分支语句,常常用于多分支的情况
continue
不是用在switch
语言中的关键字,因为continue
是跳出循环,而switch
不是循环
但break
是它的关键字
比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
if
语句写法:
int day = 0;
if (1 == day)
printf("星期一\n");
else if (2 == day)
printf("星期二\n");
else if (3 == day)
printf("星期三\n");
else if (4 == day)
printf("星期四\n");
else if (5 == day)
printf("星期五\n");
else if (6 == day)
printf("星期六\n");
else if (7 == day)
printf("星期日\n");
else
printf("输入错误\n");
switch语句写法:
int day = 0;
scanf("%d", &day);
switch(day)//switch只决定入口,出口则由break决定
{
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;
default://default字句,用于处理非case场景
printf("输入错误\n");
break;
}
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("输入错误\n");
break;
}
switch`中的`default`可以放在任意位置,但一般建议放在最后,且建议加上`break
default
写不写都可以,但即使default
不作任何处理,依然建议加上default
(方便日后拓展需求)
语法
switch(整型表达式)//char可以,const修饰的常变量不行(C++中是常量,可以使用)
{
case 整型常量表达式:
语句;
}
switch语句中整形表达式的类型只能是:整型(char也属于整型表达式,因为存储的是ASCII码值)和枚举类型,浮点类型不是
case不论含有几条语句都可以选用{ }
练习
判断打印结果
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{//switch允许嵌套使用(switch套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
分支语句中的break和continue
只有break
被使用到switch
语句中,continue
不用于分支语句
循环语句
- while(常用)
- for(最常用)
- do while
按需使用
while
while (表达式)
循环语句;
解析:看表达式是否为真,为真就进入循环语句,出了循环语句再看表达式是否为真…直至表达式为假,停止循环
if (1)
printf("hehe\n");//输出hehe
while (1)
printf("hehe\n");//持续输出hehe,死循环
练习
在屏幕上打印1-10的数字
int i = 1;//初始化
while (i <= 10)//判断
{
printf("%d ", i);
i++;//调整
}
getchar
& putchar
scanf`读取成功返回`int`类型的参数个数,读取失败返回`EOF
getchar
——get char获取字符
int getchar (void);
读取正确返回int
类型的字符ASCII码值,读取失败返回EOF
(值为-1,所以返回int而不是char)——end of file,文件结束标志,放在文件末尾,CTRL+Z会让getchar/scanf返回一个EOF
putchar
——put char打印字符
int putchar (int character);
#include <stdio.h>
int main()
{
int ch = getchar();//A
printf("%c\n", ch);//A
putchar(ch);//A
putchar('\n');//换行
putchar('a');//a
}
#include <stdio.h>
int main()
{
char ch = 0;
while ((ch = getchar()) != EOF)//输入a并回车,相当于输入a\n
{
putchar(ch);//打印a,换行(先读一个,再读一个,而不是读取2个)
}
return 0;
}
输入缓冲区
#include <stdio.h>
int main()
{
char password[20] = { 0 };
printf("请输入密码\n");
scanf("%s", password);//输入123456,回车
//此时123456\n从键盘进入输入缓冲区,scanf只取\n之前的123456进入password,并把123456从缓冲区删除
printf("请确认密码[Y/N]:");
char input = 0;
scanf("%c", &input);//scanf发现输入缓冲区中有一个\n,就把\n放入input中
//换成input = getchar();和scanf一样
if ('Y' == input)
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");//未输入input就直接输出
}
return 0;
}
局限解法:11行之后加上getchar();
(仅限处理上述代码问题,适用性差,如密码为"123 abc"就会失效,因为scanf只取空格前的"123")
通用解法:清理缓冲区剩余的全部数据,11行之后加上:
while (getchar() != '\n')
{
;
}
清除缓冲区函数fflush(stdin);
不一定达到效果(“123 abc”),因为在新版本VS上功能被取消了,不建议使用
//代码1
#include <stdio.h>
int main()
{
char ch = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
return 0;
}
//作用:循环输入输出字符
//代码2
#include <stdio.h>
int main()
{
char ch = '0';
while ((ch = getchar()) != EOF)
{
if (ch < '0' || ch > '9')
continue;//if中的continue/break执行对象不是if语句,而是循环语句
putchar(ch);
}
return 0;
}
//作用:只打印数字字符,跳过其他字符
for
语法
for (表达式1; 表达式2; 表达式3)
循环语句;
表达式1:
初始化部分,用于初始化循环变量的
表达式2:
条件判断部分,用于判断循环是否终止
表达式3:
调整部分,用于循环条件的调整
**执行顺序:**表达式1→表达式2(真)→code→表达式3→表达式2(真)→code→表达式3→表达式2(真)→code→表达式3→表达式2→…→表达式3→表达式2(假)
初始化、调整部分省略意味着什么都不做,条件判断部分省略意味着恒为真,建议不要随便省略
int i = 0;
for (i = 1; i <= 10; i++)
{
printf("%d ", i);//打印1~10
}
这三个部分也可以写多个语句
for(x = 0, y = 0; x < 2 && y < 5; ++x, y++)
for语句的循环控制变量
建议:
- 尽量不要在for循环体内修改循环变量,防止for循环失去控制
2.建议for语句的循环控制变量的取值采用“前闭后开区间”写法。因为后开可以作为边界判断表示循环次数,提高代码可读性,而后闭则无意义。需要依情况而定,比如:打印100~200整数,使用i<=200比较合适
//建议,[0,10)
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ",arr[i]);
}
//不建议,[0,9]
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }
int i = 0;
for (i = 0; i <= 9; i++)
{
printf("%d ",arr[i]);
}
一道笔试题
//请问循环要循环多少次?
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)//把0赋给k,表达式结果为0,判断为假
k++;
return 0;
}//循环0次
do...while
语法
do
{
循环语句;
} while (表达式);
先执行,所以至少循环1次,执行完再判断是否进行下一次循环
举例
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}//打印1~10
循环语句中的break
和continue
break
在三个语句中作用一样,都是跳出**一层(而不是一次)**循环
continue
在while
中是跳过本次循环后续代码,直接进入判断部分;在for
中是跳过此次循环后续代码,直接进入调整部分再判断
左值、右值
int a = 10;
a = 20;//把20放到了a的空间中,使用的是a的空间:a的空间,左值
int b = a;//使用了a中存放的值,把a中的20存放到b中:a的值,右值
左值——空间,右值——空间的内容
练习
1 n的阶乘
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int n = 0;//n为阶乘数
int i = 1;//i为每一项因数
int ret = 1;//结果
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
printf("%d ", ret);
return 0;
}
注意:容易超出int
的范围,所以不要输入太大的数(即不考虑溢出)
2 1!+2!+3!+……+10!
#include <stdio.h>
int main()
{
int n = 0;
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 10; n++)
{
ret = 1;//十分重要:重置ret,防止被上一次结果干扰
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
sum = sum + ret;
}
printf("%d ", sum);
return 0;
}
缺点:代码冗余,嵌套循环,循环次数太多
改进原理:1! + 2! + 3! +…+10!=1! + 1!*2 + 2!3 +…+ 9!*10
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int m = 0;//趋近底数
int n = 0;//目标底数
int mul = 1;//乘积
int sum = 0;//和
scanf("%d", &n);
for (m = 1; m <= n; m++)
{
mul *= m;
sum += mul;
}
printf("%d\n", sum);
return 0;
}
3 二分查找(有序数组)
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };//数组升序情况
int left = 0;//左下标
int right = left + (sizeof(arr) / sizeof(arr[0]));//右下标
int mid = left + (right - left) / 2;//中下标
int score = 0;//目标数字
printf("请输入目标数字:");
scanf("%d", &score);
while (left <= right)//注意此处是<=,若为<,结果可能出错
{
if (arr[mid] < score)
{
left = mid + 1;
mid = left + (right - left) / 2;
}
else if (arr[mid] > score)
{
right = mid - 1;
mid = left + (right - left) / 2;
}
else if (arr[mid] == score)
{
printf("成功:目标数字的下标是%d\n", mid);
break;
}
}
if (left > right)
{
printf("失败:没有该数字\n");
}
return 0;
}
挖坑:递归实现二分查找
4 演示多个字符从两端移动,向中间汇聚
#include <stdio.h>
#include <string.h>
#include <windows.h>//Sleep使用
#include <stdlib.h>//system使用
#define MAX_LEN 20
int main()
{
char str1[] = "So, Nvidia, fuck u!";
char str2[MAX_LEN + 1] = "";
int len = strlen(str1);//4
int left = 0;//左下标
int right = len - 1;//右下标('\0'不计),也可以使用sizeof求
if (len <= MAX_LEN)
{
int i = 0;
for (i = 0; i < len; i++)//str2初始化
{
str2[i] = 'X';
}
for (; left <= right; left++, right--)//演示
{
printf("%s", str2);
str2[left] = str1[left];
str2[right] = str1[right];
Sleep(1000);//单位ms
system("cls");//清理屏幕
}
printf("%s", str2);
}
else
{
printf("字符串2不够长\n");
}
return 0;
}
5 模拟用户登录情景,且至多尝试三次
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>//strcmp使用
int main()
{
char str1[] = "123456";//正确密码
char str2[20] = "";//输入密码
int num = 0;//尝试次数
for (num = 0; num < 3; num++)
{
printf("请输入密码:");
scanf("%s", str2);//填入输入字符,并最后加入一个'\0',如"xxxxx"输入"a"后变为"a\0xxx"
if (strcmp(str2, str1) == 0)//次数内登录成功
//字符串间比较不能用==
//strcmp用于字符串比较,第一个字符串小于第二个:返回<0的数;第一个等于第二个(一样)返回0;第一个大于第二个返回>0的数
//字符串比大小是从第一个字符开始,比较ASCII码值的大小,出现大小不同的字符就得到结果,与后续字符的ASCII大小无关
{
printf("登录成功\n");
break;
}
else if ((strcmp(str2, str1) != 0) && num != 2)//次数内登录失败
{
printf("登录失败,请重试\n\n");
}
}
if (3 == num)//判断是否超出次数
{
printf("错了!去去去,再试就让你小子试出来了(ノ`Д)ノ\n");
}
return 0;
}
猜数字游戏
生成随机数函数——rand
int rand (void);
返回值范围[0, 32767(RAND_MAX)]
0x开头的是16进制数字,0开头的是8进制数字
调用rand函数之前需调用srand函数去设置随机数的生成体
srand函数需要一个整型
srand(200);//随便给一个200
int a = rand();
printf("%d\n", a);//固定输出691
我们为了生成一个随机数,而srand需要一个随机数,出现问题
可以给srand传进去一个一直在变的值
电脑的时间一直在变化 —— 时间戳 —— 北京时间1970年01月01日08时00分00秒起至现在的总秒数
C语言提供了一个函数 —— time,可以返回一个时间戳
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>//rand,system使用
#include <time.h>//time使用
void menu()
{
printf("*******************\n");
printf("**** 猜数字游戏 ****\n");
printf("***** 1. play *****\n");
printf("***** 0. quit *****\n");
printf("*******************\n");
}
void game()
{
system("cls");
int num1 = 0;//目标随机数
int num2 = 0;//猜测随机数
num1 = rand() % 100 + 1;
printf("请开始猜数字(1~100):");
while (1)
{
scanf("%d", &num2);
if ((num2 < num1) && ((num2 >= 1) && (num2 <= 100)))
{
printf("猜小了,请重猜\n");
}
else if ((num2 > num1) && ((num2 >= 1) && (num2 <= 100)))
{
printf("猜大了,请重猜\n");
}
else if (num2 < 1 || num2 > 100)
{
printf("超出猜测范围,请重猜\n");
}
else
{
printf("恭喜你,猜对了\n");
printf("本局游戏结束\n\n");
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL));//rand使用前,一定要调用srand,并且只调用一次srand
int input = 0;//玩不玩
while (1)
{
menu();
printf("请输入:");
scanf("%d", &input);
if (1 == input)
{
game();
}
else if (0 == input)
{
system("cls");
printf("程序结束\n");
break;
}
else
{
printf("输入错误,请重新输入\n\n");
}
}
return 0;
}
goto语句
goto是语法,不是函数,不需要头文件
C语言中提供了可以随意滥用的goto
语句和标记跳转的标号,可以往前或往后跳转
int main()
{
again://死循环打印
printf("hehe\n");
printf("ha\n");
goto again;//名字任取
return 0;
}
从理论上goto
语句是没有必要的,实践中没有goto
语句也可以很容易的写出代码,并且使用goto
语句可能导致意外的效果,所以要少用
但是某些场合下goto
语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,如:一次跳出两层或多层循环
多层循环这种情况使用break
是达不到目的的。它只能退出到上一层的循环
for ()
{
for ()
{
for ()
{
if (disaster)
{
goto error;
}
}
}
}
error:
if (disaster)
{
;//处理错误
}
goto语句不能跨函数跳转:
void test()
{
n:
printf("hehe\n");
}
int main()
{
goto n;//错误示范
return 0;
}
一个关机程序
只要程序运行起来,电脑就在1分钟内关机,如果输入:我是猪,就取消关机
shutdown -s
关机
shutdown -a
取消关机
-t
设置倒计时(单位s)
goto
实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>//system
#include <string.h>
int main()
{
char input[20] = { 0 };
system("shutdown -s -t 60");//关机指令
again:
printf("\n电脑将在1分钟后关机,请输入:我是猪,进行取消关机!\n请输入:");
scanf("%s", input);
if (0 == strcmp(input, "我是猪"))//判断
{
system("shutdown -a");
}
else
{
goto again;
}
return 0;
}
循环实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>//system
#include <string.h>
int main()
{
char input[20] = { 0 };
system("shutdown -s -t 60");//关机指令
while (1)
{
printf("\n电脑将在1分钟后关机,请输入:我是猪,进行取消关机!\n请输入:");
scanf("%s", input);
if (0 == strcmp(input, "我是猪"))//判断
{
system("shutdown -a");
break;
}
}
return 0;
}
挖坑:exe文件添加到服务上,启动类型改为自动
课后作业 1
#difine、#include都是预处理指令
多组输入时,scanf读到几个数就返回几,故可用scanf(…) == 某个数 取代scanf(…) == EOF
8 从大到小输出
将三个整数数按从大到小输出
例如:
输入:2 3 1
输出:3 2 1
#include <stdio.h>//没有给思路,自己理解
int main()
{
int a = 0;
int b = 0;
int c = 0;
scanf("%d%d%d", &a, &b, &c);
if (a < b)
{
int tmp = a;
a = b;
b = tmp;
}
if (a < c)
{
int tmp = a;
a = c;
c = tmp;
}
if (b < c)
{
int tmp = b;
b = c;
c = tmp;
}
printf("a=%d b=%d c=%d\n", a, b, c);
return 0;
}
**注意:**顺序敏感,不论几个数,应该先从a开始,与其它所有元素比较之后再从b开始…
9 打印素数
打印100~200之间的素数
素数:即质数(除了1和自己之外,再没有其他的约数)
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <math.h>//sqrt使用所需
int main()
{
int a = 0;//被除数
int n = 0;//除数
int count = 0;//统计个数
for (a = 101; a < 200; a += 2)
{
for (n = 3; n <= sqrt(a); n += 2)
{
if (a % n == 0)
{
break;
}
}
if (n > sqrt(a))
{
printf("%d ", a);
count++;
}
}
printf("\n有%d个素数\n", count);
return 0;
}
上述方法为试除法
推荐《素数求解的n种境界》,还有筛选法…
10 打印闰年
打印1000年到2000年之间的闰年
闰年:被4整除 且 不能被100整除 或 能被400整除
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int year = 0;//年份
int count = 0;//计数
for (year = 1000; year <= 2000; year++)
{
if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
{
printf("%d ", year);
count++;
}
}
printf("\n闰年有%d个\n", count);
return 0;
}
11 最大公约数
给定两个数,求这两个数的最大公约数
例如:
输入:20 40
输出:20
求解的方式比较多:暴力穷举、辗转相除法、更相减损法、Stein算法算法
此处主要介绍:辗转相除法
//最笨的办法:从较小数开始依次减一,挨个试
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
//找出较小值
int m =a > b ? b : a;
//假设m就是最大公约数
for (; m != 0; m--)
{
if (a % m == 0 && b % m == 0)
{
printf("两数最大公约数为:%d", m);
break;
}
}
return 0;
}
//辗转相除法
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int m = 0;
while(m = a % b)
{
a = b;
b = m;
}
printf("两数最大公约数为:%d", b);
return 0;
}
经验证,a、b大小不影响结果
最大公约数表示为:(a,b)
最小公倍数表示为:[a,b]
定理: (a, b) * [a, b] = a * b (a,b均为整数)
求最小公倍数思路:
- 从较大数开始依次+1,同时能把两数整除即可
课后作业 2
3 乘法口诀表
#include <stdio.h>
int main()
{
int i = 0;
//控制行数
for (i = 1; i <= 9; i++)
{
//打印每一行内容,每行有i个表达式
int j = 0;
for (j = 1; j <= i; j++)
{
printf("%d*%d=%2d ", i, j, i * j);
//%2d可以确保每列的两位数右对齐(不够两位右对齐)
//%-2d可以确保每列的两位数左对齐(不够两位左对齐)
}
printf("\n");
}
return 0;
}
4 求最大值
求10个整数中最大值
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int i = 0;
int max = 0;
for (i = 1; i <= 10; i++)
{
scanf("%d", &arr[i]);//输入10个整数
}
max = arr[0];//让max等于其中一个数
for (i = 1; i < 10; i++)
{
if (arr[i] > max)//有其它数比max大时,把更大的值赋给max
{
max = arr[i];
}
}
printf("最大值为:%d", max);
return 0;
}
5 分数求和
计算1/1 - 1/2 + 1/3 - 1/4 + 1/5 …… + 1/99 - 1/100 的值,打印出结果
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int i = 0;
int flag = 1;
double sum = 0.0;
for (i = 1; i <= 100; i++)
{
sum += flag * 1.0 / i;
flag = -flag;
}
printf("%lf", sum);
return 0;
}
6 数9的个数
编写程序数一下 1到 100 的所有整数中出现多少个数字9
#include <stdio.h>
int main()
{
int i = 0;
int count = 0;
for (i = 1; i <= 100; i++)
{
if (i % 10 == 9)//统计_9类型
count++;
if (i / 10 == 9)//统计9_类型
count++;
}
printf("%d\n", count);//99包含2个9,记作2个9,无需减1。结果有20个9
return 0;
}
7 二分查找
编写代码在一个整形有序数组中查找具体的某个数
要求:找到了就打印数字所在的下标,找不到则输出:找不到。
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int key = 3;
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;//若直接相加除2容易造成数据溢出
//40字节 / 4字节 - 1 = 最大角标
while (left <= right)//right位置有数据,必须要添加=号
{
int mid = left + (right - left) / 2;
if (arr[mid] > key)
//key小于中间位置数据,说明key可能在左半侧,需要改变右边界
{
right = mid - 1;
}
else if (arr[mid] < key)
//key大于中间位置数据,说明key可能在右半侧,需要改变左边界
left = mid + 1;
else
{
printf("找到了,下标是:%d\n", mid);
break;//此处是两条语句,必须加{}
}
}
if (left > right)
printf("找不到\n");
return 0;
}
课后作业
反向输出一个四位数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
while (num)
{
printf("%d", num % 10);
num = num / 10;
}
return 0;
}
总成绩和平均分计算
//一般写法
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
float score1 = 0;
float score2 = 0;
float score3 = 0;
scanf("%f %f %f", &score1, &score2, &score3);
float sum = score1 + score2 + score3;
float avg = sum / 3;
printf("%.2f %.2f\n", sum, avg);
return 0;
}
//可拓展性更强
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int i = 0;
float score = 0.0;
float sum = 0.0;
for (i = 0; i < 3; i++)
{
scanf("%f", &score);
sum += score;
}
printf("%.2f %.2f\n", sum, sum / 3);
return 0;
}
BC129 小乐乐计算函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int max3(int x, int y, int z)
{
int max = x;//假设x就是最大值
if (y > max)
max = y;
if (z < max)
max = z;
return max;
}
int main()
{
int a = 0;
int b = 0;
int c = 0;
scanf("%d%d%d", &a, &b, &c);
printf("%.2f", (float)(max3(a + b, b, c)) / (max3(a, b + c, c) + max3(a, b, b + c));
return 0;
}
21行使用(float)强制类型转换