C02分支语句和循环语句
本章重点学习分支语句和循环语句的使用。
分支语句
- if
- switch
循环语句
- while
- for
- do while
goto语句
C语言是一门结构化的程序设计语言
1.顺序结构
2.选择结构
3.循环结构
什么是语句?
C语言中由一个分号 ; 隔开的就是一条语句。 比如:
printf("hehe");
1+2;
注:;
为空语句
分支语句(选择结构)
if语句
那if语句的语法结构是怎么样的呢?
演示代码:
语法结构:
if(表达式)
语句;
if(表达式)
语句1;
else
语句2;
//多分支
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
演示代码:
#include <stdio.h>
//代码1
int main()
{
int age = 0;
scanf("%d", &age);
if(age<18)
{
printf("未成年\n");
}
}
//代码2
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if(age<18)
{
printf("未成年\n");
}
else
{
printf("成年\n");
}
}
//代码3
#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");
}
}
解释一下: 如果表达式的结果为真,则语句执行。
在C语言中如何表示真假?
0表示假,非0表示真。
如果条件成立,要执行多条语句,怎应该使用代码块。
#include <stdio.h>
int main()
{
if(表达式)
{
语句列表1;
}
else
{
语句列表2;
}
return 0;
}
这里的一对 { }
就是一个代码块。
悬空else
当你写了这个代码:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else
printf("haha\n");//和离他最近的if匹配
return 0;
}
结果为空白
原因:else与前文最近的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;
}
if书写形式的对比
//代码1
if (condition)
return x;
return y;
//代码2
if(condition)
{
return x;
}
else
{
return y;
}
//代码3
int num = 1;
if(num == 5)
{
printf("hehe\n");
}
//代码4
int num = 1;
if(5 == num)
{
printf("hehe\n");
}
代码2和代码4更好,逻辑更加清晰,不容易出错。
错误例子
int age = 10;
if(13 <= age <23)
printf("未成年\n");
//错误原因13 <= age表达式值为0.表达式为假,值就为0。
//13 <= age < 23实际为0 < 23,if内条件成立
改正
int age = 10;
if(13 <= age && age <23)
printf("未成年\n");
//错误原因13 <= age表达式值为0.表达式为假,值就为0。
//13 <= age < 23实际为0 < 23,if内条件成立
练习
- 判断一个数是否为奇数
- 输出1-100之间的奇数
//1.
if( n %2)
printf("n为奇数");
//2.
int a = 1;
while(a<=100)
{
if( a % 2 )
printf("%d ",a);
a++;
}
switch语句
switch语句也是一种分支语句。 常常用于多分支的情况。
比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期七
那我没写成 if...else if ...else if
的形式太复杂,那我们就得有不一样的语法形式。 这就是switch 语句。
switch(整型表达式)
{
语句项;
}
而语句项是什么呢?
//是一些case语句:
//如下:
case 整形常量表达式:
语句;
在switch语句中的 break
在switch语句中,我们没法直接实现分支,搭配break使用才能实现真正的分支。
比如:
#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;
}
//结果是什么都不输出
有时候我们的需求变了:
- 输入1-5输出的是“weekday”;
- 输入6-7输出“weekend”
所以我们的代码就应该这样实现了:
#include <stdio.h>
//switch代码演示
int main()
{
int day = 0;
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;
}
break语句的实际效果是把语句列表划分为不同的部分。
编程好习惯
在最后一个 case 语句的后面加上一条 break语句。
(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句)例如,在case7后面加case8,然而原先的case7后没有break,case7和case8的逻辑将出问题。
default子句
如果表达的值与所有的case标签的值都不匹配怎么办?
其实也没什么,结果就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在C中并不认为错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条default子句,把下面的标签
default:
写在任何一个case标签可以出现的位置。
当 switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。
但是它可以出现在语句列表的任何位置,而且语句流会像贯穿一个case标签一样贯穿default子句。
编程好习惯
在每个 switch 语句中都放一条default子句是个好习惯,甚至可以在后边再加一个 break 。
练习
#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);// m =5,n =3
return 0;
}
swtich语句中可以出现if,不能出现continue没有意义,也不知道跳到哪里去
循环语句
- while
- for
- do while
while循环
我们已经掌握了,if语句:
if(条件)
语句;
当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。
但是我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。
那我们怎么做呢? C语言中给我们引入了:while语句,可以实现循环。
//while 语法结构
while(表达式)
循环语句;
while语句执行的流程
比如我们实现:
在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ", i);
i = i+1;
}
return 0;
}
这个代码已经帮我了解了while语句的基本语法,那我们再了解一下:
while语句中的break和continue
break介绍
//break 代码实例
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)
break;
printf("%d ", i);
i = i+1;
}
return 0;
}
这里代码输出的结果是什么?
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6 7 8 9 10
1 2 3 4 6 7 8 9 10
总结: break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的break是用于永久终止循环的。
continue介绍
//continue 代码实例1
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)
continue;
printf("%d ", i);
i = i+1;
}
return 0;
}
这里代码输出的结果是什么?
1 2 3 4√(死循环)
1 2 3 4 5
1 2 3 4 5 6 7 8 9 10
1 2 3 4 6 7 8 9 10
//continue 代码实例2
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
i = i+1;
if(i == 5)
continue;
printf("%d ", i);
}
return 0;
}
这里代码输出的结果是什么?
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6 7 8 9 10
1 2 3 4 6 7 8 9 10
2 3 4 6 7 8 9 10√
总结: continue在while循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
getchar()
介绍getchar(),putchar()
//代码1
int ch = getchar();
putchar(ch);
printf("%c\n", ch);//由下图见,只接收一个字符
//代码2
int ch = getchar();
while ((ch = getchar() )!= EOF)//EOF在输入里表示ctrl+Z
{
putchar(ch);
}
//代码3
#include <stdio.h>
int main()
{
while ((ch = getchar()) != EOF)
{
if (ch < ‘0’ || ch > ‘9’)
continue;
putchar(ch);
}
return 0;
}//只打印0-9的字符
再看几个代码:
//关于getchar,可以接受一个键盘的字符
int main()
{
int ret = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s",password );//输入密码并存放到password数组中
printf("请确认(Y/N):>");
ret = getchar();
if ('Y' == ret)
{
printf("确认成功");
}
else
{
printf("放弃确认");
}
return 0;
}
此处代码有问题,调试发现ret内值为10(回车符)printf("%d", '\n');//验真输出为10
。
关于输入缓冲区
修改:在确认前加getchar();接收回车字符"\n"
缺陷,密码有空格时,getchar再次失效
再次修改,思路:接收密码用循环getchar,直到接收到回车\n停止
int main()
{
int ret = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s",password );//输入密码并存放到password数组中
while(ch = getchar() != '\n')
{
;
}
printf("请确认(Y/N):>");
ret = getchar();
if ('Y' == ret)
{
printf("确认成功");
}
else
{
printf("放弃确认");
}
return 0;
}
这样ch将不断循环接收空格以后的字符直到接收回车
for循环
我们已经知道了while循环,但是我们为什么还要一个for循环呢? 首先来看看for循环的语法:
语法
for(表达式1;表达式2;表达式3)
循环语句;
表达式1 表达式1为初始化部分,用于初始化循环变量的。 表达式2 表达式2为条件判断部分,用于判断循环时候终止。** 表达式3 表达式3为调整部分**,用于循环条件的调整。
实际的问题:
使用for循环 在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{
int i = 0;
//for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
for(i=1; i<=10; i++)
{
printf("%d ", i);
}
return 0;
}
for循环的执行流程图:
现在我们对比一下for循环和while循环。
int i = 0;
//实现相同的功能,使用while
i=1;//初始化部分
while(i<=10)//判断部分
{
printf("hehe\n");
i = i+1;//调整部分
}
//实现相同的功能,使用while
for(i=1; i<=10; i++)
{
printf("hehe\n");
}
可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。 for循环使用的频率也最高。
break和continue在for循环中
我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。 但是还是有些差异回忆上文while死循环:
//代码1
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
break;
printf("%d ",i);
}
return 0;
}//1234
//代码2
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
continue;
printf("%d ",i);
}
return 0;
}//1 2 3 4 6 7 8 9 10
for语句的循环控制变量
一些建议:
- 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
- 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0;
//前闭后开的写法
//这样写可以清晰看出循环10次
for(i=0; i<10; i++)
{}
//两边都是闭区间
for(i=0; i<=9; i++)
{}
//都是0-9
一些for循环的变种
#include <stdio.h>
int main()
{
//变种1
//死循环
for(;;)
{
printf("hehe\n");
}
//变种2
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}//两个hehe
//0 0
//1 1
//2 2
//
1.for循环的初始化,调整,判断都可以省略但是
for循环的判断部分,如果被省略,那判断条件就是:恒为正
2.如果不是非常熟练,建议不要随便省略
一道笔试题:
//请问循环要循环多少次?
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}//循环0次,k = 0语句为假
总结:赋值语句的真假取决于右值,右值不为0,表达式为真。右值为0,表达式为假。
do…while循环
do语句的语法:
do
循环语句;
while(表达式);
执行流程
do语句的特点
循环至少执行一次,使用的场景有限,所以不是经常使用。
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d\n", i);
i++;
}while(i<10);
return 0;
}
do while循环中的break和continue
#include <stdio.h>
int main()
{
int i = 1;
do
{
if(5 == i)
break;
printf("%d\n", i);
i++;
}while(i<10);
return 0;
}//1 2 3 4
#include <stdio.h>
int main()
{
int i = 1;
do
{
if(5 == i)
continue;
printf("%d\n", i);
i++;
}while(i<=10);
return 0;
}//1 2 3 4 死循环
练习
-
计算 n的阶乘。
-
计算 1!+2!+3!+……+10!
-
在一个有序数组中查找具体的某个数字n。 编写int binsearch(int x, int v[], int n); 功能:在v[0]<=v[1]<=v[2]<=
….<=v[n-1]的数组中查找x. -
编写代码,演示多个字符从两端移动,向中间汇聚。
解释题意想要的效果为如下变化 例如
###################
w#################!
we###############!!
wel#############!!!
welc###########d!!!
welco#########ld!!!
welcom#######rld!!!
welcome#####orld!!!
welcome ###world!!!
welcome t# world!!!
welcome to world!!! -
编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。
练习答案
//1.
int Factorial(int n)
{
int i = 0, mul = 1;
for (i = 1; i <= n; i++)
{
mul = mul * i;
}
return mul;
}
//2.计算1!+2!+3!+……10!
int Fac_add()
{
int Sum = 0, i = 0, j = 0, Mul = 0;
for (i = 1; i <= 10; i++)
{
Mul = 1;
for (j = 1; j <= i;j++)
{
Mul *= j;//Mul依次为1!,2!……,10!
}
Sum += Mul;
}
return Sum;
}
阶乘的和优化
//优化
int Fact_add()
{
int Sum = 0, i = 0,Mul = 1;
for (i = 1; i <= 10; i++)
{
Mul *= i;//Mul依次为1!,2!……,10!
Sum += Mul;
}
return Sum;
}
// Mul = 1*1 Sum = 0 +1
// Mul = 1*1*2 Sum = 0 + 1 + 2
// Mul = 1*1*2*3 Sum = 0 + 1 + 2 + 6
//3.基础解法
int arr[] = { 1,2,3,4,5,6,7 };
int k = 8;
//写一个代码,在arr数组(有序)中找到4
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
//顺序查找
for (i = 0; i < sz; i++)
{
if (k == arr[i])
{
printf("找到了,下标是:%d \n", i);
break;
}
}
if (i == sz)
{
printf("找不到\n");
}
有序数组查找优化,折半查找法思想
顺序查找O(n)
❤折半查找O(log2n)
例如:2^32个数字,只需查找32次
//3.折半查找
//3.
int arr[] = { 1,2,3,4,5,6 };
int k = 4;//要查找的数字
//写一个代码,在arr数组(有序)中找到4
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int pre = 0;
//折半查找
int left = 0;
int right = sz - 1;
while(left <= right)
{
pre = (left + right)/2;//折半查找的下标
if (arr[pre] == k)
{
printf("找到了,下标是 %d \n", pre);
break;
}
else if (arr[pre] > k)//说明k可能在pre位置的左边
{
right = pre-1;
}
else
{
left = pre+1;
}
}
if(left > right)
printf("没找到\n");
//4.思路,两串字符
###################
welcome to world!!!
添加Sleep函数每次打印停顿一秒
添加system(“cls”);//执行清空屏幕
细节char arr1[] = “abc”;
保存时,会自动在末尾加‘\0’
例如:
char arr[] = “abc”;
[a b c \0]
0 1 2 3
sizeof计算的长度也是4
//
char arr1[] = "welcome to world!!!";
char arr2[] = "###################";
int sz = sizeof(arr1) / sizeof(arr1[0]);
int left = 0;
int right = sz - 2;
while (left <= right)
{
printf("%s\n", arr2);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
system("cls"); //<stdlib.h>
left++;
right--;
Sleep(1000);//头文件<windows.h>
}
最终结果为动态向中间汇聚
//5.
细节
==
不能用来比较两个字符串是否相等,应该使用一个库函数-strcmp
int i = 0;
char password[20] = {0};
for( i = 0; i<3;i++)
{
printf("请输入密码;>");
scanf("%s",password):
if(strcmp(password,"123456") == 0)
{
printf("登陆成功\n");
break;
}
if (i == 3)
printf("三次密码均错误。退出程序\n");
练习参考代码:
//代码1
//编写代码,演示多个字符从两端移动,向中间汇聚
#include <stdio.h>
int main()
{
char arr1[] = "welcome to bit...";
char arr2[] = "#################";
int left = 0;
int right = strlen(arr1)-1;
printf("%s\n", arr2);
//while循环实现
while(left<=right)
{
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
left++;
right--;
printf("%s\n", arr2);
}
//for循环实现
for (left=0, right=strlen(src)-1;
left <= right;
left++, right--)
{
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf( "%s\n", target);
}
retutn 0;
}
//代码2
int main()
{
char psw[10] = "" ;
int i = 0;
int j = 0;
for (i = 0; i < 3 ; ++i)
{
printf( "please input:");
scanf("%s", psw);
if (strcmp(psw, "password" ) == 0)
break;
}
if (i == 3)
printf("exit\n");
else
printf( "log in\n");
}
折半查找算法
比如我买了一双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜?
答案:你每次猜中间数。
代码实现:
实现在主函数内:
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int left = 0;
int right = sizeof(arr)/sizeof(arr[0])-1;
int key = 7;
int mid = 0;
while(left<=right)
{
mid = (left+right)/2;
if(arr[mid]>key)
{
right = mid-1;
}
else if(arr[mid] < key)
{
left = mid+1;
}
else
break;
}
if(left <= right)
printf("找到了,下标是%d\n", mid);
else
printf("找不到\n");
}
如果实现一个二分查找函数:
int bin_search(int arr[], int left, int right, int key)
{
int mid = 0;
while(left<=right)
{
mid = (left+right)>>1;
if(arr[mid]>key)
{
right = mid-1;
}
else if(arr[mid] < key)
{
left = mid+1;
}
else
return mid;//找到了,返回下标
}
return -1;//找不到
}
猜数字游戏实现
参考代码:
❤rand函数
MSDN手册
手册使用
在MSDN上查到
rand函数返回一个范围为0到RNAD_MAX的伪随机整数,在调用rand之前,使用srand函数为伪随机数生成器播种。
RAND_MAX转到定义发现值为0x7fff
转化为十进制为32767,即函数生成的随机数范围为0-32767
srand((unsigned)time(NULL))详解
情况一:
int random = rand();
两次执行rand函数,发现生成的随机数完全一样。
情况二:参照手册,在调用rand之前,使用srand函数为伪随机数生成器播种。
//srand函数定义
void srand( unsigned int seed );
srand函数内种子为常量时,每次生成的随机数相同
srand(1);
int random = rand();
情况三:
srand函数内种子需要时刻变化,才能完成每次生成随机数不同。
使用时间戳
拿时间戳设置随机数的生成起点,在MSDN内查看time函数
发现其返回值实际为Long类型
//time函数定义
time_t time( time_t *timer );
srand((unsigned int)time(NULL));
int random = rand();
此时生成的数字不够随机,比较相近,原因在于srand函数在game函数内调用,game函数在主函数内调用多次,将srand函数调用放在主函数体内,整个工程只调用一次。
修改后,生成随机数完成
情况四:想要控制生成的随机数范围
rand()%100;//将范围控制在0-99
rand()%100+1;//将范围控制在1-100
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("**********************************\n");
printf("*********** 1.play **********\n");
printf("*********** 0.exit **********\n");
printf("**********************************\n");
}
//TDD-测试驱动开发。
//RAND_MAX--rand函数能返回随机数的最大值。
void game()
{
int random_num = rand()%100+1;
int input = 0;
while(1)
{
printf("请输入猜的数字>:");
scanf("%d", &input);
if(input > random_num)
{
printf("猜大了\n");
}
else if(input < random_num)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择>:");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("选择错误,请重新输入!\n");
break;
}
}while(input);
return 0;
}
goto语句
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,例如一次跳出两层或多层循环。
这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
下面是使用goto语句的一个例子:
一个关机程序
#include <stdio.h>
int main()
{
char input[10] = {0};
system("shutdown -s -t 60");
again:
printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
scanf("%s", input);
if(0 == strcmp(input, "我是猪"))
{
system("shutdown -a");
}
else
{
goto again;
}
return 0;
}
而如果不适用goto语句,则可以使用循环:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[10] = {0};
system("shutdown -s -t 60");
while(1)
{
printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
scanf("%s", input);
if(0 == strcmp(input, "我是猪"))
{
system("shutdown -a");
break;
}
}
return 0;
}
关于shutdown命令的扩展-(请点这里)
goto语言真正适合的场景如下:
for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
…
error:
if(disaster)
// 处理错误情况
本章完
疑问(未解决)
数组名arr本质是地址,sizeof是怎么确定数组长度的
int arr[] = { 1,2,3,4,5,6,7 };
int k = 4;
//写一个代码,在arr数组(有序)中找到4
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
回忆字符数组
"hello hehe.\n"
这种由双引号引起来的一串字符称为字符串字面值,或简称字符串。
注:字符串的结束标志是一个\0的转义字符。在计算字符串长度的时候\0是结束标志,不算做字符串内容。
char arr1[] = "hehe";
char arr2[] = { 'h', 'e', 'l', 'l', 'o'};
char arr3[] = { 'h', 'e', 'l', 'l','o', '\0' };
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
练习题
1.下面代码执行的结果是:
#include <stdio.h>
int main()
{
int i = 0;
for( i = 0;i<10;i++)
{
if(i = 5)
printf("%d",i);
}
return 0 ;
}
- 1 2 3 4 5 6 7 8 9 10
- 5 5 5 5 5 5 5 5 5 5 5
- 死循环的打印5√
- 0 1 2 3 4 5 6 7 8 9
2.关于if语句说法正确的是 - if语句后面只能跟一条语句
- if语句中0表示假,1表示真
- if语句是一种分支语句,可以实现单分支,也可以实现多分支√
- else语句总是和它的对齐的if语句匹配
1不能表示所有的真
3.关于switch说法不正确的是
- switch语句中的default子句可以放在任意位置
- switch语句中case后的表达式只能是整形常量表达式
- switch语句中的case子句必须在default子句之前√
- switch语句中case表达式不要求顺序
int func(int a)
{
int b;
switch (a)
{
case 1: b = 30;
case 2: b = 20;
case 3: b = 16;
default: b = 0;
}
return b;
}
则func(1) = {}
- 30
- 20
- 16
- 0√
5.switch(c)
语句中,c不可以是什么类型
- int
- long
- char
- float√
如果是char类型识别ascii码值即可
6.下面代码的执行结果是什么
#include <stdio.h>
int main()
{
int x = 3;
int y = 3;
switch( x%2 )
{
case 1:
switch(y)
{
case 0:
printf("first");
case 1:
printf("second");
default:
printf("hello");
}
case 2:
printf("third");
}
return 0;
}
- secondthird
- hello
- firstsecond
- hellothird√
7.从大到小输出
写代码将三个数按从大到小输出
//2.b,c比较,大的放b,小的放c,a,b比较,大的放a。排出最大的到a。再比较bc
int a = 1;
int b = 2;
int c = 3;
int tmp = 0;
if (b > c)
;
else
{
tmp = b;
b = c;
c = tmp;
}
if (a > b)
;
else
{
tmp = a;
a = b;
b = tmp;
}
if (b > c)
;
else
{
tmp = b;
b = c;
c = tmp;
}
printf("从大到小依次为%d, %d, %d \n", a, b, c);
8.打印三的倍数的数
写一个代码打印1-100之间所有3的倍数的数字
//规律:三的倍数%3 == 0
int i = 1;
while (i <= 100)
{
if (i % 3 == 0)
printf("%d ", i);
i++;
}
9.最大公约数
给定两个数,求这两个数的最大公约数
分析:用辗转相除法
大数/小数 -余数1
小数/余数1 -余数2
余数1/余数2 - 余数3
当余数为0时此时的被除数即为最大公约数
int a = 0;
int b = 0;
int tmp = 0;
printf("输入两个数,以空号隔开\n");
scanf("%d %d", &a, &b);
if (0 == a / b)
{
//说明a为小数
tmp = a;
a = b;
b = tmp;
}
while (0 != a%b)
{
tmp = a%b;
a = b;
b = tmp;
}
printf("这两个数字的最大公约数为 %d", b);
10.打印1000年到2000年之间的闰年
分析:闰年的标准:
普通闰年:公历年份是4的倍数,且不是100的倍数的,为闰年(如2004年、2020年等就是闰年)。
世纪闰年:公历年份是整百数的,必须是400的倍数才是闰年(如1900年不是闰年,2000年是闰年)。
int i = 1000;
while (i <= 2000)
{
if ((i % 4 == 0) && (i % 100 != 0))
printf(" 普通闰年,%d \n", i);
if (i % 400 == 0)
printf("世纪闰年,%d \n", i);
i++;
}
11.打印100-200之间的素数
素数:只能被1和自身整除
用试除法,即每一个数字都用2到他自身-1的数字除,观察是否有可整除的除数,有则不是素数
int i = 0;
int j = 0;
for (i = 100; i <= 200; i++)
{
for (j = 2; j < i; j++)
{
if (i%j == 0)
{
break;//说明i不是素数,无需检测,直接跳出测下一个
}
}
if (j == i)
printf(" %d ", i);
}
打印素数优化
思路:如果一个数字不是素数,一定可以表示为 i = a*b;并且a或b中一定有一个数字是<= 开平方i
换句话说例如,判断15是否为素数,只要在2-√15中找到一个数把15整除,还是试除法,不过除的少了
库函数sqrt(15)为 开平方函数,头文件<math.h>
优化1
for (j = 2; j < sqrt(i); j++)
优化2
for (j = 2; j < i/2; j++)
优化3:跳过偶数
for (i = 101; i <= 200; i+=2)
{
for (j = 2; j < i; j++)//此处可按优化1,2修改
{
12.关于while(条件表达式)循环体,以下叙述正确的是()?(假设循环体里面没有break,continue,return,goto等等语句)
- 循环体的执行次数总是比条件表达式的执行次数多一次
- 条件表达式的执行次数总是比循环体的执行次数多一次√
- 条件表达式的执行次数与玄幻提的执行次数一样
- 条件表达式的执行次数与循环体的执行次数无关
13.有以下程序
#include <stdio.h>
int main()
{
int a = 0,b = 0;
for( a = 1,b = 1;a <= 100;a++)
{
if( b >= 20) break;
if (b % 3 == 1)
{
b = b+3;
continue;
}
b = b-5;
}
printf("%d\n",a);
return 0;
}
程序的输出结果是?
- 10
- 9
- 8√
- 7
14.数9的个数
编写程序数一下1到100的所有整数中出现多少个数字9
思路:
%10取出个位的9
/10后%10取出十位的9
int i = 0;
int count = 0;
for (i = 1; i <= 100; i++)
{
if (i % 10 == 9 )
count++;//个位为9
if ((i / 10) % 10 == 9)
count++;//十位为9
}
printf("1-100中数字9的个数为 %d \n",count);
15.分数求和
计算1/1-1/2+1/3-1/4+1/5……+1/99-1/100的值,打印出结果(交错加减)
细节
1/2结果为整形0
1.0/2结果为浮点数
int main()
{
int i = 0;
double sum = 0;
int flag = 0;
for (i = 1; i <= 100; i++)
{
/*sum += flag * 1.0 / i;
flag = -flag;*/
if (i % 2 != 0)
sum += 1.0 / i;
else
sum -= 1.0 / i;
}
printf(" %lf ", sum);
return 0;
}
16.求最大值
求10个整数中最大值
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int max = arr[0];//细节,不要随便赋值0
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
printf("max = %d ", max);
return 0;
}
17.乘法口诀表
int main()
{
int i = 0 ,j = 0;
for (i = 1; i < 10; i++)
{
for (j = 1; j <= i; j++)
{
printf(" %d*%d = %d ",j,i,i*j);
}
printf("\n");
}
return 0;
}
发现三四列对不齐
使用
❤%2d
%2d 意思为打印该数字的时候,打印两位,如果不够两位,则用空格补齐。其中%2d为右对齐,%-2d为左对齐
%2d效果
%-2d效果
18.二分查找
编写代码在一个整形有序数组中查找具体的某个数
要求:找到了就打印数字所在的下标,找不到则输出:找不到
代码见上文