总结一下:
1、首先一组数进行异或得到两个单身狗异或得到的结果。
2、得到异或的结果二进制形式下最低哪个位是1,然后是1的分一组,0的分一组。
void find_single_dog(int arr[], int sz, int* pd1, int* pd2) { int i = 0; int ret = 0; for (i = 0; i < sz; i++) { ret ^= arr[i]; } //计算ret二进制中最右边的第几位是1 //右移和1& int pos = 0; for (pos=0; pos < 32; pos++) { if (((ret >> pos) & 1) == 1) { break; } } for (i = 0; i < sz; i++) { if (((arr[i] >> pos) & 1) == 1) { *pd1 ^= arr[i]; } else { *pd2 ^= arr[i]; } } } int main() { //1 2 3 4 5 1 2 3 4 6 int arr[] = { 1,2,3,4,5,1,2,3,4,6 }; int sz = sizeof(arr) / sizeof(arr[0]); int dog1 = 0; int dog2 = 0; find_single_dog(arr, sz, &dog1, &dog2); printf("%d %d\n", dog1, dog2); return 0; }
四、模拟实现atoi函数
atoi这个函数的主要作用是把字符串数字转换为整型数字。
头文件:int atoi (const char * str);
①函数使用:
通过测试,我们发现出了一般的数字字符串比如”123456“这样的,我们还要考虑:
1、空指针
2、空字符串
3、空格
4、+-号问题
5、非数字字符
6、越界问题
7、............
#include<stdlib.h> #include<ctype.h> #include<ctype.h> #include<limits.h> enum Status { VALID, //0 INVALID //1 }sta=INVALID;//默认非法 int my_atoi(const char* str) { int flag = 1; assert(str);//解决空指针 if (*str == '\0')//解决空字符 { sta = INVALID; return 0;//歧义 ,非法0 } //跳过空白字符 while (isspace(*str)) { str++; } if (*str == '+') { flag = 1; str++; } else if(*str=='-') { flag = -1; str++; } long long ret = 0; while (*str) { if (isdigit(*str)) //越界 { ret = ret * 10 + flag * (*str - '0'); if (ret > INT_MAX || ret < INT_MIN) { //之前的定义为int就不能超过整型最大值,因为超过会发生截断 //所有要设为long return 0; } } else { return (int)ret; } str++; } if (*str == '\0') { sta = VALID; return (int)ret; } } int main() { //int atoi(const char* str) char arr[20] = "-123456"; int ret=my_atoi(arr); if (sta == INVALID) { printf("非法返回:%d\n", ret); } else if (sta == VALID) { printf("合法转换:%d\n", ret); } //遇到非数字,就停止转换 ,开头遇到空格直接过滤掉,中间遇到空格,停止转换 return 0; }
函数说明:
1、assert断言解决空指针问题
2、之所以用long long int 而不用int,是因为如果越界了,int类型会发生截断,不可能大于整型最大值,所以要定义为long long int,这是个细节。
3、使用枚举全局变量的目的是为了一些判断,因为如果是空字符串和"0"字符串如果返回是0,那么这是0还是异常的原因是无法判定的。
五、写一个宏可以把一个整数的二进制位的奇数位和偶数位交换
其实宏和函数差不多,如果感觉宏实现起来有难度,可以尝试先用函数的思想,再转化为宏。对于32位整型,提出来偶数位右移和提出来奇数位左移再相加就实现了奇数位和偶数位的交换。
例子列举:
#define SWAP_BIT(n) (((n&0x55555555)<<1)+((n&0xaaaaaaaa)>>1)) int main() { int n = 0; scanf("%d", &n); int ret=SWAP_BIT(n); printf("%d\n", ret); return 0; }
六、替换空格
实现一个函数,将一个字符串中的每个空格替换为"%20".
这道题目不难实现,问题是要想清楚,简单一点,创建一个新的字符串,遍历旧字符串,如果遇到' '就放进去”%20“,然后再把新的字符串拷贝到旧字符串,这是比较笨且浪费空间的做法。
如果我们不创建新的字符串,那么这道题怎么处置呢?我们要对旧的进行扩容,然后要从后往后搬字符,遇到空格就放'0','2','%',这样是不就解决了?
void replaceSpace(char* str, int length) { assert(str); //一个空格换成三个字符 //统计空格,然后增加空格*2 //从最后往后挪遇到' '就放0 2 %, //遇到空格,end2挪动三步 //end1再往前 char* cur = str; int count = 0; //计算空格数 while (*cur) { if (*cur == ' ') { count++; } cur++; } int end1 = length - 1; int end2 = length + count * 2 - 1; while (end1 != end2) { //We Are Happy. if (str[end1] != ' ') str[end2--] = str[end1--]; else { end1--; str[end2--] = '0'; str[end2--] = '2'; str[end2--] = '%'; } } }
七、offsetof宏的实现
设计一个宏,实现offsetof的功能
offsetof的功能是计算结构体成员偏移量,我们知道结构体成员地址是连续的,所以能否借助这一特性来写这样一个代码吗?
分析:
#define my_offsetof(type,mumber) (size_t)&(((type*)0)->mumber) typedef struct Stu { char c1; int i; char c2; }Stu; int main() { printf("%d\n", my_offsetof(Stu,c1)); printf("%d\n", my_offsetof(Stu,i)); printf("%d\n", my_offsetof(Stu,c2)); return 0; }
本期分享就到这里,谢谢大家的观看,也请勘误喔。