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;}elsereturn 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。