数据结构-串ADT(字符串 完成头文件string.h的实现)

串的比较实际上比较的是字符编码,这里正好深入了解一下字符编码 : 

ASCII 编码

ASCII占用8位(bit)。8个bit可以表示256个字符。

ASCII码只规定了128个字符的编码。

ASCII码的问题是字符太少,不能满足世界各国的需要。所以各国其他编码利用剩余的128个字符定义各自不同的编码。

GB2312 & GBK

汉字GB2312 使用两个字节(16位),最多表示65536个字符。

一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFEgb2312中两个字符组成的编码的字符叫做“全角”字符,而原来在127号以下的那些就叫”半角”字符了

对GB2312扩展就得到了GBK,再扩展得到GB18030(少数民族文字)。

所以,一个字节小于127的编码都按照ASCII码查,大于127的字节+之后的字节(一共两个字节16位)组成汉字的编码。

所以,“一个汉字两个英文字符”就是这么来的。

Unicode

为了统一一种编码,Unicode出现了。

Unicode 目前规划的总空间是17个平面(平面0至16),0x0000 至 0x10FFFF。最前面的65536个字符位,称为基本平面(缩写BMP) 。每个平面有 65536 个码点。

Unicode只规定了每个字符的码点,到底用什么样的字节序表示这个码点,就涉及到编码方法。

最直观的编码方案就是 UTF-32

UTF-32

由于Unicode是0x0000 至 0x10FFFF,直接用定长的4个字节来表示对应的字符

U+0000 = 0x0000 0000U+597D = 0x0000 597D这样好处是直观,但是太浪费空间了。

UTF-8

UTF-8是一种变长的编码,从1字节到4字节。

英文字母为1个字节,汉字为3个字节。

Unicode符号范围 | UTF-8编码方式

(十六进制) | (二进制)

—————————————————————–

0000 0000-0000 007F | 0xxxxxxx

0000 0080-0000 07FF | 110xxxxx 10xxxxxx

0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Reference 字符编码的演变

中国人民通过对 ASCII 编码的中文扩充改造,产生了 GB2312 编码,可以表示6000多个常用汉字。汉字实在是太多了,包括繁体和各种字符,于是产生了 GBK 编码,它包括了 GB2312 中的编码,同时扩充了很多。中国是个多民族国家,各个民族几乎都有自己独立的语言系统,为了表示那些字符,继续把 GBK 编码扩充为 GB18030 编码。每个国家都像中国一样,把自己的语言编码,于是出现了各种各样的编码,如果你不安装相应的编码,就无法解释相应编码想表达的内容。终于,有个叫 ISO 的组织看不下去了。他们一起创造了一种编码 UNICODE ,这种编码非常大,大到可以容纳世界上任何一个文字和标志。所以只要电脑上有 UNICODE 这种编码系统,无论是全球哪种文字,只需要保存文件的时候,保存成 UNICODE 编码就可以被其他电脑正常解释。UNICODE 在网络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8个位和 16个位。于是就会有人产生疑问,UTF-8 既然能保存那么多文字、符号,为什么国内还有这么多使用 GBK 等编码的人?因为 UTF-8 等编码体积比较大,占电脑空间比较多,如果面向的使用人群绝大部分都是中国人,用 GBK 等编码也可以。

字符串的比较

1.

str1 =  "abc"

str2 =  "abcd"

str1 < str2 

 

2.

str1 = "abcd"

str2 = "abce"

由于ascii码 e > d

str1 < str2

 

下面我们使用c语言简单的实现c语言的<string.h>

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

//状态码
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define EQ 0
#define GT 1
#define EQ 0 //相等 
#define GT 1 //大于
#define LT -1 //小于

#ifndef _STATUS_H_ //如果系统已经定义下列宏 就不在重复定义
	#define OVERFLOW -2 //堆栈上溢 超过所能表示的最大整数
	#define UNDERFLOW -3 //堆栈下溢 超过所能表示的最小负数
#endif

typedef int Status;

#define MAX_SIZE 1024

/*typedef struct{
	char ch[MAX_SIZE + 1]; //定长方式实现字符串 (浪费空间)
	int length;
}SString;*/

//使用指针实现
//串的堆式顺序存储结构(Beap)
typedef struct {
	char * ch; //如果是非空串 按照需要长度分配内存
	int length; //串的当前长度 length代替'\0'的作用
}HString;

void InitString_Heap(HString * str){
	str->ch = NULL;
	str->length = 0;
}

void PrintHeapString(HString * str){
	if(str->length == 0 || !str->ch){
		printf("堆字符串为空!\n");
		return ;
	}
	for(int i = 0; i < str->length; i++){
		printf("%c",str->ch[i]);
	}
}

//为串赋值 值为字符串首地址chars
Status StrAssign_HeapString(HString * str, char * chars){
	int len = strlen(chars);
	if(!len){
		return ERROR;
	}
	InitString_Heap(str);
	str->ch = (char *)malloc(len * sizeof(char));
	if(!str->ch){
		exit(OVERFLOW);
	}
	for(int i = 0; i < len; i++){
		str->ch[i] = chars[i];
	}
	str->length = len;
	return OK;
}

Status IsEmpty_HeapString(HString * str)
{
	if(str->length == 0 || !str->ch)
	{
		return TRUE;
	}
	return FALSE;
}

Status StrCopy_HeapString(HString * destStr, HString * srcStr){
	InitString_Heap(destStr);
	if(IsEmpty_HeapString(srcStr)){
		printf("被复制对象为空!\n");
		return ERROR;
	}
	destStr->ch = (char * )malloc(sizeof(char) * srcStr->length);
	if(!destStr->ch) exit(OVERFLOW);
	for(int i = 0; i < srcStr->length; i++){
		destStr->ch[i] = srcStr->ch[i];
	}
	destStr->length = srcStr->length;
	return OK;
}

//堆字符串的大小比较
Status StrCompare_HeapString(HString * str1 , HString * str2)
{
	/*for (int i = 0; i < str1->length && str2->length ;i++)
	{
		if(str1->length == str2->length ){
			if(str1->ch[i] < str2->ch[i])
				return -1;
			else if(str1->ch[i] > str2->ch[i]){
				return 1;
			}
		}*/
	// str1 = str2 返回0 str1 < str2 返回-1 str > str2 返回1
	//上面的写法较为麻烦建议使用下面的写法 str1 > str2 返回正数 str1 < str2 返回负数
	for (int i = 0 ; i < str1->length && i < str2->length ; i++)
	{ 
		if(str1->length == str2->length){
			return str1->ch[i] - str2->ch[i];
		}
		return str1->length - str2->length;
	}
}

//字符串连接 返回的字符串存放在deststr
Status StrConcat_HeapString(HString * deststr,HString * str1,HString * str2)
{
	InitString_Heap(deststr);
	deststr->ch = (char *)malloc(sizeof(HString));
	if(IsEmpty_HeapString(str1) || IsEmpty_HeapString(str2))
		return ERROR;
	if(!deststr) return OVERFLOW;
	deststr->length = str1->length + str2->length;
	for(int i = 0;i < str1->length;i ++){
		deststr->ch[i] = str1->ch[i];
	}
    for(i = 0;i < str2->length;i ++){
		deststr->ch[str1->length + i] = str1->ch[i];
	}
	return OK;
}

//截取字符串 从pos开始截取长度为len的字符串 截取的部分储存在deststr
Status SubString_HeapString(HString * deststr,HString * str,int pos,int len)
{
	InitString_Heap(deststr);
	if(IsEmpty_HeapString(str) || pos < 1 || pos + len -1 > str->length || len < 0 || pos > str->length)
		return ERROR;
	deststr->ch = (char *)malloc(len * sizeof(char));
	if(!deststr) return OVERFLOW;
    for(int i = 0;i < len;i++)
	{
		deststr->ch[i] = str->ch[pos - 1 + i];
	}
	deststr->length = len;
	return OK;
}

// 寻找从pos开始子串在父串中的位置 返回位置
int Index_HeapString(HString * parent , HString * child , int pos)
{
	if(pos < 0) return ERROR;
	HString * substr = (HString * )malloc(sizeof(HString)); //在父串中截取
	InitString_Heap(substr);
	int i = pos;
	while(i + child->length - 1 <= parent->length){
		//在父串中截取
		SubString_HeapString(substr , parent , i , child->length);
        if(StrCompare_HeapString(substr , child) !=  EQ){
			i++;
		}
		else{
			return i;
		}
	}
	free(substr);
	return 0;
}

// 从字符串str中pos开始删除len长度的字符串
Status Delete_HeapString(HString * str , int pos , int len)
{
    if(IsEmpty_HeapString(str) || pos < 1 || pos + len - 1 > str->length || len < 0)
		return ERROR;
	for(int i = pos - 1 ; i + len < str->length ; i++)
	{
		str->ch[i] = str->ch[i + len];	
	}
	str->length -= len;
	//减少分配空间
	str->ch = (char *)realloc(str->ch , str->length * sizeof(char));
	return OK;
}

//在str的第pos个位置插入insertstr
Status Insert_HeapString(HString * str , HString * insertstr , int pos)
{
	if(pos < 1 || pos > str->length + 1)
	{
		return ERROR;
	}
	if(IsEmpty_HeapString(str) || IsEmpty_HeapString(insertstr)) return ERROR;
	str->ch = (char *)realloc(str->ch , (str->length + insertstr->length) * sizeof(char));
	if(!str->ch) return OVERFLOW;
	//从插入位置开始后移 移出位置插入
	for(int i = str->length - 1; i >= pos - 1; i--)
	{
		str->ch[i + insertstr->length] = str->ch[i];
	}
	//插入
	for(i = 0;i < insertstr->length;i++)
	{
		str->ch[pos - 1 + i] = insertstr->ch[i];
	}
	str->length += insertstr->length;
	return OK;
}

//将str中的oldstr替换为newstr
Status Replace_HeapString(HString * str , HString oldstr , HString newstr )
{
		if(IsEmpty_HeapString(str)) return ERROR;
		int pos = Index_HeapString(str , & oldstr , 1);
		while(pos != 0)
		{
			Delete_HeapString(str , pos , oldstr.length);
			Insert_HeapString(str , &newstr , pos);
			pos += newstr.length;
			pos =  Index_HeapString(str , & oldstr , pos);
		}
		return OK;
}

int main()
{
	HString * str1 = (HString * )malloc(sizeof(HString));
	HString * str2 = (HString * )malloc(sizeof(HString));
    HString * str3 = (HString * )malloc(sizeof(HString));
	HString * str4 = (HString * )malloc(sizeof(HString));
    HString * str5 = (HString * )malloc(sizeof(HString));

	printf("将str1赋值给str2:\n");
	StrAssign_HeapString(str1,"abcde");
    StrCopy_HeapString(str2,str1);

	printf("str1:");
	PrintHeapString(str1);
	printf("\n");
	printf("str2:");
	PrintHeapString(str2);
	printf("\n");
	
	printf("比较str1和str2:\n");
	printf("%d",StrCompare_HeapString(str1,str2));

    printf("连接str1和str2并储存在str3输出str3:");
	StrConcat_HeapString(str3,str1,str2);
    PrintHeapString(str3);
	printf("\n");
  
	printf("从str1的第二个字符开始截取出3个储存在str4并输出str4:");
	SubString_HeapString(str4,str1,2,3);
    PrintHeapString(str4);
	printf("\n");
	
	printf("从abcde中寻找bcd并输出出现的位置:");
	StrAssign_HeapString(str1,"abcde");
	StrAssign_HeapString(str5,"bcd");
	printf("%d",Index_HeapString(str1,str5,1));
	printf("\n");

	printf("删除str1的第一个字符:");
	Delete_HeapString(str1,1,1);
    PrintHeapString(str1);
	printf("\n");

	printf("在abcde中的第一个位置插入bcd:");
	StrAssign_HeapString(str1,"abcde");
	StrAssign_HeapString(str2,"bcd");
	Insert_HeapString(str1,str2,1);
    PrintHeapString(str1);
	printf("\n");

    printf("将abcde中的a换为bcd:");
	StrAssign_HeapString(str1,"abcde");
	StrAssign_HeapString(str2,"bcd");
	StrAssign_HeapString(str3,"a");
	Replace_HeapString(str1 ,*str3, *str2);
    PrintHeapString(str1);
	printf("\n");

	free(str1);
	free(str2);
	free(str3);
	free(str4);
    free(str5);
	return 0;
}

输出结果

 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值