学C的第二十一天【初阶测评讲解:1. 计算递归了几次;2. 判断 do while 循环执行了几次;3. 求输入的两个数的最小公倍数;4. 将一句话的单词进行倒置,标点不倒置;补充知识点】

简介: 1. 计算递归了几次:

67040d669dcf4a7db53acae1f164fa6d.png1. 计算递归了几次:

#include <stdio.h>
int cnt = 0;
int fib(int n)
{
  cnt++;
  if (n == 0)
  {
    return 1;
  }
  else if (n == 1)
  {
    return 2;
  }
  else
  {
    return fib(n - 1) + fib(n - 2);
  }
}
void main()
{
  fib(8);
  printf("%d", cnt);
}

469d045ac4a54573bcacb00a2a223b30.png

2. 判断 do while 循环执行了几次:

//在上下文和头文件均正常的情况下,以下程序的输出结果是()
#include <stdio.h>
int main()
{
  int x = 1;
  do {
    printf("%d\n", x++);
  } while (x--);
  return 0;
}


image.png

3. 求输入的两个数的最小公倍数

思路一:

                     

假设 a 和 b 的较大值最小公倍数

                     

如果较大值能同时整除两个数,说明较大值两值的最小公倍数,跳出循环,

                     

不能整除较大值++直到能同时整除两个值跳出循环

             

//求输入两个整数的最小公倍数
#include <stdio.h>
//最小公倍数 肯定会 大于等于 较大值
//所以可以试试用 较大值 同时 整除两个数 ,能整除 最小公倍数就是 较大值
//不能整除就把 较大值++ ,直到能整除两个数
int main()
{
  //输入两个值
  long long a = 0;
  long long b = 0;
  scanf("%lld %lld", &a, &b);
  //假设 a 和 b 的较大值是最小公倍数
  //使用三目表达式,把 较大值 取出 
  long long m = a > b ? a : b;
  //
  while (1)//死循环
  {
    if (m % a == 0 && m % b == 0)
    {
      break;
      //如果较大值能同时整除两个数,说明是两值的最小公倍数,跳出循环
    }
    //不能整除则 较大值++,直到能同时整除两个值跳出循环
    m++; //效率较低
  }
  printf("%lld\n", m);
  return 0;
}

image.png

思路二:

               

假设有 a b ,两值的最小公倍数ki = 1

               

让       a * i % b        看能不能整除掉余数等于0

               

能整除最小公倍数是 k = a * i

               

不能i++

               

直到能整除为止,此时最小公倍数 k = a * i

//求输入两个整数的最小公倍数
#include <stdio.h>
//思路二:
//假设有 a 和 b ,两值的最小公倍数是 k ,i = 1
//让        a * i % b        看能不能整除掉(结果等于0)
//不能则 i++,
//直到能整除为止,此时最小公倍数 k = a * i
int main()
{
  //输入两个值
  long long a = 0;
  long long b = 0;
  scanf("%lld %lld", &a, &b);
  //求最小公倍数
  int i = 1;
  while (a*i % b != 0)//这里 !=0 可以省略
  // a*i 不能整除 b 则改变 i ,直到可以整除退出循环 
  {
    i++;
  }
  //直到能整除为止,此时最小公倍数 k = a * i
  printf("%lld\n", a*i);
  return 0;
}

image.png

4. 将一句话的单词进行倒置标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I              

补充知识点一:gets()

             

读取一个 字符串 即使中间有空格

             

   gets(arr); --  把读取到的字符串 放进 字符串数组arr

             

(编译器可能会觉得该函数不安全而报警告,因为读取的字符串放进数组后可能会导致数组越界,可能会报错爆红,但还是可以用的

补充知识点二:fgets()

             

可以使用 fgets()函数 替代 gets()函数

             

fgets(arr, 100, stdin);

     函数参数:

             

arr:把读取的字符串放进字符数组arr中

             

100获取字符串最大字符数,这里设置为100                          

             

stdin输入方式stdin键盘输入

             

(因为指定了获取的字符个数,所以不用担心数组越界,也就不会报警告

         

           
思路:(可以把两步顺序调换)

第一步: 把 整个字符串 逆序

(知道 整个字符串首尾地址后,一对一对向整个字符串中间靠拢交换)

         

第二步:再逆序每个单词

(知道 每个单词首尾地址后,一对一对向单词中间靠拢交换)

逆序的方法是一样的,可以写一个相应的自定义函数

           

           

实现代码:

//将一句话的单词进行倒置,标点不倒置。
//比如 I like beijing. 经过函数后变为:beijing. like I
//每个测试输入包含1个测试用例: I like beijing. 输入用例长度不超过100
#include <stdio.h>
#include <string.h>
//逆序 整个字符串 或 单词
void reverse(char* left, char* right)
{
  while (left < right)
  //左小于右,中间还有值且没有同时指向一个字符,继续逆序
  {
    char tmp = *left;
    *left = *right;
    *right = tmp;
    //调整指针
    left++;
    right--;
  }
}
int main()
{
  char arr[101];//数组长度不超过100,那就设置为101
  //之后要重新赋值数组的话,这里就不初始化了?
  //这里不能使用 scanf()函数 获取字符串,
  //因为当读到单词间的空格时,scanf()函数 就不再往后读了
  //这里可以使用 gets()函数 ,
  //读取一个 字符串 ,即使中间有空格
  gets(arr); //把读取到的字符串 放进 字符串数组arr中
  //但系统可能会觉得不安全,报警告
  //也可以写成:scanf("%[^\n]s",arr)
  //可以是 fgets()函数 再进行替代
  //fgets(arr, 100, stdin);
  //函数参数:
  //arr:把读取的值放进字符数组arr中
  //100:获取字符串最大字符数,这里设置为100
  //stdin:输入方式,stdin 为 键盘输入
  //求字符串长度:
  int len = strlen(arr);//strlen 不会把 \0 计算进去,找到 \0 就停了
  //逆序整个字符串:
  reverse(arr, arr + len - 1); //自定义一个逆序函数方法
  //方法参数:数组首地址(左指针) 、 最后一个字符的地址(右指针)
  //arr+len-1 :首地址 + 数组长度 - 1 ---》 最后一个字符的地址
  //逆序每个单词:
  char* start = arr;//单词起始位置
  char* cur = arr;//单词尾部位置
  //逆序每个单词:
  while (*cur != '\0')//整个字符串还没结束,继续找单词
  {
    //逆序一个单词:
    while (*cur != ' ' && *cur != '\0')
    //单词尾部未找到空格且还没到结束符就继续找下一位
    {
      cur++;
    }//直到找到单词
    //找到单词后进行单词逆序
    reverse(start, cur - 1);
    //因为单词尾部,cur 此时是 空格位置,所以要在空格(或\0)位置前-1
    //找下一个单词:
    start = cur + 1;
    //cur+1,空格后的下一个位置就是下一个单词的首地址
    if (*cur == ' ') 
    //只有是空格时才能跳过,\0不能再跳过了,不然就跳不出循环了
    {
      cur++; //尾部跳过空格
    }
  }
  printf("%s", arr);
  return 0;
}

自定义逆序函数方法:

f6be3827fcf54ab484b489a5b8d5e599.png

主函数:

bd3cabf553be486facf05430f226a169.png

b84cf2f1f38d4830a98f233080a2ae73.png

补充:

           

1. 赋值运算符 优先级很低的  (例如:*= , /=……);

             

2. 全局变量局部变量同名的情况下,调用优先调用 局部变量

             

             

3. C语言规定,在一个源程序中main函数的位置 可以是 任意的              

             

4. 注释被编译器替换成空格,所以不要随便把注释夹在代码中间;

5. C语言早期是没有库函数的,所以可以说C语言本身是没有输入输出语句的,后来C语言的标准约定了一些函数,规定了一些函数名,功能,参数,返回类型,这些约定(规定)由编译器的厂商来提供标准库,标准库提供库函数,VS提供VS的,gcc提供gcc的,不是C语言提供的;

 

6. = 是赋值,== 是等于(啊啊啊啊啊);

针变量 *p,有:*p++,++ 的优先级是比 * 要高的,但这里是 后置++ ,是只作用于 p 的,而不是 *p,因为后置所以先执行 *p ,执行后再执行 p++ (是地址++)。如果要先 p++ ,再 *p ,可以写成 (*p)++ ;

8. 整型提升 是把 char 和 short 转化为 整型。算术转换 是把 小的类型 转换为 大的类型;


   

(奇奇怪怪的彩蛋:选择题全是坑啊啊啊啊啊,大题好难啊啊啊啊啊,我好笨啊啊啊啊啊)

相关文章
|
算法 搜索推荐 程序员
C语言第十四练——请输入一个数的逆序数
C语言第十四练——请输入一个数的逆序数
128 0
|
6月前
质数类判断方法(蓝桥杯,循环分支题型)
质数类判断方法(蓝桥杯,循环分支题型)
|
6月前
|
算法
【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)
【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)
|
7月前
|
C语言
c语言编程练习题:7-51 求奇数分之一序列前N项和
c语言编程练习题:7-51 求奇数分之一序列前N项和
78 0
|
6月前
leetcode题解:1768.交替合并字符串
leetcode题解:1768.交替合并字符串
37 0
|
7月前
|
自然语言处理 算法 编译器
编译原理复习四:编译器结构 消除左递归、左公因子 最右推导 寻找句柄讲解(附题目和答案)
编译原理复习四:编译器结构 消除左递归、左公因子 最右推导 寻找句柄讲解(附题目和答案)
175 0
|
机器学习/深度学习 算法 测试技术
C++动态规划算法的应用:得到 K 个半回文串的最少修改次数 原理源码测试用例
C++动态规划算法的应用:得到 K 个半回文串的最少修改次数 原理源码测试用例
|
算法 搜索推荐 程序员
C语言第十三练——输入一个正整数,判断这个数是否是素数
C语言第十三练——输入一个正整数,判断这个数是否是素数
134 0