目录
1.实现一个计算器,计算整形变量的加减乘除(使用回调函数)
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("**************************\n");
printf("**** 1. add 2. sub ****\n");
printf("**** 3. mul 4. div ****\n");
printf("**** 0. exit ****\n");
printf("**************************\n");
}
int Calc(int (*pf)(int, int))
{
int x = 0;
int y = 0;
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
return pf(x, y);
}
int main()
{
int input = 0;
//计算器-计算整型变量的加、减、乘、除
//a&b a^b a|b a>>b a<<b a>b
do {
menu();
int ret = 0;
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
ret = Calc(Add);
printf("ret = %d\n", ret);
break;
case 2:
ret = Calc(Sub);
printf("ret = %d\n", ret);
break;
case 3:
ret = Calc(Mul);//
printf("ret = %d\n", ret);
break;
case 4:
ret = Calc(Div);//
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
2.使用qsort函数排序整型(实现升序)
先用冒牌排序实现
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz - i; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] < arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
void print_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//qosrt函数的使用者得实现一个比较函数
int cmp_int(const void* p1, const void* p2) //提供的是整型数组元素大小的比较方式
{
return (*(int*)p1 - *(int*)p2);
//强制类型转换为int*,说明比较的是整型元素
//p1,p2接收的是对应元素的地址
//如果返回值大于0,则两元素进行交换
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//排序
qsort(arr, sz, sizeof(arr[0]), cmp_int);
//打印
print_arr(arr, sz);
return 0;
}
3.使用回调函数,模拟实现qsort(采用冒泡的方式
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp1(const void* p1, const void* p2) //提供的是整型数组元素大小的比较方式
{
return (*(int*)p1 - *(int*)p2);
}
int cmp2(const void* elem1,const void* elem2) //提供的是浮点型数组元素大小的比较方式
{
return (*(float*)elem1 - *(float*)elem2);
}
struct stu2 {
char name[20];
int age = 0;
};
int cmp3(const void* elem1, const void* elem2) //提供的是结构体中stu2中name成员的比较方式
{
return (strcmp(((struct stu2*)elem1)->name, ((struct stu2*)elem2)->name));
}
int cmp4(const void* elem1, const void* elem2)//提供的是结构体中stu2中age成员的比较方式
{
return (((struct stu2*)elem1)->age - ((struct stu2*)elem2)->age);
}
void customer_sort(void*base, int num, int width, int (*cmp)(const void*elem1,const void* elem2))
{
int i = 0;
for (; i < num - 1; i++)//确定排序趟数
{
for (int b = 0; b < num - 1 - i; b++)//每趟排序进行比较的次数
{
if (cmp(((char*)base + b * width), ((char*)base + (b + 1) * width)) > 0)
//如果cmp函数返回值大于0,则进行交换
{
char tmp = 0;
for (int j = 0; j < width; j++)
{
tmp = *((char*)base + b * width + j);
*((char*)base + b * width + j) = *((char*)base + (b + 1) * width + j);
*((char*)base + (b + 1) * width + j) = tmp;
}
}
}
}
}
int main()
{
int arr1[10] = { 2,4,6,8,1,3,9,5,7,10 };
float arr2[5] = { 3.0,5.0,1.0,7.0,8.0 };
int sz = sizeof(arr2) / sizeof(*arr2);
customer_sort(arr2, sz, sizeof(*arr2),cmp2);//如果要排序其他类型数组
//把cmp函数换成对应的就行了
for (int a = 0; a < sz; a++)
{
printf("%f ", arr2[a]);
}
return 0;
}
4.易混易错sizeof和strlen
习题1
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(* &a));
//&a -- int(*p)[4] = &a;
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
习题2
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//这里没有\0之分
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
习题3
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
//printf("%d\n", strlen(*arr));
//printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
因为strlen结束标志是\0,所以前俩个找不到结束标志结果就是随机值;第三和第四个错了,strlen()应该传递的是地址,他们却传递了具体数值,把数值97当成具体地址;第五个传递过去依然会被认为是arr首地址,随机值;第六个跳过一个数组,也是随机值;第七个同理,从b的地址向后寻找\0,也是随机值。
————————————————
版权声明:本文为CSDN博主「林慢慢脑瓜子嗡嗡的」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_48953972/article/details/117591550
习题4
char arr[] = "abcdef";
//[a b c d e f \0]
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
//printf("%d\n", strlen(*arr));
//printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
习题5
char arr[] = "abcdef";
//[a b c d e f \0]
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
习题6
char* p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));
答案:4/8;4/8;1;1;4/8;4/8;4/8
习题7
char* p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p + 1));
printf("%d\n", strlen(&p[0] + 1));
答案:
6;5;err;err;
第五个随机(对p取地址,向后去\0压根不知道结果);
第六个随机,与第五个同理;
5 。
习题8
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
printf("%d\n", sizeof(a[-1]));
sizeof表达时不参与运算:
#include <stdio.h>
int main()
{
short s = 5;
int a = 4;
printf("%d\n", sizeof(s = a + 6));//1
printf("%d\n", s);//2
return 0;
}
打印结果: 2 5
5.指针笔试题
习题1:判断打印值
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
&a 取的是整个数组的地址,&a+1跳过整个数组
习题2
由于还没学习结构体,这里告知结构体的大小是20个字节。
假设p 的值为0x100000。 如下表达式的值分别为多少?
已知,结构体Test类型的变量大小是20个字节
提示:指针类型决定了指针的 运算
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}* p;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
1.p是结构体指针,加1跳过一个结构体大小。0x100014
2.强制转化成整型类型,加1就是加1。0x100001
3.p指向(unsigned int*)无符号整型指针,加1跳过一个整型变量的大小,即加4。0x100004
习题3
int a[4] = { 1, 2, 3, 4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
习题4
用小括号即为逗号表达式,逗号表达式只要最后一个,多出来的部分后面补0
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
习题5
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
习题6
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
结果:10,5
习题7
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
打印结果:at
习题8
char* c[] = { "ENTER","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--* ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);