C语言入门笔记 第五讲【分支和循环-练习题】

本文通过五个具体案例,包括计算阶乘、数组查找、字符汇聚显示、用户登录验证等,详细介绍了C语言中的核心算法实现。

题目一:计算n的阶乘。

我的思路:

n的阶乘一共要乘以n次,也就是n次循环,

这里我打算用for循环,一共循环n次,

每一次都让最终的结果乘以在第i次的i值,而i又是从1开始,以1为公差,递增到n的,

从而实现了n的阶乘。

代码实现:

int main() 
{
    int n = 0;
	int num = 1;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		num = num * i;
	}
	printf("%d的阶乘为:%d\n",n, num);
return 0;
}

结果截图:

题目二:计算 1!+2!+3!+……+10!

我的思路:

本题中的计算n的阶乘,可参考题目一。

于是,我先写了一个题目一中的for循环,计算n!。

然后,我定义了一个sum变量,用于存放最后的总值。

现在要做的,就是让n从1开始,以1为公差,递增到n。

我们再写一个外套for循环,让n从1开始,以1为公差,递增到n即可。

这里要注意的是,我们需要在外层for循环中,每一次都初始化num的值,使其为1,

这样在内层for循环执行时,都是从1开始往上乘,

如果写在外面,会出问题,每次遗留的num不被初始化,不从1开始,算出来的值会更大,也是错误的值。

代码实现:

int main() 
{
	
	int num;
	int sum = 0;
	for (int n = 1; n <= 10; n++)
	{
		num = 1;
		for (int i = 1; i <= n; i++)
		{
			
			num = num * i;

		}
		printf("%d!的阶乘为%d\n", n,num);
		sum = sum + num;
	}
	
	printf("阶乘总和为:%d\n", sum);
	return 0;
}

 结果截图:

题目三:在一个有序数组中查找具体的某个数字n。

题目补充描述:

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

功能:在v[0]<=v[1]<=v[2]<= ….<=v[n-1]的数组中查找x。

 我的思路:

首先创建一个数组,

然后对其进行排序。

这里我准备用冒泡排序法,于是准备先写一段冒泡排序:

【番外--冒泡排序】

冒泡排序的原理如下: 

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 

  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 

  3. 针对所有的元素重复以上的步骤,除了最后一个。 

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

 假如我们要排数组{1,5,6,2,7}

代码实现如下:

int BubbleSort(int v[],int n)
{
	
	for (int i = n; i > 1; i--)//对数组进行冒泡排序
	{
		for (int j = 0; j < i - 1; j++)
		{
			if (v[j] > v[j + 1])
			{
				int temp = 0;
				temp = v[j + 1];
				v[j + 1] = v[j];
				v[j] = temp;
			}

		}

	}

	for (int k = 0; k < n; k++)//输出冒泡排序的结果
	{
		printf("%d ", v[k]);
	}

	return 0;
}

接下来开始实现查找功能。

for (int k = 0; k < n; k++)//依次查找
	{
		if (x == v[k]) 
		{
			printf("已查找到元素%d,它是该数组的第%d个元素", x, k + 1);
			break;
		}
		if(k==n-1&&x!=v[k])
			printf("未找到该元素!");
			
			
	}

注:if{里面的break}不是跳出if,而是跳出整个循环。

但是,这样的查找效率未免有些低。

我们可以采用折半查找算法来进行:

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

给一组有序数:1,2,3,4,5,6,7,8,9,10

找到7。

我们要找7,

可以先找中间元素,第五个元素

再找第八个元素

再找第六个元素

再找第七个元素

...

最坏查找4次

查找效率高了很多

时间复杂度为O(log2n)

这组有序数的下标为:

0 1 2 3 4 5 6 7 8 9

查找代码:

int k = 7;//找7
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);//求出数组中的元素
	int left = 0;//左下标
	int right = sz - 1;//右下标
	while (left<=right) 
	{
		int mid = (left + right) / 2;
		if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			printf("找到了,下标是:%d\n", mid);
			break;
		}
			
	}
	if (left > right)
	{
		printf("找不到该元素\n");
	}

注:

循环的条件是:

left<=right 

只有在这样的条件下,才说明中间有元素可被查找。

最后,附上总的代码和执行结果【注意给函数加上返回值!】:

//在一个有序数组中查找具体的某个数字n。
//编写int binsearch(int x, int v[], int n); 
//功能:在v[0] <= v[1] <= v[2] <= …. <= v[n - 1]的数组中查找x。
int binsearch(int x, int v[], int n)
{
	printf("数组为:");
	for (int q = 0; q < n; q++)//输出冒泡排序的结果
	{
		printf("%d ", v[q]);
	}
	for (int i = n; i > 1; i--)//对数组进行冒泡排序
	{
		for (int j = 0; j < i - 1; j++)
		{
			if (v[j] > v[j + 1])
			{
				int temp = 10;
				temp = v[j + 1];
				v[j + 1] = v[j];
				v[j] = temp;
			}

		}

	}
	printf("\n排序后的结果为:");
	for (int m = 0; m < n; m++)//输出冒泡排序的结果
	{
		printf("%d ", v[m]);
	}

	int left = 0;//左下标
	int right = n - 1;//右下标
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (v[mid] > x)
		{
			right = mid - 1;
		}
		else if (v[mid] < x)
		{
			left = mid + 1;
		}
		else
		{
			printf("\n找到了,是第%d个元素", mid+1);
			break;
		}

	}
	if (left > right)
	{
		printf("找不到该元素\n");
	}
	return 0;

	}

int main()
{
	int v[8] = { 15,73,86,23,25,47,1,33 };
	binsearch(33, v, 8);
	return 0;
}

 执行结果:

本题心得:

如果函数定义中有数组,

比如f(int v[]){

}

那么在实际调用中,只需要:

int v[10] = {1,2,3,4};

f(v);

不用加[]。

这里到函数讲会详细再说明。

题目四:编写代码,演示多个字符从两端移动,向中间汇聚。

题目补充描述:

helloworld

##########

h########d

he######ld

...

helloworld

每一次露出两端的一个字符。

我的思路:

准备两个字符数组:

1、helloworld

2、##########

left = 0;right = n-1;

left++;right--;

这里注意:

如果arr是char类型数组,

int right = sizeof(arr1) / sizeof(arr1[0]) - 1;

这句代码无法求出数组长度和数组最后一个元素的下标!

这是因为:

举例char arr[] = "abc";

数组:[a b c \0] 会多放一个\0

下标:[0 1 2 3]

所以数组长度为sizeof(arr1) / sizeof(arr1[0]) - 1

right = sizeof(arr1) / sizeof(arr1[0] - 2)。

还有一个方法:

int right = strlen(arr1)-1;

下面看正式逻辑。

int main()
{
	char arr1[] = "helloworld";
	char arr2[] = "##########";
	int left = 0;
	int right = sizeof(arr1) / sizeof(arr1[0])-2;
	while (left<=right) 
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		left++;
		right--;
	}
	
	return 0;
}

下面加入Sleep(毫秒)函数

可以一秒后再继续;

需要引用windows.h这个头文件

再引入system();

这是执行系统命令的一个函数。

system(“cls”);

清空屏幕。

最终代码:

int main()
{
	char arr1[] = "helloworld";
	char arr2[] = "##########";
	int left = 0;
	int right = sizeof(arr1) / sizeof(arr1[0])-2;
	while (left<=right) 
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);
		system("cls");
		left++;
		right--;
	}
	printf("%s\n", arr1);
	return 0;
}

 

题目五:编写代码实现,模拟用户登录情景,并且只能登录三次。

题目补充描述:

只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序。

 我的思路:

循环三次,

如果i==3,那么说明3次都错,输出错误;

如果i<3,说明3次内,输入正确。

实现代码:

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");
}

注:

不能写如下语句:

if(password == "123456")

==不能用来比较两个字符串是否相等。

应该使用一个库函数:string compare

strcmp();头文件为string.h

strcmp(password,"123456");

返回值

字符串1=字符串2,返回值=0; 
字符串2〉字符串2,返回值〉0; 
字符串1〈字符串2,返回值〈0。 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值