前言
C语言练习题–找到数组中只出现一次的两个数字(找单身狗)、模拟实现atoi函数、将一个二进制数的奇偶位交换、求数字与斐波那契数列中数字的最近距离、将字符串中的空格转换为%20
一、找到数组中只出现一次的两个数字(找单身狗)
- 相同元素异或为 0.
- 任何数和 0 异或都是任何数。
#include <stdio.h>
void FindSingleDog(int arr[], int sz, int* dog1, int* dog2)
{
int i = 0;
int ret = 0;
// 异或
for (i = 0; i < sz; i++)
{
ret ^= arr[i];
}
// 计算找到1的位置
int pos = 0;
for (pos = 0; pos < sz; pos++)
{
if (((ret >> pos) & 1) == 1)
{
break;
}
}
// 分组
for (i = 0; i < sz; i++)
{
if (((arr[i] >> pos) & 1) == 1)
{
*dog1 ^= arr[i];
}
else
{
*dog2 ^= arr[i];
}
}
}
int main()
{
int arr[] = { 1,1,2,2,5,3,3,7,6,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
int dog1 = 0;
int dog2 = 0;
FindSingleDog(arr, sz, &dog1, &dog2);
printf("%d %d", dog1, dog2);
return 0;
}
二、模拟实现atoi函数
- atoi 函数 是将数字字符串转换为数字的库函数
- 遇到非数字字符串如下:
- 字符 ,报错
- 空格, 跳过
- +, 数字为正
- -, 数字为负
- 同时也要注意以下情况
- 空指针
- 空字符串
- 越界
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>
enum
{
VALUE,
INVALUE
}sta = INVALUE;
int my_atoi(const char* str)
{
assert(str);
int flag = 1;
// 空字符串
if (*str == '\0')
return 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)
{
return 0;
}
}
else
return (int)ret;
str++;
}
if(*str == '\0')
sta = VALUE;
return flag*(int)ret;
}
int main()
{
char arr[20] = { 0 };
printf("请输入字符串:>");
scanf("%s", arr);
int ret = my_atoi(arr);
if (sta == INVALUE)
{
printf("非法返回:%d\n", ret);
}
else if(sta == VALUE)
{
printf("合法返回:%d\n", ret);
}
return 0;
}
三、将一个二进制数的奇偶位交换
- 原数字与 0101010101010101010101010101010101010101 这样的数字按位与(&)可以得到偶数位的数字,奇数位全为0,在向左移位 1, 则偶数位数字置于奇数位。这样的数字的十六进制就是0x55555555。
- 原数字与 1010101010101010101010101010101010101010 这样的数字按位与(&)可以得到奇数位的数字,偶数位全为0,在向右移位 1, 则奇数位数字置于偶数位。这样的数字的十六进制就是0xaaaaaaaa。
- 两者相加则得到奇偶位交换后的数字
#include <stdio.h>
#define SWAP(n) ((n & 0x55555555) << 1) + ((n & 0xaaaaaaaa) >> 1)
int main()
{
int n = 0;
scanf("%d", &n);
int ret = SWAP(n);
printf("%d\n", ret);
return 0;
}
四、求数字与斐波那契数列中数字的最近距离
- 斐波那契数列从a=0,b=1开始,判断数字n的位置
- 若n == b 直接返回0
- 若n < b 则他在ab之间判断(a-n)(b-n)的距离的大小,输出小的距离
- 若n > b 则 a = b, b = c;判断下一组斐波那契的数字
#include <stdio.h>
#include <math.h>
int main()
{
int a = 0;
int b = 0;
int c = 0;
a = 0;
b = 1;
int num = 0;
scanf("%d", &num);
while (1)
{
if (num == b)
{
printf("步数为%d\n", 0);
break;
}
else if (num < b)
{
if (abs(a - num) > abs(b - num))
{
printf("步数为%d\n", abs(b - num));
break;
}
else
{
printf("步数为%d\n", abs(a - num));
break;
}
}
c = a + b;
a = b;
b = c;
}
return 0;
}
五、将字符串中的空格转换为%20
- 统计空格字符的个数
- 每一个空格字符转换成3个字符,所以每个空格字符增加两个字符的位置
- 记住增加位置后的字符串结尾地址end2,以及原来字符结尾的地址end1
- 两个地址从后往前遍历,将en1的值赋值给end2
- 若遇到空格,end1减1跳过,end2分别赋值‘0’,‘2’,‘%’,并且每一步赋值都减减
- 两个地址相等则停止循环
#include <stdio.h>
#include <string.h>
void replaceSpace(char* str, int len)
{
int count = 0;
char* arr1 = str;
while (*arr1)
{
if(*arr1 == ' ')
count++;
arr1++;
}
int end1 = len - 1;
int end2 = len + count * 2 - 1;
while (end1 != end2)
{
if (str[end1] != ' ')
{
str[end2--] = str[end1--];
}
else
{
end1--;
str[end2--] = '0';
str[end2--] = '2';
str[end2--] = '%';
}
}
}
int main()
{
char arr[100] = "we are happy.";
int len = strlen(arr);
replaceSpace(arr, len);
printf("%s\n", arr);
return 0;
}
总结
C语言练习题–找到数组中只出现一次的两个数字(找单身狗)、模拟实现atoi函数、将一个二进制数的奇偶位交换、求数字与斐波那契数列中数字的最近距离、将字符串中的空格转换为%20