C语言训练:三个字符串比较大小,实现两个整数数的交换统计二进制中1的个数

简介: C语言训练:三个字符串比较大小,实现两个整数数的交换统计二进制中1的个数

一、编写程序,输入三个字符串,比较它们的大小,并将它们按由小到大的顺序输出。要求用函数、指针实现。要求:要采用函数调用,并用指向函数的指针作为函数的参数。

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的个数

二进制中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;
}

今天就先到这了!!!

看到这里了还不给博主扣个:

⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!

有问题可以评论或者私信呢秒回哦。

相关文章
|
3月前
|
存储 C语言
【C语言】基础刷题训练4(含全面分析和代码改进示例)
【C语言】基础刷题训练4(含全面分析和代码改进示例)
|
1月前
|
C语言 C++
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
|
2月前
|
存储 C语言
【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]=&quot;hello&quot;`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
|
2月前
|
存储 Serverless C语言
【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数
本文介绍了C语言中的`gets`和`puts`函数,`gets`用于从标准输入读取字符串直至换行符,并自动添加字符串结束标志`\0`。`puts`则用于向标准输出打印字符串并自动换行。此外,文章还详细讲解了`str`系列字符串操作函数,包括统计字符串长度的`strlen`、复制字符串的`strcpy`、比较字符串的`strcmp`以及拼接字符串的`strcat`。通过示例代码展示了这些函数的具体应用及注意事项。
121 7
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
2月前
|
C语言
C语言 字符串操作函数
本文档详细介绍了多个常用的字符串操作函数,包括 `strlen`、`strcpy`、`strncpy`、`strcat`、`strncat`、`strcmp`、`strncpy`、`sprintf`、`itoa`、`strchr`、`strspn`、`strcspn`、`strstr` 和 `strtok`。每个函数均提供了语法说明、参数解释、返回值描述及示例代码。此外,还给出了部分函数的自实现版本,帮助读者深入理解其工作原理。通过这些函数,可以轻松地进行字符串长度计算、复制、连接、比较等操作。
|
3月前
|
C语言
【C语言】字符串及其函数速览
【C语言】字符串及其函数速览
30 4
|
3月前
|
C语言
【C语言篇】字符和字符串以及内存函数详细介绍与模拟实现(下篇)
perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
61 0
|
3月前
|
存储 安全 编译器
【C语言篇】字符和字符串以及内存函数的详细介绍与模拟实现(上篇)
当然可以用scanf和printf输入输出,这里在之前【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)已经讲过了,这里就不再赘述,主要介绍只针对字符的函数.
54 0
|
3月前
|
C语言
【C语言刷题训练】——第7节(含代码与分析思路)
【C语言刷题训练】——第7节(含代码与分析思路)