
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
//编写一个函数找出这两个只出现一次的数字。
//例如:
//有数组的元素是:1,2,3,4,5,1,2,3,4,6
//只有5和6只出现1次,要找出5和6.
//曾经做过在一组数中找只出现一次的题目
//我们先实现
//void Play_One(int arr[], int sz)
//{
// //利用异或的功能,将全部数字异或
// int ret = 0;
// int i = 0;
// for (i = 0; i < sz; i++)
// {
// ret ^= arr[i];
// }
// printf("%d\n", ret);
//
//}
//int main()
//{
// int arr[] = { 1,2,3,4,1,2,3 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// Play_One(arr, sz);
// return 0;
//}
//在此基础上,我们要找出两个只出现一次的数字
//我们发现找一个时,我们将全部数字异或在一起,就得出答案
//那找两个时,我们可以将两个数字各分为一组,然后在按找一个时的思路
//当我们将全部数字直接异或后,最后的结果是两个不相等的数字异或后的结果
//如:1,2,3,4,5,1,2,3,4,6
//最后只剩:5 6
//5的二进制:1 0 1
//6的二进制: 1 1 0
// 异或后 :0 1 1
//然后我们可以根据异或后二进制位次值为1进行分组,因为异或后位次上为1,那就的代表是由两个不相等的数进行异或的结果
//那一位上必然有一个为0,一个为1,我们就可以分为两组
//如:最低位为1的:1 1 3 3 5
// 最低位为0的:2 2 4 4 6
//有很多种分组法................
void Play_Two(int arr[], int sz, int* Dog1, int* Dog2)
{
//第一步:将全部数字异或,得出最终两个数异或的结果
int ret = 0;
int i = 0;
int record = 0;
for (i = 0; i < sz; i++)
{
ret ^= arr[i];
}
//第二步:找到哪一位为1
for (i = 0; i < 32; i++)
{
//&1的作用为得到当前位次上的数
if ((ret >> i) & 1)
{
//将该位的序号记住
record = i;
break;
}
}
//第三步:分组异或
for (i = 0; i < sz; i++)
{
if (((arr[i] >> record) & 1) == 1)
{
*Dog1 ^= arr[i];
}
else
{
*Dog2 ^= arr[i];
}
}
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
int x = 0;
int y = 0;
Play_Two(arr, sz, &x, &y);
printf("%d %d", x,y);
return 0;
}

//模拟实现strncpy
//指定拷贝几个字符
//char * strncpy ( char * destination, \
// const char * source, \
// size_t num )
//注意:1.当指定几个字符拷贝时,拷贝完不会自动补'\0'
// 如果目标空间有元素,只会覆盖指定几个字符后的位置,其它字符依然存在
// 2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
// 3.目标空间一定要大于源头空间
#include<assert.h>
#include<string.h>
#include<stdio.h>
char* True_Strncpy(char* Des, const char* Sou,size_t num)
{
assert(Des && Sou);
int i = 0;
int sum = 0;
char* p = Des;
for (i = 0; i < num; i++)
{
//情况一:源字符串>=num
if (strlen(Sou) >= num)
{
*(Des + i) = *(Sou + i);
}
//情况二:源字符串<num
else
{
sum++;
if (sum <= strlen(Sou))
{
*(Des + i) = *(Sou + i);
}
else
{
*(Des + i) = 0;
}
}
}
return p;
}
int main()
{
char arr1[] = "abcdef";
char arr2[20] = { 0 };
char* p = True_Strncpy(arr2, arr1, 8);
printf("%s\n", p);
return 0;
}

//模拟实现strncat
// 指定num个字符串追加
//char * strncat ( char * destination, \
// const char * source,\
// size_t num );
// 注意:目标空间一定要大于源头空间
char* True_Strncar(char* Des, char* Sou, size_t num)
{
assert(Des && Sou);
int i = 0;
char* p = Des;
int m = strlen(Des);
while (*(Des + m) = *(Sou + i))
{
m++;
i++;
if (i > num)
{
break;
}
}
return p;
}
int main()
{
char arr1[] = "abcdef";
char arr2[20] = "abc";
char*p = True_Strncar(arr2, arr1, 6);
printf("%s\n", p);
return 0;
}

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<ctype.h>
//模拟实现atoi
//int atoi(const char *str)
//功能:将由数字组成的字符串转化为整数
// 如果字符串里有数字,最后返回转化后的整形int数据
// 如果遇到字符串里的元素不为数字,最后返回0
//注意:1.字符串里的数字字符不能超过int范围
// 2.考虑字符串为空的情况/考虑空指针情况
// 3.该函数会忽视空格字符情况,遇到直接跳过
// 4.有正数或负数,应提前判断是正是负
int Num_Atoi(const char* num)
{
//第一步,判断是否为空指针,或者为空字符
if (num == NULL)
{
return 0;
}
else if (*num == '\0')
{
return 0;
}
int i = 0;
int sum = 1;
//第二步:判断字符串的正负
if(*num == '-')
{
sum = -1;
num++;
}
//第三步:判断字符串是否有空格
//isspace函数是用来判断是否为空白字符,
//如果是则该函数返回非零值(true),否则返回 0(false)。
while (isspace(*num))
{
num++;
}
//第四步:字符串转换以及检索是否存在除数字外的元素
//isdigit库函数——用于判断字符是否为数字字符
long long n = 0;//定义长整型,以防存放不下转换后的结果
while(isdigit(*num))
{
n =n* 10 + sum * (* num - '0');
//第五步:判断转换后的结果是否在int类型范围
if (n > INT_MAX || n < INT_MIN)
{
return (int)n;
}
num++;
}
//最后判断字符是否有元素
if (*num != '\0')
{
return (int)n;
}
return (int)n;
}
int main()
{
//示例一:
char num1[] = "-2314";
int sum =Num_Atoi(num1);
//int sum = atoi(num1);
printf("%d\n", sum);
return 0;
}