1.qsort的模拟实现(冒泡排序的原型制作)
1.排序整型
int cmp_int(const void* p1, const void* p2)
{
return *((int*)p1) - *((int*)p2);
}
void swap(char* p1, char* p2)//完成交换
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void *p2))
{
for (int i = 0; i < sz - 1; i++)//趟数
{
for (int j = 0; j <sz-1-i ; j++)
{
if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)//找到两个元素的地址
{
swap((char*)base + j*width, (char*)base + (j+1) *width);//char*的指针才是加几就跳过几个字节。
}
}
}
}
void pint(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
void test3()
{
int arr[] = { 3,5,7,9,1,2,4,6,8 };
int sz = sizeof(arr) / sizeof(arr[0]);
int width = sizeof(arr[0]);
pint(arr, sz);
printf("\n");
bubble_sort(arr, sz, width, cmp_int);
pint(arr, sz);
}
int main()
{
test3();
return 0;
}
在上述代码中我们需要完和qsort一样的排序功能,我们就需要改变冒泡排序的参数,变得和qsort一样,这样的话我们才能完成排序任意类型的数据。首先我们发现之前冒泡排序的交换规则也只能交换int类型的数据,所以我们也需要进行修改,我们想到使用char*的指针一个字节一个字节的交换,这样的话任意类型都可以进行交换。为了方便观察我们在排序前排序后都打印一次arr这样就方便那观察。
结果如下:
我们可以看到完成为了我们的排序要求,那它能不能完成结构体的排序呢?
2.排序结构体
我们来试试:
struct Stu
{
char name[20];
int age;
};
int sort(const void* p1, const void* p2)//结构体不需要解引用
{
return strcmp(((struct Stu*)p1)->name , ((struct Stu*)p2)->name );//strcmp库函数的返回值刚好满足qsort函数的第四个参数的需要
}
void swap(void* p1, void* p2, int width)
{
char tmp;
for (int i = 0; i < width; i++)
{
tmp = *((char*)p1 + i);
*((char*)p1 + i) = *((char*)p2 + i);
*((char*)p2 + i) = tmp;
}
}
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void *p2))
{
for (int i = 0; i < sz - 1; i++)//趟数
{
for (int j = 0; j <sz-1-i ; j++)
{
if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)//找到两个元素的地址
{
swap((char*)base + j*width, (char*)base + (j+1) *width,width);//char*的指针才是加几就跳过几个字节。
}
}
}
}
void print1(struct Stu*pt,int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%s %d ", pt->name, pt->age);
pt++;
}
}
void test1()
{
struct Stu arr[3] = { {"zhangsan",23},{"lisi",28},{"wangwu",18} };
int sz = sizeof(arr) / sizeof(arr[0]);
int width = sizeof(arr[0]);
print1(arr, sz);
printf("\n");
bubble_sort(arr, sz, width, sort);
print1(arr, sz);
}
int main()
{
test1();
return 0;
}
需要注意的是我们要将swap函数修改一下。
结果如下:
2.字符分类函数
C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。
这些函数的使⽤都需要包含⼀个头文件是 <ctype.h>
这些函数都是比较简单的我们挑几个试试,剩下的都差不多的操作。
1.islower和isupper
我们看到它的返回值为int,其实字符是以ASCLL码值存储在内存中,所以也属于int类型的。
islower函数输入一个小写字母就返回大于0的值,大写就返回一个小于0的值。isuppper相反。
2.tolower 和toupper
那么怎样将字母改变其大小写呢?我们就要使用这两个函数了,它们的头文件也是
<ctype.h>.
演示如下:
结果为:
我们给toupper函数传小写时它就会将其改为大写,传大写就不会修改。tolower刚好相反。
3.模拟实现tolower函数
char my_tolower(char *pt)
{
if (*pt)
{
*pt = *pt + 32;
return *pt;
}
else
return 0;
}
int main()
{
char arr[] = "YOU";
size_t sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
arr[i] = my_tolower(&arr[i]);
}
printf(arr);
return 0;
}
我们运用大写字母和小写字母的ASCLL码值相差32来实现,大家也可以试试模拟实现touppper。