数据存储模式与验证方法 & 字符串系列函数 & 指针 & 冒泡排序

【 数据存储模式与验证方法 & 字符串系列函数 & 指针数组& 数组指针 &冒泡排序】


前言

介绍数据存储模式及验证方法(使用指针强转)、大小端问题、指针数组与数组指针、冒泡排序、字符串操作函数、获取随机数、交换函数等操作


一、数据存储模式与验证方法

  • 内存划分基本单位 :字节

1. windows数据存储模式

小端存储 : 低地址 向 高地址存储
(低地址位置 存放 低位数据)
低地址
低位
0x78 0x56 0x34 0x12

2. LInux操作系统

一般是大端存储 : 高地址 向 低地址存储
(高地址位置 存放 低位数据)
高地址
低位
0x12 0x34 0x56 0x78

3. 验证方式

(1)指针验证
(2)联合体union验证

#include<stdio.h>

int main()
{
//指针强转
	int val = 0x12345678;
	char* pc = (char*)&val;
	if (*pc == 0x78)
		printf("小端存储模式\n");
	else
		printf("大端存储模式\n");
}

二、指针数组 数组指针 交换数值函数

(1) []的优先级 > 指针 *

(2)指针数组 与数组指针

(3)字符串类型数组

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>


//数据下标的封装  交换数据
void Swap_one(int* arr, int j, int i)		//将交换的下标传入 java无指针 常用此方法交换数据
{
	int temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

void Swap_str(const char** arr,const char** b)
{
	const char *temp = *arr;
	*arr = *b;
	*b = temp;
}

void Swap_two(const char* arr[], int i, int j)
{
	const char* temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

void Sort_Str(const char** arr,int len)
{
	assert(*arr != NULL);	//断言  参数安全的校验  ----debug版本调试版本有效  release版本无效
	int i = 0, j = 0;
	const char* temp;
	bool flag;
	for (i = 1; i < len-1; i++)
	{
		flag = false;//一趟
		for (j = 0; j <len- i - 1; j++)
		{
			if (strcmp(arr[j],arr[j+1])>0)		//字符串的比较
			{
				/*temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;*/

				//Swap_str(&arr[j], &arr[j + 1]);

				Swap_str(arr + j, arr + j + 1);

				//Swap_two(arr, j, j + 1);

				flag = true;
			}
		}
		if (!flag)		//flag==false   !逻辑非
			break;
	}
	for (int i = 0; i < len; i++)
	{
		printf("%s ",*arr);
		arr++;
	}
}

int main()
{
//  []的优先级 > 指针*
//【指针数组】
	int brr[3];		//[int][int][int]
	int* pb = brr;		//&brr[0]
	//pb+1 -->   + 1*sizeof(int)

	int *arr[3];	//[int*][int*][int*]
	//指针数组
	int** pa = arr;		//&arr[0]
	///pa+1能力  +sizeof(int*)

//【数组指针】
	int(*pc)[3] = &brr;		//区别于&brr[0]
	//pc+1 能力 +sizeof(int[3])  12字节

//【字符串类型数组】
	//定义字符串类型的数组:"abc","hello","zs";
	const char* pstr = "hello";
	const char* crr[] = { "hello","abc","zs" };
	int length = sizeof(crr) / sizeof(crr[0]);
	Sort_Str(crr,length);
	/*printf("%s", *crr);
	printf("\n%s", *(crr + 1));*/
}

三、 冒泡排序

(1)整型数组为例:交换:前者>后者 (升序)

悬挂指针(野指针):int* p;   
不能对野指针进行指针赋值操作   *p=1//err

空指针: int *p=NULL;	//#deifne NULL 0
不能对野指针 和空指针 进行解引用 
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>

void Swap(int* arr, int* b)
{
	int temp = *arr;
	*arr = *b;
	*b = temp;
}

void BubbleSort(int* arr, size_t len)
{
	assert(arr != NULL);	//断言  参数安全的校验  ----debug版本调试版本有效  release版本无效
	int i = 0, j = 0, temp = 0;
	bool flag;
	for (i = 0; i < len - 1; i++)
	{
		flag = false;//一趟
		for (j = 0; j < len - i - 1; j++)
		{
			if (arr[j ] > arr[j+1])
			{
				flag = true;
				Swap(arr + j, arr + j + 1);
				//Swap(&arr[j],&arr[j+1]);
			}
		}
		if (!flag)		//flag==false   !逻辑非
			break;
	}
}

void Printf(int *arr,size_t len)
{
	printf("\n打印: ");
	for (size_t i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n\n");
}

int main()
{
	//数组冒泡排序(升序) 时间复杂度:O(n^2)  空间复杂度O(1)		//4与4是否交换  导致的数据的稳定性
	int arr[] = { 1,4,5,3,6,4,7,8,10 };
	int brr[] = { 1,3,5,7,8,9};
	size_t len = sizeof(arr) / sizeof(arr[0]);
	size_t len2 = sizeof(brr) / sizeof(brr[0]);
	BubbleSort(arr, len);		//考虑传参arr是空地址的情况
	BubbleSort(brr, len2);		//优化问题 传入数组已经是升序数组
	Printf(arr, len);
	Printf(brr, len2);
}


四、字符串操作函数 及 获取随机数:

1. str系统函数:

strlen 求字符串长度 (int Str_Length(char* arr))
strcmp 字符串比较 (void Str_Copy(char* arr, char* brr))
strcpy 字符串拷贝 (int Str_cmp(char* arr, char* brr))
strcat 字符串连接 (void Str_Cat(char* arr, char* brr))

2. mem内存系列函数:

memset 内存初始化逐字节
memcpy 内存拷贝
memmove 内存移动

3. 其他相关函数:

atoi() 字符串类型 转 整型
itoa() 整型 转 字符串
strtok()—>分割 头文件 string.h

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<time.h>

//打印数组
void Show(int arr[], int len)  //int *arr -->地址别名 数组传参 退化成指针,地址传递比值传递节省存储空间;
{
	//int len = sizeof(arr) / sizeof(arr[0]);	//arr退化成指针,数组不在同一作用域,求出的len值为1(4/4=1);
	for (int i = 0; i < len; i++)
	{
		printf("%d\t ", arr[i]);
	}
}

//打印字符串
void Show(char* arr, int len)  //int *arr -->地址别名 数组传参 退化成指针,地址传递比值传递节省存储空间;
{
	for (int i = 0; i < len; i++)
	{
		printf("%c ", arr[i]);
	}
}

//统计数据内奇数的个数
size_t Data_Number(int* arr, int len)
{
	size_t count = 0;
	for (int i = 0; i < len; i++)
	{									//奇数的二进制末端为1  偶数的二进制末端为0
		if (arr[i] % 2 != 0)			//若用二进制来判断   (arr[i]&0x1)==1  (奇数)  按位与&  
		{
			count++;
		}
	}
	return count;
}

//统计字符串长度
int Str_Length(char* arr)
{
	int count = 0, i = 0;
	while (arr[i] != '\0')
	{
		count++;
		i++;
	}
	return count;
}

//拷贝字符串
void Str_Copy(char* arr, char* brr)
{
	int i = 0;
	while (brr[i] != '\0')
	{
		arr[i] = brr[i];
		i++;
	}

	/*int i = 0;						//第二种写法
	while (arr[i] = brr[i])
	{
		i++;
	}*/

	/*int i = 0, j = 0;						//第三种写法
	while (arr[i++] = brr[j++]);		'\0'==0  */
	arr[i] = '\0';
}

//字符串连接函数
void Str_Cat(char* arr, char* brr)
{
	int i = 0, j = 0;
	while (arr[i] != '\0')		//法一
		i++;
	while (arr[i] = brr[j])		
	{
		i++;
		j++;
	}
	arr[i] = '\0';

	/*while (brr[j] != '\0')		//法二
	{
		arr[i] = brr[j];
		i++;
		j++;
	}*/

	/*while (arr[i++] = brr[j++]);*/		//法三


	//int i = 0, j = 0;						//法四
	//size_t len = strlen(arr);
	//i += len;		//i定位到arr数组有效数据的后方\0的位置
	//while (arr[i] = brr[j])
	//{
	//	i++;
	//	j++;
	//}


}

//字符串比较函数
int Str_cmp(char* arr, char* brr)
{
		int i = 0;

		while (arr[i] == brr[i])
		{
			if (arr[i] == '\0')
				return 0;
			i++;
		}
		return arr[i] < brr[i] ? -1 : 1;

		/*while (('\0' != arr[i]) || ('\0' != brr[i]))
		{
			if (arr[i] > brr[i]) {
				return 1;
			}
			else if (arr[i] < brr[i]) {
				return -1;
			}
			i++;
		}
		return 0;*/
}

int main()
{
//【获取随机值】
	int drr[10];
	srand(10);//随机种子,10定值 输出也为随机定值 运行将10每次都改变 可获得随机数
	
	time_t t;		//time_t  :定义的typedef  long long time_t ; 实际上就是long long类型,所以我们可以理解为创建一个64位的时间变量nowtime。
	time(&t);
	srand((unsigned int)t);

	int num=rand()%100;		//rand()产生随机数
	printf("\n随机值: %d \n", num);	//伪随机值

//【atoi函数】 字符串 转 整型 
	int val = atoi("-100");
	printf( "atoi函数: %d \n", val);

//【_itoa函数】整型 转 字符串
//			  100  8  "144"
//			  100  4   "64"
	char buff[128];
	_itoa(-1, buff, 2);
	printf("_itoa函数: %s\n", buff);

//【strtok函数】
	char prr[] = "2023-11-07  20:53:20";
	/*char* res = strtok(prr, "-");
	printf("strtok函数 : %s\n", res);

	char* res2= strtok(NULL, "-");		///给NULL   以上一次分割位置 继续以“-”分割
	printf("strtok函数 : %s\n", res2);

	strtok(NULL, "-");*/
	strtok(prr, " ");
	//strtok(NULL, " ");  //得到“20:53:20”
	char * res4=strtok(NULL, ":");
	printf("strtok函数 : %s\n", res4);		//得到20


	size_t lenone = strlen("hello"); //5 //size_t是sizeof关键字运算结果的类型。(注:sizeof是关键字,并非运算符)

	int arr[] = { 1,2,3,4,5 };
	int len = sizeof(arr) / sizeof(arr[0]);	//只有在同一作用域  才能求数组长度

	Show(arr, len);			//函数名即函数入口地址
	size_t count= Data_Number(arr, len);
	printf("\n数组奇数个数:%d\n\n", count);


	char brr[] = "hello";
	int n=Str_Length(brr);
	Show(brr, n);
	printf("\n字符串数组长度:%d\n", n);


	char a[20];
	memset(a, 0, sizeof(char) * 20);			//等价于char a[10]={0};
	strcpy(a, "hello");
	printf("\n原数组a: %s\n", a);

	char b[] = "world";
	Str_Copy(a, b);
	printf("\n拷贝后数组a: %s\n", a);

	char c[] = "student";
	Str_Cat(a, c);
	printf("\n连接后数组a: %s\n", a);

	int ab = Str_cmp(a,b);
	printf("\n两数组: %d\n", ab);
}


五、补充知识点

  • 指针大小 x86 4字节 ;x64 8字节

  • 地址总线 =》找内存地址

  • win32 win64 win128(范围逐渐增大)

  • x86–win32 地址总线 2^32寻址能力 32位操作系统

  •   				 (内存) 2^32字节=4GB	0X0000 0000
      								        0Xffff ffff
    
  • x64–win64 8字节表示寻址

  • Linux win32系统 0X0000 0000

  • 【3G 内部】

      		128M :非法访问区(禁止访问区)
      		
      		代码区(存汇编语言) :高级语言-->汇编语言-->机器码(01组合)
      		
      		数据区域.data :存全局变量 静态局部变量 静态全局变量 ( static )字符串常量 (eg: const char*="hello")
      		
      		堆区.heap:内存由自己申请(malloc realloc calloc) 自己释放(free)		
      		         (堆的内存默认:1.5~1.9G)  动态内存开辟 (内存泄漏检测功能)vld检测  
      	        	(内存的分配方式:低地址->高地址)				
      	  	  
      	  	栈.stack :函数局部变量	内存由系统分配 系统回收  	
      	  	          (栈的内存默认:windows:1M   Linux:10M)
      		         (内存的分配方式:高地址->低地址)
    
  • 【1G 】内核使用

  •   		0xffff ffff
    

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值