【C语言】指针的进阶(三)—— 模拟实现qsort函数以及指针和数组的笔试题解析

news2024/11/17 11:40:57

目录

1、模拟实现qsort函数

1.1、qsort函数的回顾

1.2、模拟实现qsort函数 

2、指针和数组笔试题解析

2.1、一维数组

2.2、字符数组


1、模拟实现qsort函数

1.1、qsort函数的回顾

要模拟实现qsort函数,就要了解清楚qsort函数的参数以及使用方式。

我们先回顾一下qsort函数:

qsort是一个库函数,底层使用的是快速排序的方式对数据进行排序。头文件:<stdlib.h>

这个函数可以直接使用用来排序任意类型的数据。

qsort函数定义原型: 

void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));

  • void* base:待排序数组的第一个元素的地址
  • size_t num:待排序数组的元素个数
  • size_t size:以字节为单位,待排序数组中一个元素的大小。
  • int (*compar)(const void*,const void*):函数指针,指向一个比较函数,用来比较两个元素,由用户自行创建并封装。

形参中为什么用的是void*:

void* 是无具体类型的指针,不能进行解引用操作符,也不能进行+-整数的操作,它是用来存放任意类型数据的地址(可以理解为垃圾桶,什么都能装,当需要用时再强制类型转换为需要的类型)。只有void*被允许存放任意类型数据的地址,如果是其他类型的指针编译器会报错。正是因为定义qsort函数时用的是void*,qsort函数才可以排序任意类型的数据。

1.2、模拟实现qsort函数 

使用【冒泡排序】的算法,模拟实现一个排序函数 bsort ,可以用来排序任意类型的数据。

首先,先用冒泡排序实现排序整型数据:

void bsort(int arr[], int sz)
{
	int i = 0;
	for ( i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for ( j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bsort(arr, sz);

	int i = 0;
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);

	}
	printf("\n");
	return 0;
}

        在这个冒泡排序排序整型数据的代码的基础上进行改造。

        首先改造的第一部分就是函数参数,这里的函数参数被写死了只能进行int类型的排序,因此为了让其他类型的数据也能够传入到bsort函数中进行排序,我们这里需要使用指针来接收传入参数。

        参数一:而指针的选择上又只有 void* 最为符合,因为它是用来存放任意类型数据的地址(可以理解为垃圾桶,什么都能装,当需要用时再强制类型转换为需要的类型)。

        参数二:对照库函数qsort的定义中,第二个参数为待排序数组的元素个数,因此我们也用个 size_t num 存放待排序数组的元素个数。

当前,我们可以通过参数一和参数二知道起始位置地址(void* base)和元素个数(num),但是仅仅知道起始地址和元素个数是不够的,因为不知道一个元素有多大的,一次需要跳过多少个字节,5个?10个?

        参数三:因此还需要一个参数记录一个元素的大小 size_t size。

到此,我们先把注意里放在函数内部,函数内部循环的趟数和一趟的次数是不需要改造的,只有红色框框内的交换区域需要改造,因为整数的大小可以用><=号比较,但是结构体数据是不能直接使用><=号来比较的。排序一个整型需要整型的方法,排序一个结构体需要结构体的方法,因此如果需要排序各种各样的类型时,不能固定写死交换区域的比较方式,这就需要用户自行创建比较函数来实现。

        参数四而我们这里只需要使用函数指针 int (*cmp)(const void* e1,const void* e2)  接收用户传递的比较函数即可。e1和 e2都是指针,分别存放着一个要比较的元素的地址。

 对红框区域进行修改:

注意,在cmp函数中传入base参数时,需要对base强制类型转换char*,因为只有char的步长最短,可以满足所有类型的交换。假设是int类型的话,+1直接跳过4个字节,那么如果要交换一个char类型或者short类型的数据,那就无法做到交换了。

 【交换int类型数据的完整代码】

swap(char* buf1, char* buf2, size_t size)
{
    一个字节一个字节地交换
	int i = 0;
	for ( i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}


//模拟库函数qsort
void bsort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for ( i = 0; i < num - 1; i++)
	{
		int j = 0;
		for ( j = 0; j < num - 1 - i; j++)
		{
			//if(arr[j]>arr[j+1])
			if (cmp((char*)base + size * j, (char*)base + size * (j + 1)) > 0) //大于0时,证明j的元素大于j+1的元素,所以要交换位置
			{
				//交换
				swap((char*)base + size * j, (char*)base + size * (j + 1), size);
			}
		}
	}
}


//用户自行创建
int cmp_in(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bsort(arr, sz,sizeof(arr[0]),cmp_in);

	int i = 0;
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);

	}
	printf("\n");
	return 0;
}

【图解】

同理,结构体类型数据也能交换。 

 【交换结构体类型数据的完整代码】

swap(char* buf1, char* buf2, size_t size)
{
	//一个字节一个字节地交换
	int i = 0;
	for ( i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bsort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for ( i = 0; i < num - 1; i++)
	{
		int j = 0;
		for ( j = 0; j < num - 1 - i; j++)
		{
			//if(arr[j]>arr[j+1])
			if (cmp((char*)base + size * j, (char*)base + size * (j + 1)) > 0) //大于0时,证明j的元素大于j+1的元素,所以要交换位置
			{
				//交换
				swap((char*)base + size * j, (char*)base + size * (j + 1), size);
			}
		}
	}
}


struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

int main()
{
	struct Stu arr[] = { {"zhangsan",22},{"lisi",26},{"wangwu",20} };

	int sz = sizeof(arr) / sizeof(arr[0]);
	bsort(arr, sz,sizeof(arr[0]),cmp_stu_age);


	printf("\n");
	return 0;
}

例子中是按照年龄排序。使用调试检查一下,确实完成了交换:

如果想要进行降序排序的话,只需要将用户自行创建并封装的 cmp函数 中return的e1和e2交换即可,下面以cmp_int为例:

swap(char* buf1, char* buf2, size_t size)
{
	//一个字节一个字节地交换
	int i = 0;
	for ( i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bsort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for ( i = 0; i < num - 1; i++)
	{
		int j = 0;
		for ( j = 0; j < num - 1 - i; j++)
		{
			//if(arr[j]>arr[j+1])
			if (cmp((char*)base + size * j, (char*)base + size * (j + 1)) > 0) //大于0时,证明j的元素大于j+1的元素,所以要交换位置
			{
				//交换
				swap((char*)base + size * j, (char*)base + size * (j + 1), size);
			}
		}
	}
}

int cmp_in(const void* e1, const void* e2)
{
	return *(int*)e2 - *(int*)e1;  //进行【降序】排序
}

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bsort(arr, sz,sizeof(arr[0]),cmp_in);


	return 0;
}

2、指针和数组笔试题解析

计算下面运算输出的值

2.1、一维数组

int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));

【答案】32位环境下运行的结果

【解析】

printf("%d\n", sizeof(a));

sizeof(数组名),这里的数组名表示整个数组,所以计算的是整个数组的大小,4(int字节数)*4=16。

printf("%d\n", sizeof(a + 0));

a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+0还是首元素的地址,32位环境下,地址大小就是4。

printf("%d\n", sizeof(*a));

 a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址。*a 就是 首元素,大小就是4 ,特别的:*a == *(a+0) == a[0]

printf("%d\n", sizeof(a + 1));

 a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+1就是第2个元素的地址,32位环境下,地址大小就是4。

printf("%d\n", sizeof(a[1]));

 a[1]就是数组的第二个元素,这里计算的就是第二个元素的大小,int就是4。

printf("%d\n", sizeof(&a));

 &a - 是取出数组的地址,但是数组的地址也是地址,32位环境下,是地址就是4。数组的地址数组首元素的地址 的本质区别是类型的区别,并非大小的区别。

printf("%d\n", sizeof(*&a));

 对数组指针解引用访问一个数组的大小,单位是字节,也可以理解成 *&相互抵消即sizeof(*&a) =  sizeof(a),sizeof(数组名),这里的数组名表示整个数组,所以计算的是整个数组的大小。

printf("%d\n", sizeof(&a + 1));

 &a数组的地址,&a+1还是地址,是地址就是4。

printf("%d\n", sizeof(&a[0]));

 &a[0]是首元素的地址,计算的是地址的大小4。

printf("%d\n", sizeof(&a[0] + 1));

 &a[0]是首元素的地址,&a[0]+1就是第二个元素的地址,大小4。

2.2、字符数组

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

【答案】 32位环境下运行的结果

【解析】

printf("%d\n", sizeof(arr));

 数组名arr单独放在sizeof内部,计算的是整个数组的大小6。

printf("%d\n", sizeof(arr + 0));

arr是首元素的地址==&arr[0],是地址就是4。

  • 指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节
  • 指针变量是用来存放地址的,地址存放需要多大空间,指针变量的大小就是几个字节
  • 32位环境下,地址是32个二进制位,需要4个字节,所以指针变量的大小就是4个字节
  • 64位环境下,地址是64个二进制位,需要8个字节,所以指针变量的大小就是8个字节
printf("%d\n", sizeof(*arr));

 arr是首元素的地址,*arr就是首元素,大小就是1。

printf("%d\n", sizeof(arr[1]));

 arr[1]就是第2个元素,大小就是1。

printf("%d\n", sizeof(&arr));

 &arr是数组的地址,sizeof(&arr)就是4

printf("%d\n", sizeof(&arr + 1));

&arr+1 是跳过数组后的地址, 是地址就是4。

printf("%d\n", sizeof(&arr[0] + 1));

 第二个元素的地址,是地址就是4。

看完sizeof了,再来看一组strlen

printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));

 【答案】32位环境下运行的结果

1、随机值

2、随机值

3、err

4、err

5、随机值

6、随机值-6

7、随机值-1

【解析】

注意:题目中使用的是char arr[] = {'a','b','c','d','e','f'};的创建方式,该方式不会自动在末尾添加\0,而strlen只有遇到\0才会停下

printf("%d\n", strlen(arr));

arr是首元素的地址,就是从arr第一个元素开始,找\0,由于不知道后面\0在哪个位置,因此是随机值。

printf("%d\n", strlen(arr + 0));

 arr是首元素的地址, arr+0还是首元素的地址,与上一题同理,是随机值。

printf("%d\n", strlen(*arr));

 arr是首元素的地址, *arr就是首元素,srtlen需要接收一个地址,而这里传递的是一个字符,站在strlen的角度,认为传参进去的'a'-97就是地址,97作为地址,直接进行访问,就是非法访问,因此程序会报错。

printf("%d\n", strlen(arr[1]));

 arr第二个元素地址'b',与上一题同理,非法访问程序报错。

printf("%d\n", strlen(&arr));

 &arr表示整个数组的地址,向后查找\0,因此是随机值。

printf("%d\n", strlen(&arr + 1));

  &arr表示整个数组的地址,&arr + 1表示跳过整个数组(6个字节)向后查找\0,因此是随机值-6。

printf("%d\n", strlen(&arr[0] + 1));

 &arr[0]表示首元素地址,&arr[0] + 1跳过一个元素,向后查找\0,因此是随机值-1。

下面换成char arr[] = "abcdef";再来看看

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

【答案】32位环境下运行的结果

 

【解析】

printf("%d\n", sizeof(arr));

 sizeof(数组名)表示整个数组,sizeof是会把\0也计入在内的,因此是7。

printf("%d\n", sizeof(arr + 0));

 arr+0表示首元素地址,是地址就是4。

printf("%d\n", sizeof(*arr));

 *arr表示首元素,首元素是char类型,所以就是1。

printf("%d\n", sizeof(arr[1]));

 第二个元素,所以就是1。

printf("%d\n", sizeof(&arr));

&arr表示整个数组的地址, 是地址就是4

printf("%d\n", sizeof(&arr + 1));

 &arr表示整个数组的地址, &arr + 1表示跳过整个数组,是地址就是4。

printf("%d\n", sizeof(&arr[0] + 1));

 第一个元素的地址,是地址就是4。

换成srtlen

printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));

【答案】

1、6

2、6

3、err

4、err

5、6

6、随机值

7、5

【解析】

printf("%d\n", strlen(arr));

 统计\0前有多少个元素,就是6。

printf("%d\n", strlen(arr + 0));

 arr+0等于首元素地址,统计\0前有多少个元素,就是6。

printf("%d\n", strlen(*arr));

 *arr表示首元素,把元素作为地址直接进行访问,就是非法访问,因此程序会报错。

printf("%d\n", strlen(arr[1]));

 与上一题同理,非法访问程序报错。

printf("%d\n", strlen(&arr));

 &arr表示整个数组的地址,向后找\0所以是6。

printf("%d\n", strlen(&arr + 1));

  &arr表示整个数组的地址,&arr + 1表示跳过了一整个数组,跑到了\0之后,无法知道下一个\0在哪里,所以是随机值。

printf("%d\n", strlen(&arr[0] + 1));

 &arr[0] + 1 表示第二个元素的地址,向后找\0等于5。


如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch实战:实现Cifar10彩色图片分类

目录 前言 一、Cifar10数据集 class torch.utils.data.Dataset torch.utils.data.DataLoader 二、定义神经网络 普通神经网络: 定义损失函数和优化器 训练网络-Net CPU训练 模型准确率 ​编辑 GPU训练 训练网络-LeNet 模型准确率 点关注&#xff0c;防走丢&#x…

9月15日、9月18日上课内容 Zookeeper集群 + Kafka集群

Zookeeper 本章结构 Zookeeper 概述 Zookeeper 定义 *&#xff08;了解&#xff09; Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 Zookeeper 工作机制 *****&#xff08;非常重要&#xff0c;需要掌握&#xff09; Zookeeper从设计模式…

用低代码开发工具高效构建企业门户

企业信息门户EIP是指将各种应用系统、数据资源和互联网资源统一集中&#xff0c;根据每个用户使用特点和角色的不同&#xff0c;形成个性化的应用界面&#xff0c;并通过对事件和消息的处理、传输把用户有机地联系在一起。 企业随着业务的发展&#xff0c;运作的复杂度也在不断…

第三十二章 Objects

[toc] 第三十二章 Objects Objects 对象类简介 IRIS 通过以下对象类提供对象技术&#xff1a; %Library.RegisteredObject、 %Library.Persistent %Library.SerialObject。 下图展示了这些类之间的继承关系&#xff0c;以及它们的一些参数和方法。 %Library 包的类名称可以…

Vite + Vue3 使用cdn引入依赖 vite cdn vue3 cdn vite引入cdn

Vite Vue3 使用cdn引入依赖 vite cdn vue3 cdn vite引入cdn 1、安装插件2、在 vite.config.js 引用3、main.js4、打包测试 1、安装插件 npm install element-plus --save2、在 vite.config.js 引用 import { defineConfig } from vite import vue from vitejs/plugin-vue// …

用开源代码构建机器人需要考虑的问题

导读或许你正在考虑&#xff08;或正在进行&#xff09;将机器人使用开源软件推向市场。这个机器人是基于 linux 构建的。也许你正在使用机器人操作系统&#xff08;ROS&#xff09;或任务导向操作套件&#xff08;MOOS&#xff09;&#xff0c;或者是另外一个可以帮助你简化开…

007 数据结构_堆——“C”

前言 本文将会向您介绍关于堆Heap的实现 具体步骤 tips&#xff1a;本文具体步骤的顺序并不是源代码的顺序 typedef int HPDataType; typedef struct Heap {HPDataType* _a;int _size;int _capacity; }Heap;初始化 void HeapCreate(Heap* hp, HPDataType* a, int n) {hp-&…

AT32F407裸机工程创建

1、建立工程文件夹 2、找到AT提供DEMO例程&#xff0c;我们需要复制相关的内核文件出来&#xff0c;到我们创建的这个文件夹 1)将库文件拿过来 2)内核文件 3)启动文件 我把F407相关的内核文件都复制过来&#xff0c;然后具体看自己使用哪个型号&#xff0c;工程自己添加对应的文…

避雷!这9本期刊已被剔除!9月SCI/SSCI目录已更新(附2023年WOS历次更新全目录)

2023年9月20日&#xff0c;科睿唯安更新了Web of Science核心期刊目录。 此次更新后SCIE期刊目录共包含9490本期刊&#xff0c;SSCI期刊目录共包含3552本期刊。此次SCIE & SSCI期刊目录更新&#xff0c;与上次更新&#xff08;2023年8月&#xff09;相比&#xff0c;共有9本…

共育电商人才,引领行业发展丨知了汇智与协作时代达成战略合作

随着新一轮科技革命和产业革命的深入发展&#xff0c;数字经济正在成为重塑全球经济结构、改变全球竞争格局的关键力量&#xff0c;数字经济与实体经济的深度融合&#xff0c;也将是未来经济发展的重要动力。数字经济的发展正在催生电子商务模式不断创新&#xff0c;新业态下企…

安防监控系统/视频云存储/视频监控平台EasyCVR无法级联上级平台,该如何解决?

安防视频监控系统EasyCVR平台能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频流&#xff0c;也…

《动手学深度学习》(pytorch版+mxnet版)2023最新

我又来推书了&#xff0c;这次分享的这本书可是重量级&#xff0c;目前已经被55个国家300所大学用于教学&#xff0c;同时受到了学术界与工业界的强烈推荐。 这本书就是李沐、阿斯顿张、立顿、斯莫拉四位大佬联合编写的《动手学深度学习》。本书面向中文读者&#xff0c;能运行…

第二十四章 原理篇:DBB

上班真的好累哦&#xff01; 理论上应该从RepVGG开始写重参化的&#xff0c;而且上星期就打算写来着&#xff01; 但是上班真的好累哦完全提不起精神在周末打字看论文&#xff01; 参考教程&#xff1a; https://arxiv.org/pdf/2103.13425.pdf https://github.com/DingXiaoH/D…

自己实现一个简单的vhost-net

框架 vhost在网络中的位置如图&#xff1a; 要学习具体的框架可以看我之前的文章vhost-net--------深入了解Virtio-networking和vhost-net 接下来&#xff0c;我们自己实现一个vhost. vhost-net代码 在代码中写了详细注释&#xff0c;就直接上代码了 #include <stdio.h…

期权是什么?一分钟带你玩转期权策略!

很多人问我期权是什么&#xff0c;这个问题怎么回答呢&#xff1f;首先期权是一种交易模式&#xff0c;如同股票期货一样&#xff0c;但它又不同于股票和期货&#xff0c;因为它有自己的交易规则和特性&#xff0c;期权更多是一种工具&#xff0c;可以做空大盘对冲下跌风险&…

0018Java程序设计-springboot智慧环卫养管作业平台

文章目录 摘 要目 录系统设计开发环境 摘 要 本智慧环卫养管作业平台就是建立在充分利用现在完善科技技术这个理念基础之上&#xff0c;并使用IT技术进行对环卫养管作业的管理&#xff0c;从而保证环卫养管作业能够高效的进行&#xff0c;可以实现环卫养管作业的在线管理&…

健康云HIS系统源码,满足基层医疗机构业务需求,提供挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生站和护士站等功能

云his系统源码 二级医院HIS系统全套源代码 自主研发&#xff0c;自主版权 一款满足基层医疗机构各类业务需要的健康云HIS系统。该系统能帮助基层医疗机构完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生站和护士站等一…

wabp.m 代码注释(便于算法快速理解)

算法效果: 波峰和起点检测效果: function [r,pk] = wabp(Araw, Offset,Scale, Fs) % r = wabp(Araw,Offset,Scale, Fs); % Input: Araw (125Hz sampled) waveform in wfdb-MIT format, % Offset, Scale % Araw = 血压波形 % Offset=偏移(信号减去或者加上偏移恢复成…

启山智软/O2O商城

文章目录 启山智软介绍一、O2O商业模式是什么二、启山智软O2O商城管理系统1.O2O商城系统2.多种商业形态的O2O商城系统1、类似蜜雪冰城的合作加盟模式2、类似优衣库的连锁直营模式3、类似京东到家的同城/本地服务平台 O2O商城开发具备的特色功能&#xff1a;部分源码分享 启山智…

MTBF、MTTR、MTTA 和 MTTF

了解一些最常见的事件指标 在当今永不停机的世界中&#xff0c;中断和技术事件比以往任何时候都更加重要。故障和停机期间会带来现实后果&#xff0c;错过截止时间、付款逾期、项目延迟。 这就是为什么公司必须量化和跟踪有关正常运行时间、停机期间以及团队解决问题的速度和…