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

目录

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

1.不使用函数指针作为参数,并自己模拟strcmp。

2、不使用函数指针作为参数,使用strcmp

3、使用函数指针作为参数进行比较

4、使用指针数组存储字符串后比较

二、一道变态的面试题不能创建临时变量(第三个变量),实现两个整数数的交换

1、一般法(不符合) 

2、加减法

3、异或

三、统计二进制中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;
}

今天就先到这了!!!

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/251729.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

首字母转大写在线工具

具体请前往&#xff1a;在线首字母转大写

【教3妹学编程-算法题】统计区间中的整数数目

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 2哥 : 3妹早啊&#xff0c;大周末的起这么早&#xff…

【MyBatis-Plus】MyBatis进阶使用

目录 一、MyBatis-Plus简介 1.1 介绍 1.2 优点 1.3 结构 二、MyBatis-Plus基本使用 2.1 配置 2.2 代码生成 2.3 CRUD接口测试 三、MyBatis-Plus策略详解 3.1 主键生成策略 3.2 雪花ID生成器 3.3 字段自动填充策略 3.4 逻辑删除 四、MyBatis-Plus插件使用 4.1 乐…

软件设计师——信息安全(一)

&#x1f4d1;前言 本文主要是【信息安全】——软件设计师——信息安全的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

JSON Ajax

1. JSON概念 JSON&#xff0c;全称JavaScript Object Notation&#xff0c;即JavaScript对象表示法&#xff0c;是一种轻量级的数据交换格式。它基于JavaScript的子集&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。 JSON的诞生&#xff0c;是为了解决电…

【LeetCode刷题-排序】--179.最大数

179.最大数 思路&#xff1a; 方法&#xff1a;自定义排序 class Solution {public String largestNumber(int[] nums) {if(nums null || nums.length 0){return "";}//将每个数字转换成字符串String[] strs new String[nums.length];for(int i 0;i < nums.l…

[ 8 种有效方法] 如何在没有备份的情况下恢复 Android 上永久删除的照片?

我们生命中最重要的时刻&#xff0c;但这样做有缺点&#xff0c;其中之一就是数据丢失的风险。您可能倾向于定期删除无意义的照片&#xff0c;同时保存可爱的照片&#xff0c;从而使您的 Android 设备井井有条。然而&#xff0c;有些人在删除自己珍视的图像时不小心犯了错误。您…

c语言链表的基本操作

在C语言中&#xff0c;链表是一种常见的数据结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含一个数据元素和一个指向下一个节点的指针。链表的基本操作包括创建、插入、删除和遍历等。 下面是一个简单的链表节点结构体定义&#xff1a; struct Node { int da…

开源 LLM 微调训练指南:如何打造属于自己的 LLM 模型

一、介绍 今天我们来聊一聊关于LLM的微调训练&#xff0c;LLM应该算是目前当之无愧的最有影响力的AI技术。尽管它只是一个语言模型&#xff0c;但它具备理解和生成人类语言的能力&#xff0c;非常厉害&#xff01;它可以革新各个行业&#xff0c;包括自然语言处理、机器翻译、…

算法训练第三十九天|62. 不同路径、63. 不同路径 II

62. 不同路径&#xff1a; 题目链接 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有…

边缘分布函数

以二维随机变量说明。 二维随机变量的分布函数为&#xff0c;随机变量的分布函数为&#xff0c;随机变量的分布函数为。 称为二维随机变量关于的边缘分布函数。 称为二维随机变量关于的边缘分布函数。

Python基础05-函数

零、文章目录 Python基础05-函数 1、函数的作用及其使用步骤 &#xff08;1&#xff09;函数的作用 在Python实际开发中&#xff0c;我们使用函数的目的只有一个“让我们的代码可以被重复使用” 函数的作用有两个&#xff1a; ① 代码重用&#xff08;代码重复使用&#xf…

部署LVS的NET模式

实验准备 #负载调度器# 192.168.116.40 #内网 12.0.0.100 #外网 先添加双网卡 #web服务器# 192.168.116.20 #web1 192.168.116.30 #web2 #nfs共享服务# 192.168.116.10 #nfs systemctl stop firewalld setenforce 0 1.nfs共享文件 1…

完美解决:ftp连接遇到 ftp: connect: 拒绝连接 或者 ftp: connect: 没有到主机的路由

目录 问题&#xff1a; 问题一&#xff1a;ftp: connect: 拒绝连接 问题二&#xff1a;ftp: connect: 没有到主机的路由 解决方法&#xff1a; 问题&#xff1a; 问题一&#xff1a;ftp: connect: 拒绝连接 问题二&#xff1a;ftp: connect: 没有到主机的路由 解决方法&#…

Post Json数据与Form表单数据转换器

具体请访问&#xff1a;在线Json转Form表单参数工具

计网 - TCP重传策略大揭秘:确保数据可靠传输的秘诀

文章目录 Pre为什么需要设计重传机制四种常见的重传机制超时重传快速重传SACKD-SACK Pre 计网 - 传输层协议 TCP&#xff1a;TCP 为什么握手是 3 次、挥手是 4 次&#xff1f; 计网 - TCP三次握手原理全曝光&#xff1a;深度解析与实战演示 计网 - TCP四次挥手原理全曝光&am…

浅析LDPC软解码对SSD延迟的影响--part2

2.LDPC&#xff08;Low Density Parity Check&#xff09;纠错码 LDPC码是一种基于稀疏矩阵的纠错码&#xff0c;它由一组奇偶校验方程组成&#xff0c;其中大部分元素为零&#xff0c;因此得名“低密度”。LDPC码的优点是可以有效地纠正大量的错误&#xff0c;尤其是对于高密…

DevOps搭建(十)-安装Harbor镜像仓库详细步骤

1、下载Harbor 官方地址&#xff1a; https://goharbor.io/ 下载地址&#xff1a; https://github.com/goharbor/harbor/tags 选择文档版本进行下载&#xff0c;这里我们选择v2.7.2版本 2、上传到服务器并解压 上传压缩包到服务器后&#xff0c;解压到/usr/local目录下&a…

gin框架

1、go run 文件名 如遇上面问题&#xff1a;go mod tidy 2、查看配置信息&#xff1a;go env 3、windows用set修改配置文件&#xff0c;linux用export修改 4、中间件 (1)、全局中间件 r.Use(中间件函数名()) (2)、Next()方法 (3)、局部中间件 直接将中间件函数名用在…