c语言做题记录

👍👍👍写在前面的话

❤️❤️❤️技能的精通不是一蹴而就的成功,也不是信手拈来的辉煌,需要不断的更新自己的知识,并不断的加以有效的练习来巩固自己目前所学习到的知识。读了这么有料的毒鸡汤,我们还是步正题——c语言的小练习。目的就是为了实践一下这句毒鸡汤,巩固一下目前所学习到的知识! 🐣🐣🐣practice makes perfect!🐣🐣🐣

img

👍👍👍👍第一题:操作符的基本认识

第 1 题(单选题)

题目名称:

下面哪个是位操作符:( )

题目内容:

A .&

B .&&

C .||

D .!

c语言之所以灵活,操作符的功劳可不小,小编理解比较深刻的就是位操作符了,直接去对二进制位进行操作,这可能是就是java这种封装的很好的语言所做不到的。废话不多说,看上一题的详情吧:

A. & 是按位与操作符,位操作符还有按位货,按位异或哦。

B. && 是逻辑与,不是按位与,这两个是有很大区别的。

C. || 是逻辑或,这个和上一个是亲兄弟;他们主要是负责逻辑的判断的,一个有意思的点是他们会发生短路现象。&&如果第一个表达式结果为假,第二个表达式则不会执行;||如果第一个表达式为真,第二个表达式为也不会执行。相信很多小伙伴也被坑过很多次了。

D. ! 是逻辑反操作符,错误

那么这些操作符具体是干什么的了?也许有很多小伙伴会很迷惑😒,后面小编会进行详细的总结哦,关注我不迷路,一起加油哦😊😊😊😊

img

👍👍👍👍👍第二题:基本的运算

题目名称:

下面代码的结果是:( )

#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

这一题主要考察了操作符的基本使用。

#include <stdio.h>
int main()
{
	int a, b, c;
	a = 5;
	c = ++a;// ++a:加给a+1,结果为6,用加完之后的结果给c赋值,因此:a = 6  c = 6
	b = ++c, c++, ++a, a++;
   // 逗号表达式的优先级,最低,这里先算b=++c, b得到的是++c后的结果,b是7
   // b=++c 和后边的构成逗号表达式,依次从左向右计算的。
   // 表达式结束时,c++和,++a,a++会给a+2,给c加1,此时c:8,a:8,b:7
	b += a++ + c; // a先和c加,结果为16,后缀++优先级比+=高,所以a先加1,在加上b的值7,b的结果为23,a的值为9
	printf("a = %d b = %d c = %d\n:", a, b, c); // a:9, b:23, c:8
	return 0;
}

💖友情提示:如果记不得a,b,c分别的值,可以列出一个表格,在每执行一次之后就更新值,这样是一定不会错的;

操作abc
main函数栈帧创建未创建未创建未创建
int a, b, c;随机值随机值随机值
a = 5;5随机值随机值
c = ++a;(++a:加给a+1,结果为6,用加完之后的结果给c赋值)6随机值6
b = ++c677
c++678
++a778
a++878
b += a++ + c;9238
printf(“a = %d b = %d c = %d\n:”, a, b, c);9238
return 0;销毁销毁销毁

怎么样,这样看起来是不是清晰的一塌糊涂,当然提及到了一些函数栈帧的知识,感兴趣的小伙伴可以研究一下哦。

👍👍👍👍👍👍第三题:求两个数二进制中不同位的个数

题目名称:

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

题目内容:

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

输入例子:

1999 2299

输出例子:7

冥思一想,可知万千道来,当然我采用的是大家都能想到比较挫的方法,整体思路如下:

1.通过数字1不断左移与m,n进行&操作,如果结果为0,说明这个位置比对的数值为0,反之则为1,对两个数比对的结果进行标记,最后比对两个数的标记是否相同,如果不相同则count++
2.通过左移并赋值给c,继续上面的操作,就能达到目的,可能这方法比较挫,相信小伙伴们还有其它更加巧妙的方法。

具体代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
/*
1.通过数字1与m,n进行&操作,如果结果为0,说明这个位置比对的数值为0,反之则为1,对两个数比对的结果进行标记,最后比对两个数的标记是否相同,如果不相同则count++
2.通过左移并赋值给c,继续上面的操作,就能达到目的*/
int differences(int m, int n) {
	int count = 0;
	int c = 1;
	for (int i = 0; i < 32; i++) {
		int markm = 0;
		int markn = 0;
		if ((m & c) == 0) {
			markm = 0;
		}
		else {
			markm = 1;
		}
		if ((n & c) == 0) {
			markn = 0;
		}
		else {
			markn = 1;
		}
		if (markm == markn) {
			c <<= 1;
		}
		else {
			c <<=1;
			count++;
		}
	}
	return count;
}
int main() {
	int m = 0;
	int n = 0;
	scanf("%d%d", &m, &n);
	int ret=differences(m, n);
	printf("%d和%d在32位环境下二进制的不同位数位:%d",m,n,ret);
	return 0;
}

vs2019测试结果:

img

可以看到我们的输出结果是和题目吻合的。当然还有其它的思路,比如:

1. 先将m和n进行按位异或,此时m和n相同的二进制比特位清零,不同的二进制比特位为1
2. 统计异或完成后结果的二进制比特位中有多少个1即可

这个思路好像更简单哦,代码实现起来也更easy,小编则是用到了更多的一些位操作知识,才能达到熟悉知识的操作,后面这种思路大家可以动手实践一下哦!我试过也是能够实现的,相信你们比我更快的写出来的,保持空杯心态,才能学到更多的细节,加油!(●’◡’●)

👍👍👍👍👍👍👍第四题:打印整数二进制的奇数位和偶数位

题目名称:

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

题目内容:

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

和上题思路大致类似,只不过这一次我们是把二进制数字判断以后分别存进不同的数组中。

1.通过1与该对应位置进行&操作,如果等于0,则存0,如果等于1,则存1;

2.右移1并复制给c,继续执行1的操作,并设置flag,判断是应该存在哪个数组中;

3.判断完成,输出两个数组中的值;(逆序输出)

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void showarr(int* arr, int sz) {
	for (int i = sz-1;i>=0;i--) {
		printf("%d", arr[i]);
	}
	printf("\n");
}
int main() {
	int k = 0;
	int c = 1;
	int m = 0;
	int n = 0;
	int jishu[50];
	int oushu[50];
	printf("请输入要检查的值:\n");
	scanf("%d", &k);
	int flag = 0;//定义标记,用来区分存入什么数组中
	for (int i = 0;i < 32;i++) {
		if (flag == 0) {
			if ((k & c) == 0) {
				jishu[m++] = 0;
				c <<= 1;
			}
			else {
				jishu[m++] = 1;
				c <<= 1;
			}
			flag = 1;
			continue;
		}
		if (flag == 1) {
			if ((k & c) == 0) {
				oushu[n++] = 0;
				c <<= 1;
			}
			else {
				oushu[n++] = 1;
				c <<= 1;
			}
			flag = 0;
		}
	}
	printf("奇数:");
	showarr(jishu, m);
	printf("偶数:");
	showarr(oushu, n);
	return 0;
}

vs2019实测:img

做多了,就会发现一个技巧,c<<=1是个万金油了,位操作就会想到它了,这难道条件反射了吗?哈哈,开个玩笑,来看下一题哦。

👍👍👍👍👍👍👍👍第五题:统计二进制中1的个数

题目名称:

统计二进制中1的个数

题目内容:

写一个函数返回参数二进制中 1 的个数。

比如: 15 0000 1111 4 个 1

这里的方法就很多了,提供一下几种方法吧:

方法一:
思路:
循环进行以下操作,直到n被缩减为0:
1. 用该数据模2,检测其是否能够被2整除
2. 可以:则该数据对应二进制比特位的最低位一定是0,否则是1,如果是1给计数加1
3. 如果n不等于0时,继续1

上述方法缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。

方法二思路:
一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测,

方法二优点:用位操作代替取模和除法运算,效率稍微比较高

缺陷:不论是什么数据,循环都要执行32次

方法三:
思路:采用相邻的两个数据进行按位与运算

我采用的是第二种思路写的代码,毕竟前面说到已经形成条件反射的想到了c<<=1。

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int many_times(int n) {
	int c = 1;
	int count = 0;
	for (int i = 0;i < 32;i++) {
		if ((n & c) == 0) {
			c <<= 1;
		}
		else {
			count++;
			c <<= 1;
		}
	}
	return count;
}
int main() {
	int n = 0;
	printf("请输入一个数字:\n");
	scanf("%d", &n);
	int ret = many_times(n);
	printf("%d中有%d个1!", n, ret);
	return 0;
}

vs2019实测:img

👍👍👍👍👍👍👍👍第六题:交换两个变量(不创建临时变量)

题目名称:

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

题目内容:

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

其实这道题是有两种解法的,我们日常使用的

int temp = m;
	m = n;
	n = temp;

这种样式的代码,应为创建了临时变量temp,不满足题目的要求;有小伙伴可能会提出这样的代码:

    m = m + n;
	n = m - n;
	m = m - n;

这样确实能够实现交换并且满足题目要求,我们来看一下:

操作mn
m = m + n;m+nn
n = m - n;m+nm
m = m - n;nm

看懂了吗,这样实现简单的加减操作之后,也能实现交换操作,但是这样真的没啥问题吗,之前学过的二分查找哪里我们寻找中间坐标时,为什么不采用(left+right)/2这样的形式了,应为一个有符号的int表示的范围是-2* 31~2* 31-1这样的数字,当我们使用直接相加的方式可能会造成溢出的情况,就会引起数据丢失。这里也是一样的道理哦,所以这种方法存在一定的风险。

也许下一张就是王牌哦:

    m = m ^ n;
	n = m ^ n;
	m = m ^ n;

这里的思想和2感觉是有点类似的,把m^n存到m中,可以理解成把m,和n的差异存起来;

操作mn
m = m^ n;m和n的差异n
n = m ^n;m和n的差异m
m = m ^ n;nm

第二步m和n的差异在去和n进行^运算,差异再和n去找差异,是不是就是m了,再赋值给m;下一步同理!

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int m = 0;
	int n = 0;
	scanf("%d%d", &m, &n);
	//方法一:
	printf("交换前:m=%d,n=%d\n", m, n);
	int temp = m;
	m = n;
	n = temp;
	printf("交换后:m=%d,n=%d\n", m, n);
	//方法二
	printf("交换前:m=%d,n=%d\n", m, n);
	m = m + n;
	n = m - n;
	m = m - n;
	printf("交换后:m=%d,n=%d\n", m, n);
	//方法三
	printf("交换前:m=%d,n=%d\n", m, n);
	m = m ^ n;
	n = m ^ n;
	m = m ^ n;
	printf("交换后:m=%d,n=%d\n", m, n);
	return 0;
}

vs2019实测:img

👍👍👍总结

念念不忘,必有回响,知识也一样,时常想起积累的小知识点,总有一天你会发现自己的思维居然真的能实现成代码,但在实现的路上可能会有无数bug,这也是见怪不怪的,哈哈。但总的来说就是思维不清晰或者基础知识不扎实,前者靠锻炼,后者靠积累,大家加油!最后关注小编不迷路,后期不定时更新c的知识哦!img

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WindFall1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值