分支语句与循环语句(四)练习

文章介绍了计算阶乘的C语言代码实现,包括单个阶乘计算和阶乘之和的计算,讨论了溢出问题。接着讲解了二分查找算法在有序数组中的应用,提高了查找效率。还展示了如何通过字符数组模拟两端移动的效果。最后给出了一个简单的用户登录情景模拟,限制登录尝试次数,强调了字符串比较的正确方法。
摘要由CSDN通过智能技术生成

练习

1、计算n的阶乘。n!=1×2×3×......×(n-1)×n

int main(){
            int i=0;
            int n=0;
            scanf("%d",&n);//n为想要输入的值,这时就需要输入函数scanf
            int ret=1;   //ret不能为0,若为0,0不管乘任何数都为0
            for(i=1;i<=n;i++){
                                 ret=ret*i;
                              }
            printf("ret=%d\n",ret);
            return 0;
}

如:输入5,则ret=120。

但要注意,若n=100时,则会出现错误,因为100的阶乘在整形可能放不下;所以这串代码是在不考虑溢出的情况下运行的。

2、计算1!+2!+3!+......+10!

当我们想求出几个阶乘之和时,正确写法如下:

int main(){
            int i=0;
            int n=0;
            int ret=1;  //对应外围的循环,不影响内部的
            int sum=0;
            for(n=1;n<10;n++){
                                for(i=1;i<=n;i++){
                                                     ret=ret*i;
                                                 }
                                   sum=sum+ret;
                              }
            printf("sum=%d\n",sum);
            return 0;
}

这里要加上ret=1;才会得出正确答案。

假设我们要算1!+2!+3!阶乘的和——

n<=3时,打印结果为15;但我们知道1!+2!+3!=9

这是因为,当n=1时,ret=1×1;当n=2时,ret=1×1×2;当n=3时,ret=2×1×2×3=12;

因为ret没有被初始化,所以会累计下来。

这个代码麻烦在它将每个阶乘都算一遍;其实,只要算出前面的阶乘在乘后一个阶乘数既可。

如:算出4!的阶乘后,求5!的阶乘,只需4!的阶乘再乘5既可。如——5!=4!×5

所以优化后的代码:

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

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

编写——

int binsearch(int x,intv[],int n);

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

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

以上代码我们发现这样查找不太高效。

因为如果你要查较大的数,这样,最坏的情况下,你要找n次。

比如一双鞋子的价格·范围在1~500之间,如果按第一种方法,就得从1开始往后查询,直至找到想要的数。(这样就比较麻烦)

因为我们知道一双鞋子不可能价格很低,所以我们会来猜一个数(一般从中间数开始)

250~500?如果说250低,则往上猜。

350~500?如果说350过高,这样将价格锁定到250~350之间。

250~350相较于1~500而言,范围就小了,更接近准确值了。

回到上述问题,1~10也是同样,如果想找7;就假设从5开始~8结束

而这种方法又叫——折半查找算法或二分查找算法

对比12345678910(从前往后的算法复杂度是n);这种算法只需4次,算法复杂度是㏒₂ⁿ【如:㏒₂ⁿ的n为10的话,整体值为约等于3~4之间,接近4,所以约为4】

1 2 3 4 5 6 7 8 9 10

0 1 2 3 4 5 6 7 8 9  ——下标

算0~9的中间值为4,而下标4对应5,又因5<7;所以下标4向前一位5~9中间值为7,下标7→8,所以锁定范围6~8

以上是查找次数。

折半查找算法的话只需㏒₂ⁿ次,按顺序的话要n次。

所以代码为:

int main(){
             int arr[]={1,2,3,4,5,6,7,8,9,10}
             int k=7;
             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");
              return 0;
}

因为如果数组里没有想要的数,那计算下标的时候会可能交错。

 1 2 3 4 5 6 8 9 10 11

  0 1 2 3 4 5 6 7 8 9

5~9:7

5~6:5.1

6~5:

7~4:

因此要有left<=right。

【注:若有相同的数时,只会优先打印最前的数。就比如数组中两个数值7】

以上是二分查找算法的写法,二分查找算法可以用函数的方式写

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

如:

welcome to bit ! ! ! ! ! !

####### ## ########

w###........................#!

we#..........................#!!

             .......

达到这样的效果——把第一块空间的数组从两端开始依次往下遮盖。

那如何实现呢?——这其实要用到上面所学的二分查找算法。

left =0;                   right=n;

left++;                    right--;

char arr1[ ]="welcome to bit ! ! !"

char arr2[ ]="###############"

注:字符串中包括一个“\0”。

元素个数不给定,拿后面字符串来初始化它,用字符串来判断数组开辟多大空间。

左下标:int left=0;

右下标:int right =sizeof(arr1)/sizeof(arr[0]-2);这里要减2,不能减1.

假设char arr[ ]="abc";

这个数组其实是有4个元素。

a b c \0

0 1 2 3 ——对应下标

注意:\0并不是上一个数组的“!”,“!”后还有一个“\0”。

“c的下标是2,然计算这个数组的元素个数会是4;而4-1=3,又因下标3对应的是\0,所以要4-2才对。

【注:以上大家可以试着用这种方法去敲出代码。】

这里还可换另一种方法:

将sizeof换成strlen。【注;strlen函数求字符串长度,不包括“\0”。】

如:

int right=strlen(arr1)-1;

往下思考:

arr1——"welcome to bit!!!"

arr2——"#############"

可以用:

arr2[left]=arr1[left];

arr2[right]=arr1[right];

赋值给它。

总结得出——

#include<stdio.h>
#include<string.h>
#include<windows.h>
int main(){
             char arr1[]="welcome to bit!!!";
             char arr2[]="#################";
             int left=0;
             int right=strlen(arr)-1;
             while(left<=right){
                                   arr2[left]=arr1[left];
                                   arr2[right]=arr1[right];
                                   printf("%s\n",arr2);
                                   sleep(1000);//单位是毫秒,表示休息间隔1000毫秒,也就是1秒。
                                   left++;
                                   right++;
                                }
              printf("%s\n",arr2);//循环外添加,要想保留的话得加上。
              return 0;
}

sleep函数——这样打印出来就有了时间递进效果,不然会很快闪现出来。

这串代码还可以用上system函数——

system("cls");

这个会清空屏幕内容。

system函数用来执行系统命令。

cls——清空屏幕。

但要主要用上此函数要引用对应头文件——#include<stdlib.h>

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

#include<stdio.h>
#include<string.h>
int main(){
             int i=0;
             char password[20]={0};
             for(i=0;i<3;i++){
                               printf("请输入密码:>");
                               scanf("%s",password);
                               if(strcmp(password,"123456"==0){
                                                                  printf("登录成功\n");
                                                                  break;
                                                              }
                             }
              else{
                    printf("密码错误\n");
                  }
              if(i==3)
              printf("三次密码均错误,退出程序\n");
              return 0;
 }

注:==双等号不能用来比较两个字符串是否相等,应该使用一个库函数strcmp。

strcmp库函数比较password与123456如果相等,则会返回一个值0;如果第一个字符串大于第二个,会返回一个大于0的数;小于的话,则相反。

strcmp函数对应的头文件是——#include<string.h>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值