备注:跟着鹏哥B站学的,加了些自己写的过程中的想法,侵权删!
GetMory返回值的时候p指向的内容已被系统回收
调用GetMory函数为值传递,函数执行后,并不能改变P的值,而且函数执行过后,p被系统回收,动态开辟的内存没有被free将会存在内存泄漏
模拟实现atoi(大概)
#include<stdlib.h>
#include<ctype.h>
#include<limits.h>
enum State
{
INVALID,//0
VALID,//1
};
enum State state = INVALID; //全局变量
//statse 记录的是my_atoi返回的值是合法转化的值,还是非法的状态
int my_atoi(const char* s)
{
int flag = 1;//标记正负数
if (s == NULL)//空指针
{
return 0;
}
if (*s == '\0')//空字符串
{
return 0;
}
while (isspace(*s))
{
s++;
}
//判断正负 判断之后指针指向下一位
if (*s == '+')
{
flag = 1;
s++;
}
else if (*s == '-')
{
flag = -1;
s++;
}
//存数字字符的值
long long n = 0; //输入的字符可能超过int的取值范围 所以定义更大的类型存储它的值
while (isdigit(*s))//当不是数字字符的时候会跳出循环
{
n = n * 10 + flag * (*s - '0');//字符与'0'的差值
if (n > INT_MAX || n < INT_MIN)
{
return 0;//超出范围 出错
}
s++;
}
if (*s == '\0')//因为'\0'跳出循环 正常情况
{
state = VALID;
return (int)n;
}
else
{
return (int)n;
}
}
int main()
{
//可能遇到的非法情况:1.空指针 2.空字符串 3.遇到了非数字字符 4.数字大小超出范围
const char* p = " -12a";
int ret = my_atoi(p);
if (state == VALID)
{
printf("正常转换:%d\n", ret);
}
else
printf("非法转换:%d\n",ret);
return 0;
}
题目:一个数组中只有两个数字是出现一次,其它所有数字都出现了两次,找出只出现了一次的数字。
说实话写这道题的时候,我就是想着用冒泡排序的思想做,但是我只能找到出现了两次的下标,并不知道怎么返回只出现了一次的数字的下标,所以就放弃了,继续跟着鹏哥做了 不得不感慨按位异或运算的厉害:相同数字异或为0,与0异或为本身,刚好可以实现配对!
//一个数组中只有两个数字是出现一次,其它所有数字都出现了两次
//1 2 3 4 5 6 1 2 3 4
//思路 : //1.分组
//2.分组的要点:5和6必须在不同的组
//找出这两个只出现一次的数字
//1^2^3^4^5^6^1^2^3^4 == 5^6 == 3 !=0
//两个不同数字异或的结果3来作为分组的依据
//3的二进为011 用二进制位是1的位来分组
//第一位是否为1 可分为 1 3 5 1 3 --为1的
// 2 2 4 4 6 --为0的
//以第二位是否为1可分为1 4 1 4 5 --为0的
// 2 3 6 2 3 --为1的
//void test(int *arr,int sz,int* px,int* py)
//{
// //1。把所有数字异或
// int i = 0;
// int ret = 0;//所有数字异或以后的结果
// for (i = 0; i < sz; i++)
// {
// ret ^= arr[i];
// }
//
// //2.计算ret的哪一位为1
// //ret = 3
// //011
// int pos = 0;
// for (i = 0; i < 32; i++)
// {
// if ((ret >> i) & 1 == 1)
// {
// pos = i;
// break;
// }
// }
//
// //3.把从低位向高位的第POS位为1的放在一个组,为0的放在另外一个组
// //把一组的数据异或起来存在变量zhong
// //相同的数字异或为0 0和n异或还是n
// int num1 = 0;
// int num2 = 0;
// for (i = 0; i < sz; i++)
// {
// if ((arr[i] >> pos) & 1 == 1)
// {
// (*px) ^= arr[i];
// }
// else
// {
// (*py) ^= arr[i];
// }
// }
//
//}
//int main()
//{
// int arr[10] = { 1,2,3,4,5,6,1,2,3,4 };
// int len = sizeof(arr) / sizeof(arr[0]);
// //printf("%d\n", sizeof(arr));
// int x = 0;
// int y = 0;
// //1.传变量的地址进去,把值记录并且改变 2.也可以传数组进去 把值存在数组中
// test(arr,len,&x,&y);
// printf("%d %d \n", x, y);
// return 0;
//}
//sprintf是把格式化的数据写到字符串中 而不是文件流中
#define INT_PTR int*
typedef int* int_ptr;
INT_PTR a, b; //a是指针 b是int类型
int_ptr c, d;//c,d都是指针
//考察的是对#define字符替换的应用
//INT_PTR所定义的*号与a配对了 b只能是int类型,除非在b前面加一个*号
//而int_ptr则是一种真正的类型,与int c,d的理解方式一样
#end 不是预处理指令
#endif 才是
//#define A 2+2
//#define B 3+3
//#define C A*B
//int main()
//{
// printf("%d\n", C);//11
// return 0;
//}
//还是考察的#define的替换 只是单纯的替换
//头文件应包含 类型的定义 函数的声明 不应包含变量的定义(当在一个源文件中重复引用时很容意出错)
第九题:写一个宏 可以将一个整数的二进制位的奇数位和偶数位交换
当时写这道题的时候并没有想过把奇数位和偶数位的数单独的拿出来,想了很久想不出来
//思路 1.先把这个数的奇数位和偶数位 上的值记录
假设这个值为11111111111111111111111111111111
--按位与上01010101010101010101010101010101 --0x55555555
奇数位为01010101010101010101010101010101
把奇数位左移一位
11111111111111111111111111111111
--按位与上10101010101010101010101010101010
10101010101010101010101010101010 --0xaaaaaaaa
把偶数为右移一位
//#define CHANGE(n) ((n&(0x55555555))<<1)+((n&0xaaaaaaaa)>>1)
//
//int main()
//{
// int num = 10;
// int ret = CHANGE(num);
// printf("ret = %d\n", ret);
// return 0;
//}
最后一题:写一个宏,计算结构体中某变量相对首地址的偏移量
#include<stddef.h>
//解析:把0强制转化为 sruct A*类型的地址 指向0 0之后就会开辟出大小为struct A的地址 然后访问0地址的成员变量的地址 强转为int 类型 即是与0的差值即是偏移量
//强转不会开辟空间
#define DIT(struct_name,men_name) (int)&(((struct_name*)0)->men_name)
struct A
{
int a;
short b;
int c;
char d;
};
int main()
{
printf("%d\n", DIT(struct A, a));
printf("%d\n", DIT(struct A, b));
printf("%d\n", DIT(struct A, c));
printf("%d\n", DIT(struct A, d));
return 0;
}
完结C语言的学习,总的来说,C语言确实难学,主要是C语言不像其它语言一样,把很多功能都封装好了,你直接用就好了,比如python。但是我想走C++方向,所以还得努力,加油!鹏哥讲的很好!接下来就是数据结构了!写这篇文章只是为了记录!