C语言练习题--找到数组中只出现一次的两个数字(找单身狗)、模拟实现atoi函数、将一个二进制数的奇偶位交换、求数字与斐波那契数列中数字的最近距离、将字符串中的空格转换为%20


前言

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 函数 是将数字字符串转换为数字的库函数
  1. 遇到非数字字符串如下:
  • 字符 ,报错
  • 空格, 跳过
  • +, 数字为正
  • -, 数字为负
  1. 同时也要注意以下情况
  • 空指针
  • 空字符串
  • 越界

#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

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值