C语言练习12

1.编写函数: unsigned int reverse_bit(unsigned int value); 这个函数的返回值value的二进制位模式从左到右翻转后的值。

如: 在32位机器上25这个值包含下列各位: 00000000000000000000000000011001
翻转后:(2550136832) 10011000000000000000000000000000 程序结果返回:
2550136832

思路:要翻转整个数字二进制值应该先提取二进制当中的每一位,所以我们选择从左端开始提取,取到值为1的位左移(31-i)位将其翻转,再把这些数相加就可以得到翻转后的整个数

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>


unsigned int reverse_bit(unsigned int value){
	int i = 0;
	unsigned int num = 0;
	for (i = 31; i >= 0; --i){
		unsigned int tmp = (value >> i) & 1;
		if (tmp == 1){
			num = (tmp << (31 - i)) + num;
		}
	}
	printf("%u\n", num);
	value = num;
	return value;
}


int main(){
	unsigned int value = 0;
	reverse_bit(25);
	system("pause");
	return 0;
}

2.不使用(a+b)/2这种方式,求两个数的平均值。

思路:题目不能用两个数相加除以二的传统方式,那我们可以运用按位与操作和按位异或操作来实现这个式子.
将数字a和b都分为两个部分,一部分是窦唯’1’的部分,因为相同所以直接相加即可,另一部分是a为’1’而b为’0’以及a为’0’而b为’1’的部分,两部分相加除以二,与上一个部分相加.

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>

int Average(int a, int b){
	int tmp = (a&b) + ((a^b) >> 1);
	//a&b取出a和b二进制都为'1'的所有位
	//a^b的作用是取出a或b中有'1'的所有位
	//(a^b)>>2这个操作相当于(a^b)/2
	return tmp;
}

int main(){
	printf("请输入数字a b:");
	int ret = 0;
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	ret = Average(a, b);
	printf("a和b的平均数为:%d\n", ret);
	system("pause");
	return 0;
}

3.编程实现: 一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。 请找出这个数字。(使用位运算)

思路:要找到一组数据中只出现一次的数字,我们可以想到用异或的方式,异或的规则如下:
一个数与本身异或结果为0;一个数与0异或结果为其本身.

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>

int main(){
	int arr[5] = { 0 };
	printf("请输入一组数字(5个):");
	for (int i = 0; i < 5; i++){
		scanf("%d", &arr[i]);
	}
	int size = sizeof(arr) / sizeof(arr[0]);
	int tmp = 0;
	printf("单独出现的数字有:");
	
	for (int i = 0; i < size; i++){
		tmp = arr[i];
		int count = 0;
		for (int j = 0; j < size; j++){
			if ((tmp^arr[j]) == 0){
				count++;
			}
		}
		if (count<2){
			printf("%d ", tmp);
		}
	}
	system("pause");
	return 0;
}
  1. 有一个字符数组的内容为:“student a am i”, 请你将数组的内容改为"i am a student". 要求: 不能使用库函数。 只能开辟有限个空间(空间个数和字符串的长度无关)。
    过程:
    student a am i
    i ma a tneduts
    i am a student

思路:第一次想这道题第一步时,也想到了比较下标大小然后交换元素,一下子没想起来怎么实现,拿着ipad画了半天也算编出来了但是很复杂,那段代码留个纪念吧…
Fine这道题我们需要分为两步,先翻转整个数组,再翻转整个数组.
注意,函数声明时需要将数组传入函数,本质上传入的是数组首元素的地址.

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int my_strlen(char* arr){
	int len = 0;
	while (*arr++){//当数组元素不为'\0'时++len,
		//arr的首元素地址进行++来判断arr的元素内容,使用++*str会越界
		++len;
	}
	return len;
}
void reverse(char* start, char* end){
	//当左下标小于右下标时交换两个数
	while (start < end){
		*start = *start^ *end;
		*end = *start^ *end;
		*start = *start^ *end;
		++start;
		--end;
	}
}

int main(){
	char arr[] = "student a am I";
	printf("%s\n", arr);
	char* left = arr;
	char* right = arr;
	//先对整个字符串进行逆置
	reverse(arr, arr + my_strlen(arr) - 1);
	printf("%s\n", arr);
	//再对每个单词进行逆置
	while (*left != '\0'&& *right != '\0'){
		if (*right == ' '){
			reverse(left, right - 1);
			left = right + 1;
		}
		right++;
	}
	reverse(left, right - 1);
	printf("%s\n", arr);

	system("pause");
	return 0;
}
#if 0
int main(){
	//整个字符串的倒置一开始想了很久,发现太复杂了留个纪念
	char arr[] = "student a am i";
	printf("%s\n", arr);
	char tmp[15] = { 0 };
	int my_strlen = (sizeof(arr) / sizeof(arr[0])) - 1;//14
	for (int i = my_strlen - 1; i >= 0; --i){//13
		if (arr[i + 1] == '\0'){
			int a = (my_strlen - 1) - i;
			tmp[a] = arr[i];
			arr[i] = '\0';
		}
	}
	for (int i = 0; i < my_strlen; i++){
		arr[i] = tmp[i];
	}
	printf("%s\n", arr);
	return 0;
}
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值