当前位置: 首页 > news >正文

C语言编程实战:每日刷题 - day3

在这里插入图片描述

🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言
🔥专栏:《C语言从零开始到精通》
《C语言编程实战》
《数据结构与算法》
《小游戏与项目》

💪格言:做好你自己,你才能吸引更多人,并与他们共赢,这才是你最好的成长方式。


前言:

本系列博客将会更新一些每日的刷题代码以及对题目的解读,帮助大家更好地理解编程思路和实现方法


文章目录

  • 前言:
  • 题目:
    • 1. n的阶乘
    • 2. 打印一个整数的每一位
    • 3. 交换两个变量(不创建临时变量)
    • 4. 统计二进制中1的个数
    • 5. 求两个数二进制中不同位的个数
    • 6. 单身狗1
    • 7. 打印整数二进制的奇数位和偶数位
  • 知识点
    • 1. 右移操作符
      • 1.1. 逻辑右移(Logical Right Shift)
      • 1.2 算术右移(Arithmetic Right Shift)
      • 1.3 关键区别总结
      • 1.4 C 语言中的右移规则


题目:

1. n的阶乘

  • 递归和非递归分别实现求n的阶乘(不考虑溢出的问题)

阶乘的定义是n! = n × (n-1) × … × 1,其中0!和1!都为1。下面分别用递归和循环(非递归)的方式实现:

//递归和非递归分别实现求n的阶乘(不考虑溢出的问题)
#include<stdio.h>
//递归实现:将大问题分解为规模更小的子问题,直到达到终止条件
int fact(int n)
{//终止条件:1的阶乘是1,2的阶乘是2(也可简化为n<=1时返回1)if (n == 1 || n == 2){return n;}else{//递归公式:n! = n × (n-1)!return n * fact(n - 1);}
}int main()
{//测试递归实现,计算6的阶乘printf("%d\n", fact(6));//循环(非递归)实现:通过迭代累乘得到结果int n = 6;int facter = 1; //初始化乘积为1(乘法的单位元)while (n > 0){facter *= n; //累乘当前值n--; //逐步减小数值,直到n变为0}printf("%d\n", facter);return 0;
}

2. 打印一个整数的每一位

  • 递归方式实现打印一个整数的每一位

要打印一个整数的每一位(如951打印为9 5 1),可以通过递归不断提取高位数字,直到剩下最后一位时开始打印,从而实现从高位到低位的输出。

//递归方式实现打印一个整数的每一位
#include<stdio.h>
//递归实现:先处理高位,再打印当前位
void print(int n)
{//终止条件:如果n是个位数,直接打印if (n < 10){printf("%d ", n);}else{//先递归处理去掉最后一位的数(获取高位)print(n / 10);//再打印最后一位(通过取余10得到)printf("%d ", n % 10);}
}int main()
{//测试:打印951的每一位print(951); //输出结果:9 5 1 return 0;
}

3. 交换两个变量(不创建临时变量)

  • 不允许创建临时变量,交换两个整数的内容

通常交换两个变量需要借助临时变量,这里利用异或()的特性实现无临时变量交换。异或的特点是:aa=0,a^0=a,且满足交换律和结合律。

#include <stdio.h>
int main()
{int a = 6;int b = 12;printf("交换前:a=%d b=%d\n", a, b);//第一步:a存储a和b的异或结果(a^b)a = a ^ b;//第二步:b = (a^b) ^ b = a ^ (b^b) = a ^ 0 = a(此时b的值变为原来的a)b = a ^ b;//第三步:a = (a^b) ^ a(新b是原a)= (原a^原b) ^ 原a = 原b ^ (原a^原a) = 原b ^ 0 = 原ba = a ^ b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}

4. 统计二进制中1的个数

  • 二进制中1的个数

统计二进制中1的个数可以利用位运算的技巧:n & (n-1) 会消除n二进制中最后一个1。通过循环执行该操作,直到n变为0,执行的次数就是1的个数。

//写一个函数返回参数二进制中 1 的个数。
//比如: 15    0000 1111    4 个 1
#include<stdio.h>
void Count(int n)
{int count = 0; //计数器,记录1的个数while (n != 0){//n & (n-1) 会消除n的二进制中最后一个1n = n & (n - 1);count++; //每消除一个1,计数器加1}printf("%d\n", count);
}int main()
{int n = 0;scanf("%d", &n); //输入一个整数Count(n); //统计并打印该整数二进制中1的个数return 0;
}

5. 求两个数二进制中不同位的个数

  • 编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?

输入例子:

  • 1999 2299

  • 输出例子:7

关键思路是利用异或(^)操作:两个数异或后,结果的二进制中,1的位置就是两个数二进制不同的位置。因此,只需统计异或结果中1的个数即可。

#include <stdio.h>//统计一个数二进制中1的个数(复用第4题的逻辑)
int Count(int n)
{int count = 0;while (n != 0){n = n & (n - 1);count++;}return count;
}int main() {int a, b;//循环读取输入,直到文件结束(EOF)while (scanf("%d %d", &a, &b) != EOF) { //a^b的结果中,1的位置即为a和b二进制不同的位置int c = a ^ b;//统计c中1的个数,即为不同位的数量int count = Count(c);printf("%d\n", count);}return 0;
}

6. 单身狗1

  • 在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。
  • 例如:

数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5

这里使用双重循环的暴力解法:遍历每个元素,统计其在数组中出现的次数,次数为1的即为目标数字。(更优的解法可以利用异或特性:aa=0,0a=a,将所有元素异或后结果即为只出现一次的数字)

//在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。
//数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5
#include <stdio.h>
int main()
{int arr[] = { 1,2,3,4,5,5,4,6,3,2,1 }; //示例数组,6是只出现一次的数字int sz = sizeof(arr) / sizeof(arr[0]); //计算数组元素个数//遍历数组中的每个元素for (int i = 0;i < sz;i++){int count = 0; //统计当前元素出现的次数//再次遍历数组,计数与当前元素相等的元素个数for (int j = 0;j < sz;j++){if (arr[i] == arr[j]){count++;}}//如果次数为1,说明找到目标数字if (count == 1)printf("%d",arr[i]);}return 0;
}

7. 打印整数二进制的奇数位和偶数位

  • 获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

整数的二进制位从右向左(即从低位到高位)编号,最右边为第1位(奇数位),第2位为偶数位,以此类推。通过循环取余和除法提取每一位,分别存入奇数位和偶数位的数组,最后打印即可。

//获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
#include <stdio.h>
void print(int n)
{int count = 0; //记录当前是第几位(从1开始)int arr1[16] = {0}; //存储奇数位(第1,3,5,...位),int型共32位,故最多16个奇数位int arr2[16] = {0}; //存储偶数位(第2,4,6,...位),最多16个偶数位while (n != 0){int m = n % 2; //提取当前最低位(0或1)count++; //位数加1//判断当前位是奇数位还是偶数位,存入对应数组if (count % 2 != 0) //奇数位(第1,3,5...位){arr1[(count - 1)/2] = m; //计算存储位置(0,1,2...)}else //偶数位(第2,4,6...位){arr2[count/2 -1] = m; //计算存储位置(0,1,2...)}n = n / 2; //移除已经处理的最低位}//打印奇数位(从右向左,即从第1位开始)printf("奇数位,从右向左依次:");for (int i = 0;i < 16; i++){printf("%d ", arr1[i]);}printf("\n");//打印偶数位(从右向左,即从第2位开始)printf("偶数位,从右向左依次:");for (int i = 0;i < 16; i++){printf("%d ", arr2[i]);}
}int main()
{print(0b1111); //测试二进制1111(十进制15),其奇数位为1,1,偶数位为1,1return 0;
}

知识点

1. 右移操作符

在计算机中,右移运算(>>)是对二进制位的操作,根据处理符号位的方式不同,分为逻辑右移算术右移,二者的核心区别在于移位后左侧空出的位如何填充。下面详细讲解:

1.1. 逻辑右移(Logical Right Shift)

  • 规则:不管原数是正数还是负数,右移时左侧空出的位一律用 0 填充,右侧超出边界的位直接丢弃。
  • 适用场景:通常用于无符号整数(unsigned),因为无符号数没有符号位,仅表示数值大小。
  • 示例
    以 8 位二进制为例,对无符号数 0b10110100(十进制 180)进行逻辑右移 2 位:
    原二进制:10110100
    右移 2 位后:00101101(左侧补 0,右侧丢弃最后 2 位)
    结果为十进制 45

1.2 算术右移(Arithmetic Right Shift)

  • 规则:右移时,左侧空出的位用原数的符号位(最高位)填充,右侧超出边界的位直接丢弃。

    • 若原数是正数(符号位为 0),则左侧补 0;
    • 若原数是负数(符号位为 1),则左侧补 1。
  • 适用场景:主要用于有符号整数(signed),目的是保持移位后数值的符号不变(即移位后与原数同号),且近似于“除以 2 的 n 次方”(向下取整)。

  • 示例
    ① 正数右移:8 位有符号数 0b00110100(十进制 52)算术右移 2 位:
    原二进制:0 0110100(符号位为 0)
    右移 2 位后:0 0001101(左侧补符号位 0)
    结果为十进制 13(52 ÷ 4 = 13,符合预期)。

    ② 负数右移:8 位有符号数 0b11001100(十进制 -52,补码表示)算术右移 2 位:
    原二进制:1 1001100(符号位为 1)
    右移 2 位后:1 1110011(左侧补符号位 1)
    结果为十进制 -13(-52 ÷ 4 = -13,符合预期)。

1.3 关键区别总结

类型左侧填充值适用数据类型核心目的
逻辑右移固定填充 0无符号整数(unsigned)仅移动位,不考虑符号
算术右移填充原符号位有符号整数(signed)保持符号不变,近似除以 2ⁿ

1.4 C 语言中的右移规则

C 语言标准没有明确规定有符号数的右移是逻辑右移还是算术右移,具体由编译器实现(大多数编译器对有符号数采用算术右移,对无符号数采用逻辑右移)。例如:

int a = -52;       // 二进制补码:11111111 11111111 11111111 11001100(32位)
a = a >> 2;        // 算术右移后:11111111 11111111 11111111 11110011(结果为 -13)unsigned int b = 180; // 二进制:00000000 00000000 00000000 10110100
b = b >> 2;           // 逻辑右移后:00000000 00000000 00000000 00101101(结果为 45)

因此,在处理有符号数的右移时,需注意编译器的行为,避免依赖未定义的操作。


  • 本节完…
http://www.dtcms.com/a/611859.html

相关文章:

  • GPT‑5.1 全面解析:智能与人性化的再平衡
  • Windows 11 无线网卡故障排查
  • 潍坊网站建设尚荣青岛市专业做网站的吗
  • GJOI 11.11 题解
  • C语言编译器 | 如何选择适合自己的编译器进行开发
  • 广东省交通建设监理检测协会网站怎么做自己的网站赚钱
  • (论文速读)AIMV2:一种基于多模态自回归预训练的大规模视觉编码器方法
  • 蓝牙 Prmary PHY LE Coded 收发测试发送没问题,但接收不到,是否是硬件不支持
  • 网站备案需要多少时间企业建设网站应如何申请
  • 商城网站建设公司报价番禺制作网站技术
  • 电商网站开发研究内容和预期成果扬中市人才网官网
  • 天保建设集团有限公司网站天津多媒体设计公司
  • 重庆网捷网站建设技术有限公司wordpress如何设置关键词
  • 舞美设计制作公司sem与seo的区别
  • 数字营销软件逆冬seo
  • 网站整站下载带数据库后台的方法大连百度推广公司有几家
  • 数学分析简明教程——4.2
  • 物联网网站开发网站建设一般用英文怎么说
  • 红旗渠建设集团有限公司网站注册一个公司网站的费用
  • 台州网站关键字优化详情网络销售是做什么的
  • 学校网站建设答辩php 5.4 wordpress
  • AI大模型参数
  • 数据库练习查询5
  • wordpress摘要开启做网站建设优化的公司
  • 中国建设招标网是什么网站有没有做美食的规模网站
  • 网站制作计划可以做兼职的网站
  • 网站开发需要哪些能力公众号关注推广
  • 四川省城市建设培训中心 网站义乌开锁做网站哪个好
  • 做网站上传服务器品牌设计包括哪些方面
  • 外贸高端网站开发wordpress 广告 插件