学C的第七天(继续 深入了解 循环语句,学习二分查找‘折半查找算法’;练习:计算n的阶乘、计算阶乘再相加、在有序数组中查找某个数字、多个字符从两端移动向中间汇聚、模拟用户登录情景)-2

简介: 练习:1.计算n的阶乘(不考虑溢出)

练习:

1.计算n的阶乘(不考虑溢出):

//计算 n的阶乘
#include <stdio.h>
//5!= 1 * 2 * 3 * 4 * 5 
//先用循环生成1-n个数字,再依次相乘
int main()
{
  int n = 0;
  scanf("%d", &n);
  int i = 0;
  int ret = 1; // 相乘后赋值给该函数,因为0乘任何数都为0,所以初始化为1
  for ( i = 1; i <= n; i++) // 利用循环生成1-n个数字
  {
    ret = ret * i; // 依次相乘
  }
  printf("%d\n", ret);
  return 0;
}


be0fb77f2e9c4a11a691d888790771e0.png

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

第一种方法效率比较低,会重复计算之前的计算过的阶乘,但逻辑比较好理解

//计算1! + 2! + 3! +...+ 10! :
#include <stdio.h>
//5!= 1 * 2 * 3 * 4 * 5 
//内循环:循环生成1-n个数字,再依次相乘
//外循环:阶乘相加
int main()
{
  int n = 0;
  int i = 0;
  int ret = 1; // 相乘后赋值给该变量,因为0乘任何数都为0,所以初始化为1
  int sum = 0; // 外循环将阶乘相加赋给该值
  //外循环:阶乘相加
  for ( n = 1; i <= 10; n++) // 加到10!
  {
    ret = 1; // 内循环中相乘后赋值给该变量,每次出了循环要重新刷新该值(重点)
    //内循环:循环生成1-n个数字,再依次相乘
    for (i = 1; i <= n; i++) // 利用循环生成1-n个数字
    {
      ret = ret * i; // 依次相乘
    }
    sum += ret; // 将阶乘相加赋给该值
  }
  printf("%d\n", sum);
  return 0;
} 


image.png

第二种方法:在原本已计算的阶乘上再乘上’下一个数‘,实现‘下一个数’的阶乘)

//第二种方法:
//计算1! + 2! + 3! +...+ 10! :
#include <stdio.h>
//5!= 1 * 2 * 3 * 4 * 5 
int main()
{
  int n = 0;
  int i = 0;
  int ret = 1; // 相乘后赋值给该变量,因为0乘任何数都为0,所以初始化为1
  int sum = 0; // 将阶乘相加赋给该值
  for (n = 1; n <= 10; n++) // 执行到10!
  {
    ret = ret * n; // 直接乘n,
    //在原本已计算的阶乘上再乘上’下一个数‘,实现下一个数的阶乘
    sum += ret; // 将阶乘相加赋给该值
  }
  printf("%d\n", sum);
  return 0;
}


image.png

3.在一个有序数组中查找具体的某个数字n。(讲解二分查找算法‘折半查找算法’):

第一种方法逻辑简单,而且在无序数组中也可以使用,但效率较低,需要一个一个查找)

//在一个有序数组中查找具体的某个数字n。
#include <stdio.h>
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; // 升序(有序数组)
  //数组下标:  0 1 2 3 4 5 6 7 8 9
  int find = 7; // 在数组中要找的值
  int i = 0; // 数组下标
  //利用for循环在数组中一个一个查找
  for ( i = 0; i < 10; i++ )
  {
    if (arr[i] == find) 
    {
      printf("找到了,该值在数组中对应的下标是:%d\n", i);
      break; // 找到后跳出循环
    }
  }
  if (i == 10) // 10超过数组下标了,说明数组中没有这个值
  {
    printf("数组中没有该值。\n");
  }
  return 0;
}

image.png

第二种方法二分查找算法‘折半查找算法’,在有序数组查找中效率更高,一次查找就能排除一半的值,重点!!)

思路:(重点!!))

改错:“对比中间下标和所找值的下标”,是要对比数组中对应下标的值


4c2c474712254cf7bd3c38a5386588a9.png

代码实现:结合上面原理图理解)

//第二种方法
#include <stdio.h>
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; // 升序(有序数组)
  //数组下标:  0 1 2 3 4 5 6 7 8 9
  int find = 7; // 在数组中要找的值
  int i = 0; // 数组下标
  int sz = sizeof(arr) / sizeof(arr[0]); // 求元素个数
  // sizeof(arr): 计算数组总大小(单位是字节)
  // sizeof(arr[0]):计算数组中单个元素大小
  // 用 sizeof(arr) / sizeof(arr[0]) ,总大小 除以 单个大小 = 元素个数
  // 1. 求左下标和右下标:
  int left = 0; // 左下标
  int right = sz - 1; // 右下标
  // 因为数组是从0开始得,所以用 元素个数-1 得出 最右边下标
  int flag = 0; // 用来设置未找到情况下的处理
  //循环查找:
  while ( left <= right ) 
  // left <= right: 说明被左右下标包裹中的数组还有值,还有值就继续循环查询
  {
    // 2.确定中间元素下标:
    int mid = (left + right) / 2;
    //进行查找:
    //找到:
    if (arr[mid] == find)
    {
      printf("找到了,该值在数组中对应的下标是:%d\n", mid);
      flag = 1;
      break;
    }
    //未找到:
    //中间值小于要找的值,排除mid和小于mid左边的值      
    else if (arr[mid] < find)
    {
      left = mid + 1; // 调整左下标
    }
    //中间值大于要找的值,排除mid和大于mid右边的值
    else
    {
      right = mid - 1; // 调整右下标
    }
  }
  if (flag == 0)
  {
    printf("没找到\n");
  }
  return 0;
}


image.png

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

Sleep(1000)休眠1秒后再执行后面语句,Sleep需要一个windows.h的头文件

system("cls"):system函数可以执行系统命令cls是清理屏幕

//编写代码,演示多个字符从两端移动,向中间汇聚:
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main()
{
  //利用字符数组来存储字符串,后面隐藏一个\0
  char arr1[] = "welcome to school!!!!!";
  char arr2[] = "######################";
  //定义左右下标:
  int left = 0;
  int right = strlen(arr1) - 1;
  // strlen(数组名称):求数组的长度,计算字符数组中\0前有多少个字符
  // 数组长度 - 1 = 最右端的小标
  while (left <= right) 
  // 如果left > right说明数组中左右下标之间已经没有值了
  // 所以有值则一直循环到无值
  {
    arr2[left] = arr1[left]; // 将arr1靠左边上的值 赋值给 arr2最左边的值
    arr2[right] = arr1[right]; // 将arr1靠右边上的值 赋值给 arr2最右边的值
    printf("%s\n", arr2); // 打印重新赋值后的arr2
    Sleep(1000); // 休眠1秒后再执行后面语句
    //Sleep需要一个windows.h的头文件
    system("cls"); // system函数可以执行系统命令,cls是清理屏幕
    left++; // ”倒数最左“
    right--; // “倒数最右”
  }
  printf("%s\n", arr2);
  return 0;
}

image.png

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

strcmp库函数:

两个字符串比较相等不能使用==(等于),应该使用strcmp库函数,需添加<string.h>头文件

       strcmp返回0表示2个字符串相等

       strcmp返回>0的数字,表示第一个字符串大于第二个字符串

       strcmp返回<0的数字,表示第一个字符串小于第二个字符串

       字符串比较大小:比较对应位置字符的ASCII值

abcd 和 abq 比较:第一位a=a,第二位b=b,第三位c<q(c的ASCII值小于q的)

       所以 abcd < abq

//5:
#include <stdio.h>
#include <string.h>
int main()
{
  int i = 0;
  //假设密码是:“123456”
  char password[20] = {0};
  int flag = 0;
  for ( i = 0; i < 3; i++) // 循环3次
  {
    printf("请输入密码:>");
    scanf("%s", password);
    // 因为password是数组,数组名本来就是地址,所以不用加取地址符&
    // 判断密码是否正确:
    // 两个字符串比较相等不能使用==(等于),
    // 应该使用strcmp库函数,需添加<string.h>头文件
    // strcmp返回0表示2个字符串相等
    // strcmp返回>0的数字,表示第一个字符串大于第二个字符串
    // strcmp返回<0的数字,表示第一个字符串小于第二个字符串
    // 字符串比较大小:比较对应位置字符的ASCII值
    // abcd 和 abq 比较:第一位a=a,第二位b=b,第三位c<q(c的ASCII值小于q的)
    // 所以 abcd < abq
    if (strcmp(password, "123456") == 0)
    {
      printf("登录成功\n");
      flag = 1;
      break; // 成功则跳出循环
    }
    else 
    {
      printf("密码错误\n");
    }
  }
  if (flag == 0) 
  {
    printf("退出程序\n");
  }
  return 0;
}

image.png

补充内容:变量的左值右值

//变量的左值和右值
#include <stdio.h>
int main()
{
  int a = 10; // 在内存申请名叫a的空间,把10存进去
  a = 20; // 把20放在a的这块空间里,这里使用的是a的空间
  int b = a; // 这里是使用了a中存放的值,把a中的20存放到b的空间(使用的是b的空间)中
  //使用变量空间的变量就是 左值  , 使用变量中存放的值的变量是 右值
  //  简单理解       (空间)                          (空间的内容) 
  return 0;
}

888332b6e66347e5bb578d4983b35b11.png

相关文章
|
17天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
60 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
13天前
|
机器学习/深度学习 人工智能 自然语言处理
【EMNLP2024】基于多轮课程学习的大语言模型蒸馏算法 TAPIR
阿里云人工智能平台 PAI 与复旦大学王鹏教授团队合作,在自然语言处理顶级会议 EMNLP 2024 上发表论文《Distilling Instruction-following Abilities of Large Language Models with Task-aware Curriculum Planning》。
|
1月前
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
62 2
动态规划算法学习三:0-1背包问题
|
17天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
17天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明