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;
}
- 有一个字符数组的内容为:“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