c语言 选择结构 循环结构

166 阅读3分钟

1. 选择结构

在c语言中 非零就是真 ,-1也是真。0 就是假。

if 分支语句

int main()
{
	int age = 20;
	if (age >= 18) // 判断是否大于等于 18
	{
		printf("成年 \n"); // 符合判断 执行
	}
	else
	{ // 不符合执行代码块
		printf("未成年 \n");
		printf("不能恋爱 \n");
	}
	return 0;
};
// 多分支语句
int main()
{
	int age = 30;
	if (age <= 18 && age >= 3) {
		printf("儿童");
	}
	else if(age > 18 && age < 26) {
		printf("青年");
	}
	else if (age > 26 && age < 38) {
		printf("壮年");
	}
	else if (age > 38 && age < 50) {
		printf("中年");
	}
	else {
		printf("老年");
	}
	return 0;
};

// 有坑啊 else 就近匹配 if 下面打印 空白 什么都没有。
// 因为 else 会匹配 if(b == 2)printf("hehe \n");
// 一定要注意代码风格 把大括号写上 好区分代码 高质量编程
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
		if (b == 2)
			printf("hehe \n");
	else
		printf("hahhah \n");
	return 0;
};

// 改正
// 打印 hahhah
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
	{
		if (b == 2)
			printf("hehe \n");
	}
	else
	{
		printf("hahhah \n");
	}
	return 0;
};

// 再看问题

int main()
{
	int a = 3;
	// 代码可以通过 但是 a 被 **赋值成了 5** ,不是 3 ,所以不对
	if (a = 5)
	{
            printf("成功");
        };
	return 0;
};

// 改正
int main()
{
	int a = 3;
        // 两个整型进行比较的化把常量放到 **左边** 不会出错
	if (5 == a)
	{
            printf("成功");
        };
	return 0;
};

if 分支小练习

int main()
{
	// 判断一个数是否为奇数
	int i = 20;
	if (i % 2 == 1)
	{
		printf("是奇数");
	}
	else {
		printf("不是奇数");
	}
	return 0;
};
// ------------------------  分割线  --------------------------------
int main()
{
	int i = 0;
	// 判断 1 -100 以内的奇数 打印
	while (i <= 100) 
	{
		i += 1;
		if (i % 2 == 1)
		{
			printf("%d 是奇数 \n", i);
		}
	}
	return 0;
};

switch 分支语句

int main()
{
	int day = 0;
	scanf("%d",&day);
	switch (day) // 只能是整型表达式
	{
	case 1: // case 决定了入口 ,必须包含常量值,字符型也可以,浮点不行
		printf("星期一");
		break; // break 决定了出口
	case 2:
		printf("星期二");
		break;
	case 3:
		printf("星期三");
		break;
	case 4:
		printf("星期四");
		break;
	case 5:
		printf("星期五");
		break;
	}
	return 0;
};

// ------------------------  分割线  --------------------------------

int main()
{
	// 1 - 5 工作日
	// 6 7 休息日
	int day = 0;
	scanf("%d",&day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("%d 工作日",day);
		break;
	case 6:
	case 7:
		printf("%d 休息日", day);
		break;
	}
	return 0;
        default: // 不满足 case 时执行
            printf("请输入1-7数字");
	break;
};

编程好习惯
在最后一个case语句的后面加上一条break语句。
(之所以这么写是可以避免出现在以前的最后一个case语句后面忘了添加break语句)。

switch 分支语句 小练习

int main()
{
	int n = 1;
	int m = 2;
	switch (n)
	{
	case 1: m++; // 3
	case 2: n++; // 2
	case 3: 
		switch (n) // 2
		{
		case 1:
			n++;
		case 2:
			m++; // 4
			n++; // 3
			break;
		}
	case 4:
		m++; // 5
		break;
	default :
		break;
	}
	printf("m = %d ,n = %d \n ", m, n);// m = 5 n = 3
	return 0;
};

while 循环语句

while( 表达式 ){ 循环语句 代码块 };表达式成立 循环语句 执行,否则不执行。

int main()
{
	int i = 0;
	// 在 while 循环中 break 用于永久的终止循环
	// 在 while 循环中 continue 的作用是 跳过本次循环 continue 后面的代码,
	// 直接去 while 判断是否进行下次循环
	while (i <= 10)
	{
		i++;
		if (i == 9)
		{
			printf("跳出");
			break;
		}
		 if (i % 2 == 0)
		{
			continue;
		}
		printf("%d \n", i);
	}
	return 0;
};

// ------------------------  分割线  --------------------------------

int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)// getchar 获取字符
	{
		putchar(ch); // putchar 输出字符
	}
	return 0;
};

getchar()
scanf() 都是在输入缓冲区拿取数据

while 小练习

int main()
{
	char str[20] = { 0 };
	printf("请输入密码 : > ");
	scanf("%s", str);
	printf("请确认密码(Y/N)");
	int temp = 0;
        // 清理缓存区
	while ((temp = getchar()) != '\n')
	{
		;
	}

	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功");
	}
	else if (ch == 'N')
	{
		printf("确认失败");
	}
	return 0;
};


int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		if (ch < '0' || ch > '9') // 除数字以外都不管用 
		{
			continue;
		}
		putchar(ch);
	}
	return 0;
};

for 循环语句

// for(表达式1;表达式2;表达式3)
// { 代码块 }
// 不要在for循环体内 改变循环变量
// for循环控制变量的取值采用 “前闭后开区间”写法
int main()
{
	for (int j = 0; j < 10; j++)
	{
		printf("%d \n", j);
	}
	return 0;
};

for循环的变种

int main()
{
	for (;;)// 死循环 可以省略,但是判断部分省略就会死循环
	{
		printf("hehe \n");
	}
	return 0;
};

// ------------------------  分割线  --------------------------------

int main()
{
	// 省略写法带来的麻烦
	int i = 0;
	int k = 0;
	for (; i < 3; i++)
	{
		for (; k < 3 ;k++)
		{
			printf("hehe \n");// 结果 打印三个 hehe。 为什么?
			// 第一次循环进来执行 到 k 执行了三次 
			// 第二次循环执行进来时 k 已经是 3 了,没有重置成 k = 0
			// 可以理解成 你把变量写在全局 但是 局部没更新它 拿的还是全局存储的当前变量值
		}
	}
	return 0;
};

// ------------------------  分割线  --------------------------------

int main()
{       // 混合变量
	for (int x = 0, y = 0; x < 2 && y < 5; ++x ,y++)
	{
		printf("hehe \n");// 2 次
	}
	return 0;
};

// ------------------------  分割线  --------------------------------

// 笔试题 循环几次。 答:一次也没循环

int main()
{
	int i = 0;
	int k = 0;
	for (i = 0,k = 0;k = 0;i++,k++)// 在判断表达式 写成了赋值 k = 0, 那么不会进入循环体内。
	{
		k++;
	}
	return 0;
};

do while 循环语句

// 循环只少一次
do
{
    循环语句
}while(表达式)

// ------------------------  分割线  --------------------------------

int main()
{
	int i = 0;
	do
	{
		i++;
		if (i == 9) break;
		if (i == 5) continue; // 跳过 5
		printf("%d \n", i);
	} while (i < 10);
	return 0;
};

循环 小练习

int main()
{
	// 阶乘 1 * 2 * 3 ...
	int n = 1;
	int sum = 1;
	int i = 1;
	scanf("%d", &i);
	while (i >= n)
	{
		sum *= n;
		n++;
	}
	printf("%d", sum);

	return 0;
};

// ------------------------  分割线  --------------------------------

int main()
{
	int n = 1;
	int pro = 1;
	int i = 4; // 4 的阶乘
	int sum = 0; // 存储阶乘相加的数
	while (i >= n)
	{
		pro *= n;  
		sum += pro;// 1! + 2! + 3! + 4! = 33
		n++;
	}
	printf("%d", sum);

	return 0;
};

// ------------------------  分割线  --------------------------------

// 二分查找 元素
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 2;
        // sizeof() 是操作符 返回byte ,int 一个 byte 是4,
        // 所以 40 / 4 = 10
	int len = sizeof(arr) / sizeof(arr[0]); // 数组的元素个数
	int left = 0; int right = len - 1;
	while (left <= right)
	{
		int mid = (left + right) / 2;// 拿到当前的中间下标

		if (arr[mid] < i)
		{
			left = mid + 1;
		}
		else if (arr[mid] > i)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了下标 :%d", mid);
			return 0;
		}
	}
	if (left > right)
	{
		printf("找不到元素");
	}
	return 0;
};

二分查找 小总结:

  1. 首先确定数组是有序的,确定查找目标值。

  2. sizeof() 操作符找到数组的个数

  3. 确定左边下标位 0 ,右边下标位 len -1.

  4. 每次寻找中间下标数 (left + right) / 2

  5. 判断查找的当前数组元素是否 小于 目标元素,比如我要查找 7 ,而当前 arr[mid] 是 5 当前 mid 是4,如果小于那么确定要查找的元素 范围 5 -- 10,可以让 left 重新赋值 为 mid +1,确定范围 5 -- 10,

  6. 下次查找 的下标元素为 mid = (5+10)/2;确定 mid 值:7,arr[mid] 值:8,当前值比 目标值 7 大, arr[mid] > i ,查找范围 5 -- 8,让 right 重新赋值 为 mid -1,当前的 mid :6 ,arr[mid]:7。

  7. 下次查找 的下标元素为 mid = (5+7)/2;确定 mid 值:6, arr[mid] 值:7 ,查找目标值为 7, 找到元素 返回 下标:6 。

  8. 因为它们都是从两侧不断的 向中间 压缩,所以循环条件 是 left <= right ,如果 left > right 那么 不会有你要找的元素。


int main()
{
	char arr1[] = "welcome to china !!!\0";
	char arr2[] = "####################\0";
	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);// 睡眠一秒
		left++;
		right--;
	}
	return 0;
};

0133.png

// 三次密码输入
int main()
{
	char pas[20] = { 0 };
	int pas1 = "123456";
	int i = 2;
	for (i = 2; 0 <= i; i--)
	{
		printf("请输入密码:> ");
		scanf("%s", pas);
		if (strcmp(pas, "123456") == 0)// 密码输入对了,字符串比较使用 strcmp()
		{
			printf("正确");
			break;
		}
		else
		{
			printf("密码错误,剩余次数: %d 次 \n", i);
		}
	}
	return 0;
};
// 打印三角
int main()
{
	char arr2[] = "          \0";
	char arr1[] = "**********\0";

	int len = strlen(arr1);
	int mid = (len / 2);
	int left = mid - 1;
	int right = mid + 1;

	arr2[mid] = arr1[mid];
	printf("%s \n", arr2);
	while (left > 0 && right < 10)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[left];
		printf("%s \n", arr2);
		left--; right++;
	}

	return 0;
};

0998.png