题一:qsort
练习使用库函数,qsort排序各种类型的数据
qsort<stdlib.h>
//排序任意类型数据
void qsort(void* base, size_t num, size_t size,
int (*compar)(const void*, const void*));
#include <stdio.h> #include <string.h> #include <stdlib.h> //比较函数 int compare(const void* e1, const void* e2) { //int sum = (*(char*)e1 - *(char*)e2); return (*(char*)e2 - *(char*)e1); } int main() { char arr[] = { 'a','g','q','c','c','b','d','e','o','j'}; ///*char arr1[5] = "abc"; //char arr2[5] = "zcd"; //char arr3[5] = "dde"; //char arr4[5] = "uef";*/ ///*char* arr[4] = { arr1,arr2,arr3,arr4 };*/ int sz = sizeof(arr)/sizeof(arr[0]); int n = sizeof(arr[0]); qsort(arr,sz,n,compare); int i = 0; for (i = 0;i < sz;i++) { printf("%c ", arr[i]); } /*printf("%s %s %s %s",arr1,arr2,arr3,arr4);*/ return 0; }
模拟实现qsort在不同情形的实现
#include <stdio.h> #include <string.h> //定义结构体 struct S { char ar1[20]; int age; int No; }; //定义一个比较函数 int my_compare(const void* e1, const void* e2) { return (*(char*)e1 - *(char*)e2); } //交换 void my_sawp(char* p1,char*p2, size_t n) { size_t i = 0; for (i = 0; i < n; i++) { char tmp = 0; tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2++; } } //name的比较函数 int my_compare_name(const void* e1,const void* e2) { return strcmp(((struct S*)e1)->ar1, ((struct S*)e2)->ar1); } //age的比较函数 int my_compare_age(const void* e1, const void* e2) { return ((*(struct S*)e1).age - (*(struct S*)e2).age); } //No的比较函数 int my_compare_No(const void* e1, const void* e2) { return ((*(struct S*)e1).No - (*(struct S*)e2).No); } //模拟的qsort void my_qsort(void* arr,size_t sz,size_t n,int(*my_compare)(const void*e1,const void*e2)) { size_t i = 0; size_t j = 0; for (i = 0; i < sz; i++) { for (j = 0; j < sz - 1; j++) { //从小到大,所以用>0 if (my_compare((char*)arr + n * j, (char*)arr + n * (j + 1)) > 0) { //达到条件交换 my_sawp((char*)arr + n * j, (char*)arr + n * (j + 1),n); } } } } int main() { //字符数组 //char arr[] = { 'a','g','q','c','c','b','d','e','o','j' }; //int sz = sizeof(arr) / sizeof(arr[0]); //int n = sizeof(arr[0]); //int i = 0; // //my_qsort(arr, sz,n,my_compare); //for (i = 0; i < sz; i++) //{ // printf("%c ", arr[i]); //} //结构体 struct S s1[] = {{ "zhangsan",20,123 }, { "aisi",60,125 }, { "wanwu",70,111 }, { "laoliu",18,106 }}; int sz1 = sizeof(s1) / sizeof(s1[0]); //my_qsort(s1,sz1,sizeof(s1[0]),my_compare_name); //my_qsort(s1, sz1, sizeof(s1[0]), my_compare_age); my_qsort(s1, sz1, sizeof(s1[0]), my_compare_No); return 0; }
题二:strlen
模拟实现strlen
#include <stdio.h> #include <string.h> #include <assert.h> int my_strlen(const char* arr) { assert(arr); int count = 0; int i = 0; for (i = 0; i < 10000; i++) { if (*(arr + i) != '\0') { count++; } else { break; } } return count; } int main() { int n = 0; char arr[] = "woxinli" ; //n = strlen(arr); n = my_strlen(arr); printf("%d\n", n); return 0; }
优解一
//计数器方式 int my_strlen(const char * str) { int count = 0; while(*str) { count++; str++; } return count; }
优解二
//不能创建临时变量计数器 int my_strlen(const char * str) { if(*str == '\0') return 0; else return 1+my_strlen(str+1); }
优解三
//指针-指针的方式 int my_strlen(char *s) { char *p = s; while(*p != ‘\0’ ) p++; return p-s; }
题三:strcpy
模拟实现strcpy
#include <stdio.h> #include <string.h> void my_strcpy(char* arr2,const char* arr1) { int i = 0; for (i = 0; i < 10000; i++) { if (arr1[i] != '\0') { arr2[i] = arr1[i]; } else { break; } } } int main() { char arr1[20] = "wojiaoshuaige"; char arr2[20] = { 0 }; //strcpy(arr2,arr1); my_strcpy(arr2,arr1); return 0; }
优解一
//1.参数顺序 //2.函数的功能,停止条件 //3.assert //4.const修饰指针 //5.函数返回值 //6.题目出自《高质量C/C++编程》书籍最后的试题部分 char *my_strcpy(char *dest, const char*src) { char *ret = dest; assert(dest != NULL); assert(src != NULL); while((*dest++ = *src++)) { ; } return ret; }
题四:strcmp
模拟实现strcmp
#include <stdio.h> #include <string.h> #include <assert.h> int my_strcmp(const char* arr1, const char* arr2) { assert(arr1 && arr2); int i = 0; for (i = 0; i < 10000; i++) { if (*(arr1 + i) > *(arr2 + i)) { return 1; } else if (*(arr1 + i) < *(arr2 + i)) { return -1; } } return 0; } int main() { char arr1[20] = "abcdef"; char arr2[20] = "abcdzf"; /*int n = strcmp(arr1, arr2);*/ int n = my_strcmp(arr1,arr2); return 0; }
优解一
int my_strcmp (const char * src, const char * dst) { int ret = 0 ; assert(src != NULL); assert(dest != NULL); //&&是当ret为0时,加入循环语句中实现++ while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) ++src, ++dst; if ( ret < 0 ) ret = -1 ; else if ( ret > 0 ) ret = 1 ; return( ret ); }
题五:strcat
模拟实现strcat
#include <string.h> #include <stdio.h> #include <assert.h> void my_strcat(char* arr1,const char* arr2) { assert(arr1 && arr2); int i = 0; int sz = 0; sz = strlen(arr1); for (i = 0; i < 10000; i++) { if (arr2[i] != '\0') { arr1[sz] = arr2[i]; sz++; } else { break; } } } int main() { char arr1[20] = "hello "; char arr2[20] = "bit "; char arr3[20] = "shaniao"; //strcat(arr1,arr2); my_strcat(arr1,arr2); my_strcat(arr1,arr3); return 0; }
优解一
char *my_strcat(char *dest, const char*src) { char *ret = dest; assert(dest != NULL); assert(src != NULL); while(*dest) { dest++; } while((*dest++ = *src++)) { ; } return ret; }
题六:strstr
模拟实现strstr
#include <stdio.h> #include <string.h> #include <assert.h> char* my_strstr(const char* arr1, const char* arr2) { assert(arr1 && arr2); int i = 0; int j = 0; int sz = strlen(arr1); int sz1 = strlen(arr2); for (i = 0; i < sz; i++) { int count = 0; if (arr1[i] == arr2[0]) { char* p = &arr1[i]; for (j = 0; j < sz1; j++) { if (arr1[i + j] == arr2[j]) { count++; } else if (arr1[i + j] != arr2[j]) { break; } } if (count == sz1) { return p; } } } return NULL; } int main() { char arr1[20] = "abcdef"; char arr2[20] = "def"; //char* str = strstr(arr1,arr2); char* str = my_strstr(arr1, arr2); return 0; }
优解一
char * strstr (const char * str1, const char * str2) { char *cp = (char *) str1; char *s1, *s2; if ( !*str2 ) return((char *)str1); while (*cp) { s1 = cp; s2 = (char *) str2; while ( *s1 && *s2 && !(*s1-*s2) ) s1++, s2++; if (!*s2) return(cp); cp++; } return(NULL); }
题七:memcpy
模拟实现memcpy
#include <stdio.h> #include <string.h> void* my_memcpy(void* s2,const void* s1,size_t n) { void* tmp = s2; while (n--) { *((char*)s2) = *((char*)s1); s2 = (char*)s2 + 1; s1 = (char*)s1 + 1; } return tmp; } int main() { char arr2[20] = { 0 }; char arr1[20] = "abcdef"; my_memcpy(arr2,arr1,3); //memcpy(arr2, arr1,3); return 0; }
题八:memmove
模拟实现memmove
#include <stdio.h> #include <string.h> #include <assert.h> void* my_memmove(void* s1,const void* s2,size_t n) { assert(s1 && s2); void* tmp = s1; if(s1 >= s2)//当目标地址大于或等于源地址时 { while (n--) { *((char*)s1) = *((char*)s2); s2 = (char*)s2 + 1; s1 = (char*)s1 + 1; } } else while (n--)//当目标地址大于或等于源地址时 { *((char*)s1+n) = *((char*)s2+n); } return tmp; }
或者
void * memmove ( void * dst, const void * src, size_t count) { void * ret = dst; if (dst <= src || (char *)dst >= ((char *)src + count)) { /* * Non-Overlapping Buffers * copy from lower addresses to higher addresses */ while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } } else { /* * Overlapping Buffers * copy from higher addresses to lower addresses */ dst = (char *)dst + count - 1; src = (char *)src + count - 1; while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return(ret); }
做错的选择题
关于回调函数描述错误的是( )
A.回调函数就是一个通过函数指针调用的函数
B.回调函数一般通过函数指针实现
C.回调函数一般不是函数的实现方调用,而是在特定的场景下,由另外一方调用。
D.回调函数是调用函数指针指向函数的函数。
调用指针”、“指向函数”是什么鬼……D选项简直逻辑鬼才!ABC就是基础概念,可以复习下。
下面test函数设计正确的是:( )
char* arr[5] = {"hello", "bit"};
test(arr);
A.void test(char* arr);
B.void test(char** arr);
C.void test(char arr[5]);
D.void test(char* arr[5]);
指针的数组传递给子函数变为指针的指针,也就是二级指针。但是允许中括号写法,写成char **arr、char *arr[]、char * arr[5]都可。所以BD正确。
下面程序的结果是:( )
int main()
{
int aa[2][5] = {10,9,8,7,6,5,4,3,2,1};
int *ptr1 = (int *)(&aa + 1);//&的优先级大于+
int *ptr2 = (int *)(*(aa + 1));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
A.1, 6
B.10, 5
C.10, 1
D.1, 5
跟上题类似,&aa的类型是int (*)[2][5],加一操作会导致跳转一个int [2][5]的长度,直接跑到刚好越界的位置。减一以后回到最后一个位置1处。*(aa + 1)相当于aa[1],也就是第二行的首地址,自然是5的位置。减一以后由于多维数组空间的连续性,会回到上一行末尾的6处。故选A。
下面代码中print_arr函数参数设计哪个是正确的?( )
int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
print_arr(arr, 3, 5);
A.void print_arr(int arr[][],int row, int col);
B.void print_arr(int* arr, int row, int col);
C.void print_arr(int (*arr)[5], int row, int col);
D.void print_arr(int (*arr)[3], int row, int col);
二维数组相当于数组的数组,传到子函数变成数组的指针。int arr[3][5]相当于是3个元素的arr,每个元素是int [5],所以int [5]是类型说明不能省略。丢失的信息只有数组的元素个数,也就是3。A丢了类型中的5,B选项指针层级都错了,D选项5写成了3,故选C。
下面程序的结果是:( )
int main()
{
int a[5] = {5, 4, 3, 2, 1};
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
A.5, 1
B.4, 1
C.4, 2
D.5, 2
*(a + 1)等同于a[1],第一个是4,a的类型是int [5],&a的类型就是int(*)[5],是个数组指针。所以给int(*)[5]类型加一,相当于加了一个int [5]的长度。也就是这个指针直接跳过了a全部的元素,直接指在了刚好越界的位置上,然后转换成了int *后再减一,相当于从那个位置向前走了一个int,从刚好越觉得位置回到了1的地址处,所以第二个是1,故选B。