操作符这块,你可得把握住(中)

简介: 操作符这块,你可得把握住(中)

3.程序题:求一个整数的二进制序列中有多少个1

方法1:

使用计数器变量count,让每一位二进制位分别移到最后面,与上1->如果相与之和的结果为1,count++


如何让每一位二进制位分别移到最后面?

-> 按位右移把每一个位都得到进行判断

->int :4个字节,->32位->右移32次

用循环:右移0位(此时为二进制序列最后一位)开始,到右移31位


此种写法对于负数也可以


int main()
{
    int count = 0;
    int i = 0;
    int n = 0;
    scanf("%d",&n);
    for(i = 0;i < 32; i++)
    {
        //写法1:
        // n>>i  :右移i位
        if( ((n>>i) & 1 )== 1)
        {
            count++;
        }
        //写法2
        int b = 0;
        b = n &1;
        if(b == 1)
        {
            count++;
        }
        n = n>>1; 
        //n先与1进行判读, 再右移一位
    }
    printf("%d的二进制序列中,1的个数为:%d\n",n,count);
    return 0;
}
复制代码


方法2:n &(n-1)

每进行一次可以去掉n中二进制序列中最后一位比特位

此种方法对于负数也适用


int count_bit(int n )
{
    int count = 0;
    while(n)
    {
          count ++; 
         n = n&(n-1); //将n&(n -1)得到的值赋给n
    }
    return count;
}
int main()
{
    int n = 0;
    scanf("%d",&n);
    int count = count_bit(n);
    printf("%d的二进制序列中共有%d个1\n",n,count);
    return 0;
}
复制代码


4.计算一个数是否为2的次方数

方法:n &(n-1)


n&(n-1):去掉二进制序列中最后一个1
 对于2的次方数,二进制序列中只有一个1
    如4: 0000 0100
      8: 0000 1000
    如果n&(n-1)为0,那么就是2的次方数
复制代码
//如果是2的次方数就返回1,不是返回0
int is_power_2(int n)
{
   // if(n &(n-1) == 0)  
    //ERR写法  原因:==的优先级比&高,有可能先算(n-1)==0 ,所以应该前面的东西括起来和0比较
    if((n & (n-1)) == 0)
    {
        //n就是2的次方数
          return 1;
    } 
    else
    {
        return 0;
    }
}
int main()
{
    int n = 0;
    printf("输入操作数:\n");
    scanf("%d",&n);
    int ret = is_power_2(n);
    ////如果n是2的次方数  ret=1,不是,ret = 0
    if(ret)
    {
          printf("%d是2的次方数\n",n);
    }
    else
    {
         printf("%d不是是2的次方数\n",n);
    }
    return 0;
}
复制代码


5.交换变量a,b的值

01:采用临时变量


int main()
{
    int a = 0;
    int b =0;
    scanf("%d %d",&a,&b);
    printf("before:a = %d b = %d\n",a,b);
    //交换
    int tmp = a;
    a = b;
    b = tmp;
    printf("before:a = %d b = %d\n",a,b);
    return 0;
}
复制代码
//写成函数的形式->传址
//若传值,形参是实参的一份临时拷贝,对形参的改变不影响实参
void Swap(int* pa,int* pb)
{
    int tmp = *pa;
    *pa = *pb;
    *pb = tmp;
}
int main()
{
    int a = 0;
    int b =0;
    scanf("%d %d",&a,&b);
    printf("before:a = %d b = %d\n",a,b);
    Swap(&a,&b);
    //Swap(a,b);  ---err
     printf("before:a = %d b = %d\n",a,b);
    return 0;
}
复制代码


02:不采用临时变量
方法1:


int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d",&a,&b);
    printf("before:a = %d b = %d\n",a,b);
    a = a + b;  //a存放a+b的和
    b = a - b;  //和 - b就是原来的a
    a = a - b;  //现在b存放的是a的值,和 - a就是原来的b
    printf("after:a = %d b = %d\n",a,b);
    return 0;
}
复制代码


缺陷:当a,b的值过大时,c = a+ b 可能会溢出



方法2 -- 不采用临时变量


a^b -得到密码 
密码^b -> 原来的a  
密码^a  ->原来的b
异或:a^a ->0
0^a ->a  所以a^a^b 结果是:b  
a^b^a 结果是  b
 结论:异或是支持交换律的
复制代码
//使用异或
int main()
{
  int a = 0;
    int b = 0;
    scanf("%d %d",&a,&b);
    printf("before:a = %d b = %d\n",a,b);
    //异或
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("after:a = %d b = %d\n",a,b);
    return 0;
}
//记忆方法: 左边  a b a 右边:a^b
复制代码


缺点:但是代码可读性不高,同时该代码只适用于整形




=  赋值操作符


int main()
{
    int a = 10;
    int x = 0;
    int y = 20;
    a = x = y+1;
    //把y+1的值赋给x, 再把x=y+1的值赋给a
    printf("%d\n",a);//21
    printf("%d\n",x);//21
    return 0;
}
复制代码


&   取地址操作符


& :取出的是低地址
复制代码

int main()
{
    int a = 10;
    int* p = &a;
    int b = *p;  
    //对指针解引用就是指针指向的内容
    // p存放的是a的地址,所以 *p 就是a
    *p = 20;  //把p指向空间的值改成20
    printf("%d\n",a); //20
    return 0;
}
复制代码

int a = 200;
int c = b;  //b为右值, 把 b指向空间的内容 赋给c
b = 1000; //b为左值,使用的是b的空间  把1000放到b的空间里
复制代码


sizeof()操作符


sizeof()是计算类型或者变量所占内存空间的大小,单位是字节 。和内存中存放什么数据没有关系 
注意:sizeof是操作符,不是函数
复制代码

如:


char arr[10] = "abc";
printf("%d\n",sizeof(arr));
//是10 不是3 
//和内存存放的数据无关,计算的是数组的大小, 数组名单独放在sizeof内部,计算的是整个数组的大小
复制代码


证明sizeof()不是函数


int main()
{
    int a = 10;
    int ret = sizeof(a);
    int ret2 = sizeof a;
    int ret3 = sizeof(int);
   // int ret4 = sizeof int;   err
    printf("%d %d %d\n",ret,ret2,ret3); // 4  4  4
    return 0;
}
复制代码


不可以写成sizeof int   但是可以写成sizeof (int)

而sizeof a 和sizeof (a)都可以

由此可以证明 sizeof() 不是函数  因为函数一定要加括号调用 如Add(x,y);




sizeof对于变量:可以省略括号,但是对于变量类型不可以省略

sizeof()内部的表达式不参与真实运算

如:下例子, sizeof内部写的是赋值表达式也不会真实赋值


int main()
{
    int a = 1;
    int ret = sizeof(a = a +1); //sizeof计算的是赋值之后的结果的类型,相当于sizeof(2) = 4
    printf("%d %d\n",a,ret);// 1 4 
    return 0;
}
复制代码

int a = 5;
short s = 10;
printf("%d\n",sizeof(s = a+2)); //2
printf("%d\n",s); //10
复制代码


a是int类型 4个字节,放到short变量s中, short:2个字节,会发生截断,只取a中低地址的两个字节 最后sizeof计算的是s的大小,s为short类型,所以大小为2

相关文章
|
6月前
高等数学II-知识点(1)——原函数的概念、不定积分、求原函数的两种常用方法 (凑微分法、第二换元法)、分部积分法、有理函数原函数求法、典型三角函数原函数求法
高等数学II-知识点(1)——原函数的概念、不定积分、求原函数的两种常用方法 (凑微分法、第二换元法)、分部积分法、有理函数原函数求法、典型三角函数原函数求法
177 1
|
7月前
|
机器学习/深度学习 算法 测试技术
青蛙跳台阶:我如何得知它是一道斐波那契数列题?——应用题破题“三板斧”(二)
这篇内容是关于解题策略的,主要介绍了在面对应用题时可以采用的“三板斧”方法:举例、模拟和找规律。通过一个走楼梯的例子详细解释了这三个步骤如何运用。首先,举例将抽象问题具体化,比如走5级台阶有几种方式。其次,通过模拟不同情况,例如思考走每一步的可能,发现递归或循环的模式。最后,通过找规律归纳出一般性的解决方案,这里发现走台阶问题与斐波那契数列相关。文章还提到了一个拓展案例——矩形覆盖问题,同样可以用类似的方法分析。总的来说,文章强调了解题过程中理解和转化问题的重要性,以及通过训练提升这方面能力。
62 0
|
7月前
|
C语言
青蛙跳台阶:我如何得知它是一道斐波那契数列题?——应用题破题“三板斧”(一)
这篇内容介绍了C语言学习中的经典例题——斐波那契数列,强调了解题思路的重要性。斐波那契数列是一个数列,其中每个数是前两个数的和。文章指出,很多类似题目,如“青蛙跳台阶”,实质上都在考察斐波那契数列的实现。文中提供了斐波那契数列的定义、代码实现和递归与非递归的思路,并鼓励读者从问题中分析出解题模型,而非直接套用已知方法。此外,还提及了一道相关题目“矩形覆盖问题”,以供进一步练习。
61 0
|
7月前
|
测试技术
【一刷《剑指Offer》】面试题 9:斐波那契数列(扩展:青蛙跳台阶、矩阵覆盖)
【一刷《剑指Offer》】面试题 9:斐波那契数列(扩展:青蛙跳台阶、矩阵覆盖)
|
7月前
|
存储 算法 搜索推荐
C语言第二十九练 三分算法求峰值
C语言第二十九练 三分算法求峰值
77 1
|
算法 C语言
面试 | 移位妙解递归乘法【细节决定成败】
面试 | 移位妙解递归乘法【细节决定成败】
56 0
|
算法 索引
代码随想录训练营day34| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果...
代码随想录训练营day34| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果...
100 0
|
算法 C语言
07【C语言 & 趣味算法】最佳存款方案(采用 从后往前 递推解决)
07【C语言 & 趣味算法】最佳存款方案(采用 从后往前 递推解决)
07【C语言 & 趣味算法】最佳存款方案(采用 从后往前 递推解决)
|
编解码 人工智能 C++