一、编写程序,输入三个字符串,比较它们的大小,并将它们按由小到大的顺序输出。要求用函数、指针实现。要求:要采用函数调用,并用指向函数的指针作为函数的参数。
1.不使用函数指针作为参数,并自己模拟strcmp。
compare_s函数:
- 此函数的目的是比较两个字符串s1和s2的大小。
- 使用while循环逐个字符地比较两个字符串,直到其中一个字符串结束或找到不同的字符。
- 如果两个字符串的某个字符不相等,则返回它们的差值,确定它们的大小关系。
- 如果两个字符串完全相同,则返回0。
compare_output函数:
- 此函数的目的是根据compare_s函数的比较结果对三个字符串s1、s2和s3进行排序。
- 首先,它确保s1是三个字符串中最大的,然后确保s2是次大的,最后确保s3是最小的。
- 为了交换字符串,它使用了一个临时字符串s。
int compare_s(char* s1, char* s2)//定义比较字符串大小的函数 //模拟实现strcmp { int i = 0;//把函数返回值初始化为0 while (*s1 && *s2 )//当字符串未结束时,执行该循环 { s1++;//未比较出大小则继续比较下一位,故使指针增加1 s2++;//未比较出大小则继续比较下一位,故使指针增加1 } return *s1 - *s2;//返回比较结果 } void compare_output(char* s1, char* s2, char* s3) { char s[N];//定义一个字符型数组充当临时字符串 //以下分析了三个字符串所有的大小关系并重新排列 if (compare_s(s1, s2) < 0)//确保s1>=s2 { strcpy(s, s1); strcpy(s1, s2); strcpy(s2, s);//保证s1>s2 } if(compare_s(s1, s3) < 0)//确保s1>=s3 { strcpy(s, s1); strcpy(s1, s3); strcpy(s3, s);//保证s1>s3 } if (compare_s(s2, s3) < 0)//确保s2>=s3 { strcpy(s, s2); strcpy(s2, s3); strcpy(s3, s);//保证s2>s3 } } int main() { char s1[N], s2[N], s3[N];//定义两个字符串 printf("请输入第一个字符串:\n");//提示用户输入第一个字符串 fgets(s1, 100, stdin);//使用fgets函数获取字符串s1 printf("请输入第二个字符串:\n");//提示用户输入第二个字符串 fgets(s2, 100, stdin);//使用fgets函数获取字符串s2 printf("请输入第三个字符串:\n");//提示用户输入第三个字符串 fgets(s3, 100, stdin);//使用fgets函数获取字符串s3 compare_output(s1, s2, s3); printf("从小到大:\n%s%s%s", s3, s2, s1); return 0; }
2、不使用函数指针作为参数,使用strcmp
void compare_output(char* s1, char* s2, char* s3) { char s[N];//定义一个字符型数组充当临时字符串 //以下分析了三个字符串所有的大小关系并重新排列 if (strcmp(s1, s2) < 0) { strcpy(s, s1); strcpy(s1, s2); strcpy(s2, s);//保证s1>s2 } if(strcmp(s1, s3) < 0) { strcpy(s, s1); strcpy(s1, s3); strcpy(s3, s);//保证s1>s3 } if (strcmp(s2, s3) < 0) { strcpy(s, s2); strcpy(s2, s3); strcpy(s3, s);//保证s2>s3 } } int main() { char s1[N], s2[N], s3[N];//定义两个字符串 printf("请输入第一个字符串:\n");//提示用户输入第一个字符串 fgets(s1, sizeof(s1), stdin);//使用fgets函数获取字符串s1 printf("请输入第二个字符串:\n");//提示用户输入第二个字符串 fgets(s2, sizeof(s2), stdin);//使用fgets函数获取字符串s2 printf("请输入第三个字符串:\n");//提示用户输入第三个字符串 fgets(s3, sizeof(s3), stdin);//使用fgets函数获取字符串s3 compare_output(s1, s2, s3); printf("从小到大:\n%s%s%s", s3, s2, s1); return 0; }
3、使用函数指针作为参数进行比较
void swap(char* s1, char* s2)//交换两个字符串的值 { char s[N]; strcpy(s, s1); strcpy(s1, s2); strcpy(s2, s); } void my_sort(char* s1, char* s2, char* s3, void (*swap)(char* s1, char* s2)) { char s[N]; if (strcmp(s1, s2) < 0) { swap(s1, s2);//保证s1>s2 } if (strcmp(s1, s3) < 0) { swap(s1, s3);//保证s1>s3 } if (strcmp(s2, s3) < 0) { swap(s2, s3);//保证s2>s3 } } int main() { char s1[N], s2[N], s3[N];//定义两个字符串 printf("请输入第一个字符串:\n");//提示用户输入第一个字符串 fgets(s1, 100, stdin);//使用fgets函数获取字符串s1 printf("请输入第二个字符串:\n");//提示用户输入第二个字符串 fgets(s2, 100, stdin);//使用fgets函数获取字符串s2 printf("请输入第三个字符串:\n");//提示用户输入第三个字符串 fgets(s3, 100, stdin);//使用fgets函数获取字符串s3 my_sort(s1, s2, s3,swap); printf("从小到大:\n%s%s%s", s3, s2, s1); return 0; }
4、使用指针数组存储字符串后比较
#include <stdio.h> // 比较两个字符串前后顺序 int compare(const char *str1, const char *str2) { while (*str1 && (*str1 == *str2)) { str1++; str2++; } return *str1 - *str2; } // 交换两个字符串的位置 void swap(char **str1, char **str2) { char *temp = *str1; *str1 = *str2; *str2 = temp; } // 使用指向函数的指针来排序字符串数组 void sortStrings(char **strings, int n, int (*compare)(const char*, const char*)) { int i, j; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (compare(strings[j], strings[j+1]) > 0) { swap(&strings[j], &strings[j+1]); } } } } int main() { char str1[100], str2[100], str3[100]; // 输入三个字符串 printf("请输入第一个字符串:"); scanf("%s", str1); printf("请输入第二个字符串:"); scanf("%s", str2); printf("请输入第三个字符串:"); scanf("%s", str3); // 定义一个指针数组,保存三个字符串的地址 char *strings[] = {str1, str2, str3}; int n = sizeof(strings) / sizeof(strings[0]); // 使用指向函数的指针来排序字符串数组 sortStrings(strings, n, compare); // 输出排序后的字符串数组 printf("排序后的字符串数组:\n"); for (int i = 0; i < n; i++) { printf("%s\n", strings[i]); } return 0; }
二、一道变态的面试题
不能创建临时变量(第三个变量),实现两个整数数的交换
1、一般法(不符合)
int main() { int a = 3, b = 5; //交换a和b的值 //一般法 int c = a; a = b; b = c; printf("%d\n", a); printf("%d\n", b); return 0; }
2、加减法
int main() { int a = 3, b = 5; //加减法 a = a + b; b = a - b; //b = a + b - b a = a - b; 这种写法的缺陷:a,b非常大,求和超过整型的最大值 printf("%d\n", a); printf("%d\n", b); return 0; }
3、异或
异或操作符的特点:
a^a = 0
0^a = a
int main() { int a = 3, b = 5; //异或 a = a ^ b; b = a ^ b; //b = a ^ b ^ b = a ^ 0 a = a ^ b; printf("%d\n", a); printf("%d\n", b); return 0; }
三、统计二进制中1的个数
思路一:
循环进行以下操作,直到n被缩减为0:
1. 用该数据模2,检测其是否能够被2整除
2. 可以:则该数据对应二进制比特位的最低位一定是0,否则是1,如果是1给计数加1
3. 如果n不等于0时,继续1
int NumberOf1(int n) { int count = 0; while(n) { if(n%2==1) count++; n = n/2; } return count; }
上述方法缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。
思路二:
一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测,具体如下
int NumberOf1(unsigned int n) { int count = 0; int i = 0; for(i=0; i<32; i++) { if(((n>>i)&1) == 1) count++; } return count; }
思路二优点:用位操作代替取模和除法运算,效率稍微比较高
缺陷:不论是什么数据,循环都要执行32次
思路三
采用相邻的两个数据进行按位与运算
int NumberOf1(unsigned int n) //把有符号当成无符号数 { int count = 0; while (n) { count++; n = n & (n - 1); //效果:把二进制中最右边的1去掉了 //n = 15 //1111 - n 1110 - n-1 //1110 - n 1101 - n-1 //1100 - n 1011 - n-1 //1000 - n 0111 - n-1 //0000 - n } return count; }
可以观察下:此种方式,数据的二进制比特位中有几个1,循环就循环几次,而且中间采用了位运算,处理起来比较高效
思路四:
1 << i;
依次顺序移动遍历二进制中的每一位
通过这种左移操作,我们可以生成一个只在第i位上为1的数字,其他位都为0。例如:
- i=0: 0001
- i=1: 0010
- i=2: 0100
- i=3: 1000
- ... 以此类推
int NumberOf1(int n) { // write code here int i = 0, count = 0; for (i = 0; i < 32; i++) { if (n & (1 << i)) count++; } return count; }
今天就先到这了!!!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。