[C学习]-分支和循环语句

结构:顺序结构、循环结构、分支节后
分支语句 if switch
循环语句 while for do while
goto 语句

1.什么是语句

C 语句可分为以下五类:
  • 1. 表达式语句
  • 2. 函数调用语句
  • 3. 控制语句
  • 4. 复合语句
  • 5. 空语句
本章后面介绍的是控制语句。
控制语句 用于控制程序的执行流程,以实现程序的各种结构方式
C 语言支持三种结构:(顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C 语言有九种控制语句。
可分成以下三类:
  • 1. 条件判断语句也叫分支语句:if语句、switch语句;
  • 2. 循环执行语句:do while语句、while语句、for语句;
  • 3. 转向语句:break语句、goto语句、continue语句、return语句。

2.分支语句(选择结构)

2.1 IF语句

2.1.1语法结构

单分支

多分支

if ( 表达式 1 )
    语句 1 ;
else if ( 表达式 2 )
    语句 2 ;
else
    语句 3 ;

用else if  比只用if效率更高,前者满足第一个条件后,后面就不判断了,后者即使满足了后面也会判断,效率比较低。

if、else语句默认后面只控制一条语句,如果需要执行多条语句,应该使用代码块,即加上{  }。
 

#include <stdio.h>
int main ()
{
    if ( 表达式 )
  {
        语句列表 1
  }
    else
  {
        语句列表 2
  }
    return 0 ;
}

2.1.2悬空else

else 的匹配 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;
}

代码风格要好,该空行空行,该空格空格,该对齐对齐。

2.1.3 if书写形式的对比

代码1、代码2都是一样的,尽量写成代码2的形式。return之后后面就不执行了

//代码1
if (condition) {
    return x;
}
return y;
//代码2
if(condition)
{
    return x;
}
else
{ 
return y;
}

判断两个值是否相等的时候(==)
a 两个都用数字
b 一字母一常量,常量写在左边。

int main()
{
	int n = 5;
	if (5 == n) //避免出现漏掉一个=的错误,如出现编译器会自动发现
		printf("hehe\n");

	return 0;
}

2.1.4练习  

        1. 判断一个数是否为奇数
        2. 输出 1-100 之间的奇数
1.
include<stdio.h>
int main 
{
    int n = 0;
    scanf("%d", &a);
    if (a%2==1)
    {
        printf("是奇数\n");
    }
    else
    {
        printf("不是奇数\n");
    }
    return 0;
}

2

int main()
{
	int i = 1;
	while (i <= 100)
	{
		//判断i是奇数的话,就打印i
		if(i % 2 == 1)
			printf("%d ", i);
		++i;
	}
	return 0;
}

2.2 Switch语句

写成 if...else if ...else if 的形式太复杂,就得有不一样的语法形式。
switch(整型表达式)
{
   语句项;
}
这就是 switch 语句。
语句项 是什么呢?
// 是一些 case 语句:
// 如下:
case 整形常量表达式 :
    语句 ;

2.2.1 switch中的break

#include <stdio.h>
int main()
{
    int day = 0; //const在c++是修饰常量,在c语言修饰变量
    switch(day)//day是整形int
   {
        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>
//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;
        default:
            printf("输入错误\n");//不符合情况的时候
//switch语句中的default没有顺序,default放哪一行都可以
   }
    return 0;
}

2.2.2 default语句

如果表达的值与所有的 case 标签的值都不匹配怎么办?
其实也没什么,结构就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在 C 中并不认为是个错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条 default 子句,把下面的标签
default
写在任何一个 case 标签可以出现的位置。
switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个 switch 语句中只能出现一条 default 子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个 case 标签一样执行 default 子句。
编程好习惯
在每个 switch 语句中都放一条 default 子句是个好习惯,甚至可以在后边再加一个 break

2.2.3 练习

switch支持嵌套使用
break只会跳出一层switch语句

3.循环语句

  • while
  • for
  • do while 

3.1 while

3.1.1 while中breakcontinue

int main()
{
	int n = 1;
	while (n <= 10)
	{
		n++;
		if (n == 5)
			continue;//跳过本次循环continue后边的代码,直接去while循环的判断部分
		printf("%d ", n);
	}
	return 0;

//输出结果:1 2 3 4;且一直在循环,代码一直在运行,进入死循环

breakwhile循环中的作用:
其实在循环中只要遇到 break ,就停止后期的所有的循环,直接终止循环。
所以: while 中的 break 是用于 永久 终止循环的。
continuewhile循环中的作用就是:
continue 是用于终止本次循环的,也就是本次循环中 continue 后边的代码不会再执行,
而是直接跳转到 while 语句的判断部分。进行下一次循环的入口判断

3.1.2 while中的getchar、putchar【有点乱,视频1的末尾】

getchar:从键盘中获取字符,读取阿斯克码值,返回值类型是int
为什么getchar()读取的是一个字符而返回的却是整形呢,因为字符在存储时是以阿斯克码值存储的,返回整形是返回了他的阿斯克码值
当getchar()读取错误的时候会返回EOF,EOF的含义就是end of file,是文件的结束标志,是-1

C语言中getchar()函数的详解_getchar()的功能-CSDN博客

// //EOF - end of file 文件结束标志

// //#define EOF (-1)

// //在函数读取失败的时候返回了EOF

// //scanf 函数读取成功,返回的是读取到的数据的个数

// //读取失败返回EOF

// //getchar 读取成功返回字符的ASCII码值

// //读取失败返回EOF

// //ctrl+Z - 回让scanf 或者 getchar 返回EOF

#include <stdio.h>
int main()
{
int 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 ;
    putchar ( ch );
}
return 0 ;
}
// 这个代码的作用是:只打印数字字符,跳过其他字符的、 
scanf只能读到空格前

3.2 for循环

 for(初始化:表达式1;判断:表达式2;调整:表达式3)
        printf()  

for只执行下面的一个语句,如果需要执行多条,要用{语句组}

3.2.1 for中的break和continue

break

#include <stdio.h>
int main()
{
 int i = 0;
 for(i=1; i<=10; i++)
 {
 if(i == 5)
 break;
 printf("%d ",i);
 }
 return 0;
}

//打印:1 2 3 4 
//break终止了
#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
//没有死循环,调整语句在循环体外

3.2.2for语句的循环控制变量

建议:
1. 不可在 for 循环体内修改循环变量,防止 for 循环失去控制。
2. 建议 for 语句的循环控制变量的取值采用 前闭后开区间 写法。 【用<10,非<=9,因为刚好循环10次】
1.在循环体内修改:
int main()
{
	int  i = 0;
	for (i = 1; i <= 10; i++)
	{ 
		if (i == 5)
			continue;
		printf("%d ", i);	
        i=5;
	}

	return 0;
}

//打印:6 6 6 6 6 6 ……(死循环)

3.2.4 for循环的变种

1.for(;;)
{}

初始化和调整部分省略就是啥都不做。
判断部分省略,意味着判断恒为正,无限循环。

2.打印几次“hehe”?——

int main()
{
    int i = 0;
    int j = 0;
    //这里打印多少个hehe?
    for(i=0; i<4; i++)
   {
        for(j=0; j<4; j++)
       {
         printf("hehe\n");
       }
   }
}

//打印16次hehe

省略初始化

int main()
{
int i = 0;
    int j = 0;
    //如果省略掉初始化部分,这里打印多少个hehe?
    for(; i<4; i++)
   {
        for(; j<4; j++)
       {
 printf("hehe\n");
       }
   }
}
//打印4次,i=0时执行后,j=4.后面的for不再执行

3.使用多余一个变量控制for循环

 int x, y;
    for (x = 0, y = 0; x<2 && y<5; ++x, y++)
   {
        printf("hehe\n");
   }
 return 0;

4一道笔试题目:赋值表达式中

a=b=4相当于a=(b=4),b=4中把4赋值给b后,这个表达式的值就是4,然后再赋值给a

//请问循环要循环多少次?
#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,循环不会进去

3.3 do while ()循环

(变量的左值和右值,左值指的是空间,右值是空间的内容)

do(一上来先执行一次循环语句)while(再判断);不常用

#include <stdio.h>
//打印1-10
int main()
{
 int i = 1;
 do
 {
//if (i==5)
//    break/continue
//最后都是只打印 1 2 3 4 (continue变成死循环,不断判断)
 printf("%d ", i);
        i=i+1;
 }while(i<=10);
 return 0;
}

3.4练习

1. 计算 n 的阶乘。
2. 计算 1!+2!+3!+……+10!
3. 在一个有序数组中查找具体的某个数字 n 。(讲解二分查找)
4. 编写代码,演示多个字符从两端移动,向中间汇聚。
5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则 提示登录成,如果三次均输入错误,则退出程序。

2.1

int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;
	int sum = 0;
	//1!+2!+3! = 1 + 2 + 6 = 9
	//1!
	//2! = 1*2
	//3! = 1*2*3
	//4! = 1*2*3*4
	for (n = 1; n <= 3; n++)
	{
		ret = 1;//这个很容易漏!
		for (i = 1; i <= n; i++)
		{
			ret = ret * i;
		}
		sum += ret;
	}

	printf("%d\n", sum);

	return 0;
}

2.2简便一点

int main()
{
	int n = 0;
	int ret = 1;
	int sum = 0;

	for (n = 1; n <= 3; n++)
	{
		ret = ret * n;
		sum += ret;
	}

	printf("%d\n", sum);

	return 0;
}

3

(1)

//在一个有序数组中查找具体的某个数字n

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//升序
	int k = 17;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		if (arr[i] == k)
		{
			printf("找到了,下标是:%d\n", i);
			break;
		}
	}
	if (i == 10)
	{
		printf("找不到了\n");
	}
	return 0;
}
//但是这里浪费了有序这个条件
//所以要用折半(二分)查找算法

(2)折半查找算法[仅限于有序的数组]

1.确定被查找范围的左右下标left、right
2.根据left、right,确定中间元素的下标mid
3.根据mid锁定的元素,和查找的元素比较,确定新的查找范围,left、right。

int main()
{
 int arr[] = {1,2,3,4,5,6,7,8,9,10};
	//printf("%d\n", sizeof(arr));//计算的数组的总大小,单位是字节
	//printf("%d\n", sizeof(arr[0]));//4
	//printf("%d\n", sizeof(arr) / sizeof(arr[0]))
 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(arr[mid] == key)
     printf("找到了,下标是%d\n", mid);
     else
     printf("找不到\n");
}

查找次数为 log_{2}^{n}。10个数字,找4次。、

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//升序
	//printf("%d\n", sizeof(arr));//计算的数组的总大小,单位是字节
	//printf("%d\n", sizeof(arr[0]));//4
	//printf("%d\n", sizeof(arr) / sizeof(arr[0]));
	int k = 7;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//1
	int left = 0;
	int right = sz-1;
	int flag = 0;//flag的作用是标志是否找到了
	//2
	while (left<=right)
	{
		int mid = (left + right) / 2;
		if (arr[mid] == k)
		{
			printf("找到了,下标是:%d\n", mid);
			flag = 1;
			break;
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	//1 2
	if (flag == 0)
		printf("没找到\n");

	return 0;
}

4.

//编写代码,演示多个字符从两端移动,向中间汇聚
//welcome to bit!!!!!
//###################
//w#################!
//we###############!!
//wel#############!!!
//...
//welcome to bit!!!!!
//

//welcome to bit!!!!!
//###################
#include <string.h>
#include <windows.h>
//Sleep需要一个windows.h的头文件

int main()
{
	char arr1[] = "welcome to bit!!!!!";
	char arr2[] = "###################";
	int left = 0;
	int right = strlen(arr1)-1;

	while (left<=right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);//单位是毫秒
		system("cls");//system函数可以执行系统命令(cmd中),cls是清理屏幕
//加了这个实现的效果是只有一行,两端向中间汇聚
		left++;
		right--;
	}
	printf("%s\n", arr2);
	return 0;

5.

//假设密码是:"123456"
//
int main()
{
	int i = 0;
	char password[20] = {0};
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", password);
		//判断密码是否正确
		//两个字符串比较相等是不能使用==的,应该使用strcmp库函数
		//strcmp返回0表示2个字符串相等
		//strcmp返回>0的数字,表示第一个字符串大于第二个字符串
		//strcmp返回<0的数字,表示第一个字符串小于第二个字符串
		//比较对应位置的字符串
		//abcd\0
		//abq\0
		//a,b都相等,q的阿斯克码值更大,所以第二个字符串更大

		if (strcmp(password, "123456") == 0)
		{
			printf("登录成功\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	//1 2
	if (i == 3)
		printf("退出程序\n");

	return 0;
}

问题:scanf输入字符串到数组里面会放入\0吗?——利用代码和监视器实现

关于gets()与scanf()输入字符串与\0,\n,空格之间的问题_scanf输入空格会被当作字符吗-CSDN博客

int main()
{
	char arr[] = "xxxxxxxxxx";
	scanf("%s", arr);

	return 0;
}
3.4.3 猜数字游戏实现【自己打代码、课(3)50min】
要求:
1.电脑会随机生成一个数字(要随机,并且1-100)
2.猜数字
        a 猜到了,提醒猜大,继续猜
        b 猜小了,提醒猜小,继续猜
        c 猜对了,恭喜你
3.玩完一把不过瘾可以继续玩,不用退出程序
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void menu()
	printf("***************************\n");
	printf("***** 1.play   0.exit *****\n");
	printf("***************************\n");
}

//void srand (unsigned int seed);
void game()
{
	RAND_MAX;
	//1. 生成随机数
	int ret = rand() % 100 + 1;//可以生成随机数,随机数的范围是:0~32767
	//0~99
	//2. 猜数字
	int guess = 0;

	while (1)
	{
		printf("请猜数字:>");
		scanf("%d", &guess);
		if (guess > ret)
		{
			printf("猜大了\n");
		}
		else if (guess < ret)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}

int main()
{
	//打印菜单
	//1. 玩游戏
	//0. 退出游戏
	int input = 0;
	srand((unsigned int)time(NULL));//要给srand传递一个变化的值,计算机上的时间是时刻发生变化的
	//time函数可以返回一个时间戳
	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);

	return 0;
}

int main()
{
again:
	printf("hehe\n");
	printf("hehe\n");
	printf("hehe\n");
	printf("hehe\n");

	goto again;

end:
	return 0;
}

void test()
{
flag:
	printf("test\n");
}

int main()
{
	printf("hehe\n");
	goto flag;//goto 语句只能一个函数内部跳转,不能跨函数跳转的
	return 0;
}

4.go to语句

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值