C语言操作符例题

这里写目录标题

  • 例题一
    • 题目解析
  • 例题二
    • 题目解析
  • 例题三
    • 方法一
    • 方法二
    • 方法三
  • 例题四
  • 例题五

感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐓🏀 python

例题一

下面代码的结果是:( )

#include <stdio.h>
int main()
{
	int a, b, c;
	a = 5;
	c = ++a;
	b = ++c, c++, ++a, a++;
	b += a++ + c;
	printf("a = %d b = %d c = %d\n:", a, b, c);
	return 0;
}

A.a = 8 b = 23 c = 8
B.a = 9 b = 23 c = 8
C.a = 9 b = 25 c = 8
D.a = 9 b = 24 c = 8

答案 B

题目解析

c=++a是先执行++a,也就是a=a+1=6(注意这里是永久改变a的值),然后再执行c=a=6
b=++c,c++,++a,a++这里要注意对于b我们是只算b=++c,所以先执行c=c+1=7
b=c=7,然后再执行后面的c++,++a,a++(后面还是会执行的,只不过和b就没关系了),最终c=8.a=8
b+=a++ +c先变成b=b+a++ +c再执行a=a+1=9,b=b+a+c=7+8+8=23
最终a=9 b=23 c=8

例题二

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

题目解析

我们需要用到按位异或的方法去解决,按位异或在之前我有写到操作符详解上(非常详细)

#include <stdio.h>
int main()
{
	int a = 10;
    int b = 20;
    printf("交换前:a = %d b = %d\n", a,b);
    a = a^b;
    b = a^b;
    a = a^b;
    printf("交换后:a = %d b = %d\n", a,b);
	return 0;
}

按位异或就是相同为0不同为1,并且满足数学的交换规律
对于
一式a=a^b ,二式b=a^b, 三式a=a^b
我们将一式带入二式,b=a^ b^b,由于b ^b=1,那么最后b=a
而三式a=a^b其实就是a=a ^b ^a,其中a ^b是一式带入的,利用交换律我们就可以变成a=a ^a ^b,所以最后a=b

例题三

统计二进制中1的个数
代码解析:

方法一

*/
int NumberOf1(int n)
{
	int count = 0;
	while(n)
	{
		if(n%2==1)
			count++;
		n = n/2;//每次除2然后循环判断
	}
	return count;
}
/*

上述方法缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。
我们看看另外一个思路
一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测,具体如下

方法二


*/
int NumberOf1(unsigned int n)
{
	int count = 0;
	int i = 0;
	for(i=0; i<32; i++)
	{
		if(((n>>i)&1) == 1)
			count++;
	}
	return count;
}

int NumberOf1(int n ) {
    int j=0;
    for(int i=1;i<=32;i++)
    {
        if(n%2)//如果n%2为1就代表个位是1(这里不用判断十位百位)
        {
            n=n>>1;
            j++;
        }
        else(如果个位是0就直接右移)
            n=n>>1;
    }
    printf("%d",j);
    return j;
}

/*
  优点:用位操作代替取模和除法运算,效率稍微比较高
  缺陷:不论是什么数据,循环都要执行32次
  

方法三

思路:采用相邻的两个数据进行按位与运算
举例:‬
第一次循环:n=9999  
n=n&(n-1)=9999&9998=9998
(10 0111 0000 1111)
(10 0111 0000 1110) 
=(10 0111 0000 1110) 
第二次循环:n=9998 
 n=n&(n-1)=9998&9997= 9996
 (10 0111 0000 1110) 
 (10 0111 0000 1101) 
 =(10 0111 0000 1100) 
第三次循环:n=9996 
n=n&(n-1)=9996&9995= 9992
(10 0111 0000 1100) 
(10 0111 0000 1011) 
=(10 0111 0000 1000) 
第四次循环:n=9992   
n=n&(n-1)=9992&9991= 9984
(10 0111 0000 1000) 
(10 0111 0000 0111)
=(10 0111 0000 0000)
第五次循环:n=9984
n=n&(n-1)=9984&9983= 9728
(10 0111 0000 0000)
(10 0110 1111 1111)
=(10 0110 0000 0000)
第六次循环:n=9728   
n=n&(n-1)=9728&9727= 9216
(10 0110 0000 0000)
(10 0101 1111 1111)
=(10 0100 0000 0000)
第七次循环:n=9216   
n=n&(n-1)=9216&9215= 8192
(10 0100 0000 0000)
(10 0011 1111 1111)
=(10 0000 0000 0000)
第八次循环:n=8192   
n=n&(n-1)=8192&8191= 0
(10 0000 0000 0000)
(01 1111 1111 1111)
=(00 0000 0000 0000)


可以观察到:此种方式,数据的二进制比特位中有几个1,循环就循环几次
而且中间采用了位运算,处理起来比较高效
*/
int NumberOf1(int n)
{
	int count = 0;
	while(n)
	{
		n = n&(n-1);
		count++;
	}
	return count;
}

例题四

打印整数二进制的奇数位和偶数位
代码解析:

/*
思路:
1. 提取所有的奇数位,如果该位是1,输出1,是0则输出0
2. 以同样的方式提取偶数位置


 检测num中某一位是0还是1的方式:
   1. 将num向右移动i位
   2. 将移完位之后的结果与1按位与,如果:
      结果是0,则第i个比特位是0
      结果是非0,则第i个比特位是1
*/
void Printbit(int num)
{
	for(int i=31; i>=1; i-=2)
	{
		printf("%d ", (num>>i)&1);
	}
	printf("\n");
    
	for(int i=30; i>=0; i-=2)
	{
		printf("%d ", (num>>i)&1);
	}
	printf("\n");
}

例题五

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

#include <stdio.h>

int main() {
    int a, b,sum=0;
 scanf("%d %d",&a,&b);
 for(int i=0;i<32;i++)
 {
  int c=a>>i; 
  int d=b>>i;
  if((c&1)==(d&1))判断个位是否相同
  ;
  else
   sum++;

 }
 printf("%d",sum);
    return 0;
}
/*
思路:
1. 先将m和n进行按位异或,此时m和n相同的二进制比特位清零,不同的二进制比特位为1
2. 统计异或完成后结果的二进制比特位中有多少个1即可
*/
#include <stdio.h>
int calc_diff_bit(int m, int n)
{
	int tmp = m^n;//找出相同的位
	int count = 0;
	while(tmp)
	{
		tmp = tmp&(tmp-1);//和上一题的方法三相同
		count++;
	}
	return count;
}
int main()
{
 int m,n;
 while(scanf("%d %d", &m, &n) == 2)
 {
     printf("%d\n", calc_diff_bit(m, n));
 }
 return 0;
}

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月8日
下一篇 2023年12月8日

相关推荐