1.编写函数:
unsigned int reverse_bit(unsigned int value);
这个函数的返回值是value的二进制位模式从左到右翻转后的值。
如:
在32位机器上25这个值包含下列各位:
00000000000000000000000000011001
翻转后:(2550136832)
10011000000000000000000000000000
程序结果返回:
2550136832
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
unsigned int reverse_bit(unsigned int value)
{
int j = 0;
int tmp = 0;
for (j = 0; j < 32;j++)
{
tmp=tmp+((value >> j) & 1)*pow(2,31-j);//右移之后进行乘以2^(31-j).
}
return tmp;
}
int main()
{
int value = 0;
printf("请输入: ");
scanf("%d", &value);
int ret = 0;
ret =reverse_bit(value);
printf("%u\n",ret);//%u打印无符号十进制整数
system("pause");
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
unsigned int reverse_bit(unsigned int value)
{
int j = 0;
int tmp = 0;
for (j = 0; j < 32; j++)
{
tmp+= ((value >> j) & 1)<<(31-j);//先得到这个数每一位(即通过右移&1),再从得到的二进制最低位依次左移31-j
}
return tmp;
}
int main()
{
int value = 0;
printf("请输入: ");
scanf("%d", &value);
printf("%u\n", reverse_bit(value));//%u打印无符号十进制整数
system("pause");
return 0;
}
2.不使用(a+b)/2这种方式,求两个数的平均值。
//1
#include <stdio.h>
#include <stdlib.h>
int main()
{
double a = 25.0;
double b = 14.0;
double avg= b+(a-b) / 2.0;
printf("%f", avg);
system("pause");
return 0;
}
//2
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10;
int b = 10;
int avg1 = 0;
int avg2 = 0;
avg2 = (b + ((a - b)>>1));// << >> 运算符操作数均为整数
avg1 = (a&b) + (a ^ b)/2;//avg1 = (a&b) + (a ^ b)>>;
printf("avg2= %d\n", avg2);
printf("avg1= %d\n", avg1);
system("pause");
return 0;
}
方法1,2各有优缺点:方法2由于受到操作符限制只能进行整数运算,方法1就可以实现小数之间的avg计算.
3.编程实现:
一组数据中只有一个数字出现了一次。
其他所有数字都是成对出现的。
请找出这个数字。(使用位运算)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[9] = { 1, 2, 3, 4, 4, 3, 1, 2, 5 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int ret = 0;
for (i = 0; i < sz; i++)
{
ret = ret ^ (arr[i]);
}
printf("%d\n", ret);
system("pause");
return 0;
}
4.
有一个字符数组的内容为:"student a am i",
请你将数组的内容改为"i am a student".
要求:
不能使用库函数。
只能开辟有限个空间(空间个数和字符串的长度无关)
分析:
student a am i
i ma a tneduts 字符串整体逆置
i am a student 每个空格处字符串逆置
先将字符串整个逆置,形成i ma a tneduts,
然后利用指针,如果指针指向空白符,说明前边的内容为一个单词然后逆置,
直到指针指向的内容为'\0'的前一项位置,此时字符串则为i am a student.
#include <stdio.h>
#include <stdlib.h>
int my_strlen(char*arr)//定义求字符串长度函数
{
if (arr == NULL)
{
return 0;
}
int cout = 0;
while ('\0' != *arr)
{
cout++;
arr++;
}
return cout;
}
void my_reverse(char *left, char *right) //定义具有逆置字符功能的函数
{
char tmp = NULL;
while (left < right)
{
tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
void reverse_str(char arr[],int sz) //定义逆置字符串的函数
{
char *start = arr;
char *end = arr + sz - 1;
char *curr = NULL;
if ((arr == NULL) || (arr[0] == '\0')) //如果指针为空或者首元素为字符串结束符
{
return; //字符串为空,直接结束程序
}
my_reverse(start, end);
while (*arr) //不为NULL,‘\0’的情况
{
curr = arr;
while ((*arr != '\0') && (*arr != ' ')) //元素不为\0和空白符,说明一个单词还未读取完毕
{
arr++;
}
end = arr - 1; //如果为空白符arr-1说明退至此单词末尾字母处,如果为‘\0' arr-1说明退至字符串结束位置处的前一位
my_reverse(curr, end);
if (*arr == ' ') //指针指向的内容为空白符时,指针移动到下一单词的首字母处,去除了指向结束符时指针仍旧移动而越界的弊端
{
arr++;
}
}
}
int main()
{
char arr[] = "student a am i";
int sz = 0;
sz= my_strlen(arr);
//printf("%d\n", sz);
reverse_str(arr,sz);
printf("%s\n", arr);
system("pause");
return 0;
}
对第3题进行升级:
//int arr[]={ 1, 2, 3, 4, 4, 3, 1, 2, 5 ,9};
//一组数据中只有一个数字出现了一次。
//其他所有数字都是成对出现的。
//请找出这个数字。(使用位运算)
//不能申请新的数组,不能使用for嵌套
#include<stdio.h>
#include <stdlib.h>
void function(int *arr, int sz, int* x, int *y)
{
int i = 0;
int sum = 0;
int pos = 0;
//获取整个序列异或的结果
for (i = 0; i < sz; i++)
{
sum = sum^arr[i];//
}
//找出从右往左起第pos位为1的位
for (i = 0; i < 32; i++)
{
if ((sum >> i) & 1 == 1)
{
pos = i;
break;
}
}
//按上面的得到POS分割数组
for (i = 0; i < sz; i++)
{
if (((arr[i] >> pos) & 1) == 1)
*x = *x^arr[i];
else
{
*y =*y^arr[i];
}
}
}
int main()
{
int arr[] = { 1, 2, 3, 4, 4, 3, 1, 2, 5, 9 };
int sz = sizeof(arr) / sizeof(arr[0]);
int x = 0;
int y = 0;
function(arr, sz, &x, &y);
printf("%d %d\n", x, y);
system("pause");
return 0;
}