C语言基础练习

文章介绍了计算阶乘n!的代码实现,包括使用循环的方法。接着探讨了如何计算1!到10!的和,通过优化循环避免了错误。随后讲解了在有序数组中进行二分查找的原理和代码实现。此外,还展示了如何设计字符从两端向中间汇聚的动画效果,利用`system(cls)`清屏和`Sleep`延迟函数。最后,模拟了用户登录情景,重点提到了`strcmp`函数用于比较字符串。
摘要由CSDN通过智能技术生成

目录

1.1 计算n!

代码如下: 

1.2 计算1! + 2! +……+ 10!

 代码如下:

2.1 在有序数组中查找某个具体的数字

2.2 二分查找

代码如下:

3.1 字符从两端移动,向中间汇聚

3.2 字符从两边向中间一个一个跳出来

system("cls")

sleep函数

最终代码如下:

4.模拟用户登录情景

strcmp函数


1.1 计算n!

当我们看到n!时会想到n!=1*2*3*……*n 这个计算的本质就是循环

我们可以先定义一个字母i=1或者i=0也行,反正循环里面是要重新定义的
然后定义一个字母n,让n可以手动输入任意数字
使用for循环

代码如下: 

int main()
{
    int i = 0;
    int n = 0;
    scanf("%d", &n);
    int ret = 1;//创建一个数字产生乘积让前一个i可以与后一个i相乘

    for (i = 1; i <= n; i++)
    {
        ret = ret * i;//当i进入循环,ret会随i的变化而变化
    }
    printf("%d", &ret);
    return 0;
}

1.2 计算1! + 2! +……+ 10!

上一题中我们已经能算出一个n!,这题我们要将这些n!相加
我们可以新定义一个字母来存放累加的数
使用两次for循环可以解决

有小伙伴看到这里就迫不及待的去写了,不就是两个for循环吗,于是给大家演示一个错误代码:

int main()
{
    int i = 0;
    int n = 0;
    int ret = 1;//定义一个字母,当数字产生乘积时,让前一个i可以与后一个i相乘
    int sum = 0;//定义一个字母,使得每次算出的结果相加

    for (n = 1; n <= 10; n++)
    {
        for (i = 1; i <= n; i++)
        {
            ret = ret * i;//当i进入循环,ret会随i的变化而变化
        }
        sum = sum + ret;
    }
    printf("%d", sum);

    return 0;
}

细心的小伙伴调试一下会发现,当n=3时,3!的数字就不对了,怎么回事呢?

我们可以看到当n=3时,ret≠1而是ret=2,原来是刚刚的操作使ret叠加了,我们现在只需要强制的将ret在每次循环的开始改为ret=1就能解决。

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

    for (n = 1; n <= 10; n++)
    {
        ret = 1;//强制将ret=1
        for (i = 1; i <= n; i++)
        {
            ret = ret * i;
        }
        sum = sum + ret;
    }
    printf("%d", sum);

    return 0;
}

虽然这样可以计算了,但是还是有些啰嗦,能不能只用一个循环呢?我们从数学公式的本质入手:

1! =1
1! +2! =3
1! +2! +3! =9
观察一下,你就能够发现:
1! +2! +3!=( 1! +2! ) * 3
也就是说3! =2! * 3
这就好办了,我们只需要在算完一次后先存下结果,再用结果乘以下一个数字

 代码如下:

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

    for (i = 1; i <= n; i++)
    {
        ret = ret * i;
        sum = sum + ret;
    }
    printf("%d", sum);
    return 0;
}

2.1 在有序数组中查找某个具体的数字

看到这个题目的第一想法是什么?——内心想:不就是查找吗?判断有没有相等的就行了,然后咔咔一顿写。

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//一个有序数组
    int k = 7;//要查找的数字
    int i = 0;
    int flag = 0;

    for (i = 0; i < 10; i++)
    {
        if (arr[i] == k)
        {
            printf("找到了,下标是:%d\n", i);
            flag = 1;
            break;
        }
    }
    if (flag == 0)
    {
        printf("没找到\n");
    }
    return 0;
}

这个代码本质上是没什么问题,就是太慢了。如果在1~100内,查找78,我们怎么查?是不是先猜50?然后我们查找的范围是不是就变成了50~100,比刚才一个个按顺序查找快了很多。这种方式我们称之为“二分查找”或者是“折半查找”。

2.2 二分查找

首先我们是直接找数组的中间数,只需要用下标来查找,那么数组中间的下标就是(左下标+右下标)/2
我们可以用left表示左下标,right表示右下标,mid表示中间下标

我们要找的数字肯定是在左右下标中间的,当left>right时肯定是找不到任何数的,所以循环的条件就是left>=right
当要查找的数字>mid时,我们的 left 右移到mid+1的地方
当要查找的数字<mid时,我们的right左移到mid- 1的地方
(这里不理解的可以画图分析一下)

搞定了这些后你就会发现有两种情况会导致程序结束:1是找到了,2是没找到
这时我们就可以定义一个标记flag,一开始定义flag=0;当“找到了”时,flag=1
在程序的最后再判断flag

代码如下:

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int k = 7;//要查找的数字
    int left = 0;//左下标
    int right = 9;//右下标
    int flag = 0;

    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);
            flag = 1;
            break;
        }
    }
    if (flag == 0)
    {
        printf("找不到\n");
    }
    return 0;
}

3.1 字符从两端移动,向中间汇聚

比如说,我想在屏幕上打印一段字幕“welcome to CSND !!!”并且这个句子从两端移动,向中间汇聚:

1.创建一个字符串里面存放“welcome to CSDN !!!”

2.为了有汇聚这个效果,我们可以再创建一个字符串使得两个字符串中的元素可以替换,当然替换的前提条件是两个字符串的长度相同。

3.因为是从两端开始汇聚,所以我们需要知道如何替换左右两边的元素。下标是每个元素都有的,我们定义左下标为left,右下标为right,因此最左边的下标为0,最右边的下标就是字符串长度-1

(这里 “最右边的下标就是字符串长度-1” 是因为字符串的最后结尾是“\n”

(字符串的长度可以用“strlen”求出,他的头文件是#include<string.h>)

4.显然我们一次次替换不可能停留在第一个,左下标要右移:left++;  右下标要左移:right - -;

再使用一个循环就搞定,循环的条件就是 左下标<=右下标 。代码如下: 

int main()
{
	char arr1[] = "welcome to CSDN !!!";
	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);
		left++;
		right--;

	}
	return 0;
}

然后就可以看到:

 完成是完成了,但是不够美观。我想要的是只有一排,然后不断往中间变化的。

3.2 字符从两边向中间一个一个跳出来

在上一题的基础上,我们加一点东西进去:

这时就给大家介绍一个新的库函数:

system("cls")

头文件是#include<string.h>。这个函数有清屏的效果,可以再每一次循环后清屏以便形成我想要的结果。

值得注意的是:当我们的句子完全显示出来后,应为有这个函数存在,他依然是会清屏的,我们要想保留住这个句子,还需要在循环结束后打印出来。

新的问题出现了:他变化的太快了,我都没有反应过来,他就已经结束了。

哈哈,没关系,在介绍一个新函数给你:

sleep函数

单位是毫秒,头文件是#include<windows.h>。

在这道题中,我想他一秒跳出一个,只用加上Sleep(1000); 就行啦

最终代码如下:

int main()
{
	char arr1[] = "welcome to csdn!!!!!";
	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");
		left++;
		right--;

	}
	 printf("%s\n", arr2);
	return 0;

4.模拟用户登录情景

只允许输入三次密码,若三次密码均输入错误,则退出程序。

既然只允许输入三次密码,for循环可以解决

有登录成功和密码错误两个结果,if语句可以解决

为了区别是登录成功退出程序还是密码错误退出程序,可以有一个记号flag

*重点*

strcmp函数

判断两个字符串是否相等不能直接使用“==”,应该使用 strcmp函数,头文件是#include<string.h>,strcmp函数有返回值

int ret = strcmp(password,"123456");

如果第一个字符串小于第二个字符串,返回<0的数字

如果第一个字符串大于第二个字符串,返回>0的数字

如果第一个字符串等于第二个字符串,返回0

int main()
{
	int i=0;
	char password[] = { 0 };
	int flag = 0;

	for (i = 1; i <= 3; i++)
	{
		printf("请输入密码:_\n");
		scanf("%s", password);//数组名本质上就是地址,所以这里不需要取地址

		if (0==strcmp(password,"123456"))
		{
			printf("登陆成功!");
			int flag = 1;
			break;
		}
		else
		{
			printf("第%d次密码错误\n", i);
		}
	}
	if (flag == 0)
	{
		printf("三次密码均输入错误,退出程序!");
	}
	return 0;
}
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值