一、习题

1.计算 n 的阶乘

这个问题还是比较简单的,n的阶乘可以写成123*…*n,因此可以利用一个循环函数,当<=n 

#include <stdio.h>
int main()
{
	int i = 1;
	int n = 0;
	int sum = 1;
	scanf("%d", &n);
		for (i = 1; i <= n; i++)
		{
			sum *= i;
		}
	printf("%d\n", sum);
	return 0;
}

分支和循环 做题解析(二)_C语言

 

2.计算 1!+2!+3!+……+10!’

测试算出3的阶乘,应该得到1+2+6=9

分支和循环 做题解析(二)_C语言_02

必须将第二个for里中ret初始化为1,不然每个n阶乘都会乘上一个n-1的阶乘

比如,将n == 3;没有ret的初始化,输出结果为15,实际输出应为9

改进如下⬇

分支和循环 做题解析(二)_二分查找_03

#include <stdio.h>
int main()
{
	int i = 0;
	int n = 0;
	int ret = 1;
	int sum = 0;
	for (n = 1; n <= 3; n++)
	{
		ret = 1;//初始化ret
		for (i = 1; i <= n; i++)
		{
			ret = ret * i;
		}
			sum = sum + ret;
	}

	printf("%d", sum);

	return 0;
}

分支和循环 做题解析(二)_二分查找_04

int main()
{
	int i = 0;
	int n = 0;
	int ret = 1;
	int sum = 0;
	
	for(n=1; n<=3; n++)
	{

			ret = ret * n;
		
		sum = sum + ret;
	}
	//ret = 1*1 = 1
	//ret = 1*1*2 = 2
	//ret = 1*1*2*3 = 6

	
	printf("sum = %d\n", sum);
	return 0;
}

 

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

题目:编写int binsearch(int x, int v[], int n);

功能:在v[0]<=v[1]<=v[2]<= ….<=v[n-1]的数组中查找x。
解题思路:这个题目的意思就是定义一个含多个元素的有序数组,在数组中找到某个元素。

例如:定义一个数组arr[] == {1,2,3,4,5,6,7,8,9,10},在数组中找到元素7并确定其数组下标。

首先,我想到的代码是这样的:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;
	int i = 0;
	//用数组占用字节长度除以数组首地址占用字节长度,可得出数组元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	for(i=0; i<=sz; i++)
	{
		if (k == arr[i])
		{
			printf("找到了,下标是%d\n",i);
		}
		else
		{
			printf("没找到\n");
		}
	}
	return 0;
}

但结果却是这样

分支和循环 做题解析(二)_二分查找_05

我们需要的效果应该是寻找数组全部的元素后,在屏幕上打印是否找到元素的结果,而不是找一个元素输出一个结果。

可知,代码中的分支结构中缺少break,于是改进代码。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
    //用数组占用字节长度除以数组首地址占用字节长度,可得出数组元素个数
	//从数组中所有元素中一个个查找,所以i<=sz
	for(i=0; i<=sz; i++)
	{
		if (k == arr[i])
		{
			printf("找到了,下标是%d\n",i);
			break;
		}
	}
	if(i == sz)
		printf("没找到\n");
	return 0;
}

分支和循环 做题解析(二)_二分法_06

自此,我们已经能成功在数组中寻找相关元素。

 

*二、折半查找算法*(二分法)

对与题目“在一个有序数组中查找具体的某个数字n”,当元素个数不多时,我们可以使用例题3中的解题思路;但我们要思考,当数组元素特别多时,这样从头到尾一个个从数组检查,有时候需要检查n给元素才能得知结果,效率是比较低的,那么我们能不能通过改进代码逻辑提高程序运行效率呢,这时,不得不提出二分法的概念。

折半查找算法:又称二分查找算法,又称二分法,即当有一已知最大值的一串有序数组,可以通过不断取中间值与所需寻找的元素相比较,排除一半数据,缩小搜索范围,最终确定元素的方法。比如我们去买鞋,老板告诉我们最高200元,让我们猜,那么理论上,价格可以是0,1,2…200。一般情况下,我们会说100元,如果老板说低了,那么此时猜的范围缩小为100—200,直接排除了一般数据。此时,在进行下一步猜测,直到得出结果。

于是,代码可以改进为:

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;
	int left = 0;//数组左下标
	int right = sizeof(arr) / sizeof(arr[0]) - 1;//数组右下标
	//用数组占用字节长度除以数组首地址占用字节长度,可得出数组元素个数,元素个数减一得数组右下标
	while (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)//left>right是,说明数组元素全部被寻找还是没找要找的元素
		printf("没找到\n");
	return 0;
}

分支和循环 做题解析(二)_二分查找_07

 

4. 编写代码,演示多个字符从两端移动,向中间汇聚。

解题思路:既然是多个字符从两端移动,那么就应该有两个数组,一个表示演示的字符串,一个表示不输出字符串时需要输出的字符串。

 

注意:1. 字符串结束\0算一个小标,用sizeof要-2

           2. 也可用strlen

分支和循环 做题解析(二)_二分查找_08

 

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
int main()
{
	char arr1[] = "hello,world";
	char arr2[] = "###########";
	int left = 0;//数组左值
	int i = 0;
	//因为字符串的结束是'\n',数组下标从0开始(与数组个数差一),因此用sizeof计算是应该减2
	//int right = sizeof(arr2) / sizeof(arr2[0])-2;
	int right = strlen(arr1) - 1;//数组长度减一,strlen不会计算'\n'
	while (left <= right)
	{
		arr2[left] = arr1[left];//将arr1中左边的字符传递给arr2
		arr2[right] = arr1[right];//将arr1中右边的字符传递给arr2
		printf("%s\n", arr2);
		Sleep(1000);//延迟函数,单位为ms
		system("cls");//执行系统命令的一个函数-cls-清空屏幕
		left++;
		right --;
	}
	printf("hello, world\n");
	return 0;
}

效果如下:

分支和循环 做题解析(二)_二分查找_09

分支和循环 做题解析(二)_算法题_10

 

5、模拟用户登录情景,并且只能登录三次

编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则  提示登录成,如果三次均输入错误,则退出程序。

 

int main()
{
	int i = 0;
	char password[] = "123456";
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码: ");
		scanf("%s", password);

		if (strcmp(password ,"123456")==0)
		//== 不能用来比较两个字符串是否相等,应该使用一个库函数-strcmp
		{
			printf("输入正确,登录成功\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	if (i == 3)
	{
		printf("三次输入错误,退出程序\n");
	}
	return 0;
}

效果如图:

分支和循环 做题解析(二)_二分法_11分支和循环 做题解析(二)_算法题_12

  三、goto语句举例

goto语句可以直接跳转到设定的位置,但易造成程序逻辑错误,较少用。

//goto语言,30s关机程序
int main()
{
	char input[20] = { 0 };
	system("shutdown -s -t 30");//设置30s关机
	again:
	printf("你的电脑将在30s后关机,请输入:我是猪,取消关机\n");
	scanf("%s", &input);
	if (strcmp(input, "我是猪") == 0)//设置取消关机的判断条件
	{
		system("shutdown -a");//取消关机
		printf("你已取消关机\n");
	}
	else
	{
		goto again;
	}
	return 0;
}