C语言算法

知识为进步之母,而进步又为富强之源泉。这篇文章主要讲述C语言算法相关的知识,希望能为你提供帮助。
错题详解

int main()
{
int i = 0;
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (i = 0; i < = 12; i++)
{
arr[i] = 0;
printf("hehe\\n");
}

return 0;
}

错误原因:数组地址指向了数组的外面




无限循环的原因:i创建在了arr的高位,arr往高位读取,将i里面的数字修改成了0,重新开始


数据存放在内存中时,是先放在高地址中,在往低地址中存放
然而数据读取,是从低地址往高地址中读取
vs2019在这个数组和变量的地址中间隔了2隔空地址
自己写一个strcpy(究极简化版)
#include< assert.h>
char my_strcpy(char* arr1,const char* arr2)
{
assert(arr1 != NULL); //断言
assert(arr2 != NULL); //判断如果括号里面的是真,就执行下面,不然会报错,直接打印到界面里面
int* ret = arr1;
while (*arr1++ = *arr2++)//当传过去/0的时候while判断括号里面都是假所以跳出
{
;
}
return ret;
}
int main()
{
char arr1[20] = "*********";
char arr2[] = "hello";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;
}

const的使用语法使用
int main()
{
const int m = 10; //这里相当于把门封上了,但是靠地址可以空降到地方进行处理
int n = 100;
//int* p = & m;
//const int* p = & m; //这里是将*p即内容锁死,是内容无法更改
//也可以写成int const* p = & m
//p = & n;
//*p = 0; //err

//int * const p = & m; //这里是将p即地址锁死,使地址无法更改无法更改
//p = & n; //err
//*p = 0;

//int const* const p = & m; //这样也可以写,两个都没法改

printf("%d\\n", m);
return 0;
}

自己的理解
int main()
{
int m = 10;
int n = 100;
const int* p = & m;
p = & n; //这里还是被改了只想的地方被改,内容会被改,但是直接更改内容还是不行
printf("%d\\n", *p);
return 0;
}

实现strlen
#include< assert.h>
unsigned int my_strlen(const char* a)
{
assert(a != NULL); //断言的是空指针,而不是指针的内容
unsigned int count = 0;
while (*a++ != \\0)
{
count++;
}
return count;
}
int main()
{
char a[20] = "123";
int i=my_strlen(a);
printf("%d\\n", i);
return 0;
}

实现assert
void my_assert(char* input)
{
if (0==input)
{
printf("此条件不成立\\n");
}
}
int main()
{
int a = 0, b = 0;
int* i = a + b;
my_assert(i);
return 0;
}

奇怪的题1、++和括号的优先级
int main()
{
int a = 0, b = 1, c = 0;
b =(++c,c++,++a, a++); //b=1,a=2; 把括号去掉的话,会把c也加上
printf("%d %d\\n", a, b); //这里输出2 1
return 0;
}

int main()
{
int a = 0, b = 1, c = 0;
b =++c,c++,++a, a++; //b=1,a=2; 把括号去掉的话,会把c也加上
printf("%d %d\\n", a, b); //这里输出2 3
return 0;
}

2、+=和+的优先级
int main()
{
int i = 10;
int j = 30;
int k = 3;
k *= i + j; //+优先级大于*=
//等于k *= (i + j);
printf("%d\\n", k);
return 0;
}

3、特殊语法和类型提升
int main()
{
/*int x = 123;
if (x = 0)//这里判定为假
{
printf("123");
}*/

//int year = 2021, * p = & year;
////等同于
//int year = 2021;
//int* p = & year;

char a; int b; float c; double d;
a* b + c - d;
//这里的结果类型是double
//a会先整型提升为int,a*b的类型会提升为double,再减去float,最后的结果还会是double
return 0;
}

用按位与来求,二进制有多少个1
int number1(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int n = 15;
int ret = number1(n);
printf("%d\\n", ret);
return 0;
}

解释
m1111
m-1 1110
m1110
m-1 1101
m1100
m-1 1011
m1000
m-1 0111
m0000
这个算法会让m的二进制最右面的1消掉
看m和n中二进制各个位不一样的有多少 思路:1、先按位异或 2、在看结果有多少1
int number2(int n, int m)
{
int i = n ^ m;
int count = 0;
while (i)
{
i = i & (i - 1);
count++;
}
return count;
}
int main()
{
int m = 1;
int n = 0;
int ret = number2(n, m);
printf("%d\\n", ret);
return 0;
}

思路:用%2/2的方式
int number3(int n)
{
int count = 0;
while (n)
{
if (1 == n % 2)
{
count++;
}
n = n / 2;
}
return count;
}
int main()
{
int m = 15;
int ret = number3(m);
printf("%d\\n", ret);
return 0;
}

输入一个数,将他的二进制的奇数位和偶数位分别打印
int main()
{
int n = 15;
int i = 0;
//scanf_s("%d", & n);
//00000000 00000000 00000000 00001111
// 0000000 00000000 00000000 00001111
//从右向左的判别是否是偶数
//偶数
for (i = 31; i > = 1; i -= 2)
{
printf("%d ", (n > > i) & 1);
//在最后向右移动1位就是最开始从右向左的第二位,即第一个偶数位
}
printf("\\n");
for (i =30; i > = 0; i -= 2)
{
printf("%d ", (n > > i) & 1);
}
return 0;
}

全局变量与局部变量遵从金字塔逻辑 即同级与同级之间没有联系,某一级只和他的上一级和下一级有联系
int a = 1;
void text()
{
int a = 2;
a += 1;
}
int main()
{
text();
printf("%d\\n", a);
return 0;
}


























【C语言算法】


    推荐阅读