计算机中的非数值处理的对象基本上都是字符串,目前对于字符串的使用和处理也越来越常见,也是很多公司笔试和面试的常见内容。
    串是由零个或多个字符组成的有限序列,一般记为
    s = 'a1a2……an', n表示字符串的长度。
    字符串需要 注意
    1. 称两个字符串是相等的,只有当两个串的长度相等,并且对应位置上的字符都相等时才可以。
    2. 空格串和空串不是一回事。因为空格也是字符。
    
    
    串的表示方法有以下3种:
    1. 定长顺序存储方式。
    这种方法用一组地址连续的存储单元存储串值。因为这种方法为每个定义的串变量分配一个固定长度的存储区,所以一般要预先知道所要使用的串的大概的长度,并且经常造成存储空间的浪费,因为很可能预先分配的这段空间没有全部被占用。
    2. 堆分配存储表示
    根据串的大小动态的分配所需的存储空间。显然这种方法比较好,对存储空间的利用率较高,应用也较为广泛。
    串的结构定义:
    
typedef struct
{
    char *ch;
    int length;
}HString;
     串的基本操作函数如下:
//生成一个字符串
Status StrAssign(HString &T, char *chars)
{
	int i = 0,j = 0;
	char *c = NULL;
	//释放T原来所占的空间
	if(T.ch)
	{
		free(T.ch);
	}
	//求字符串的长度
	for(i=0,c = chars; *c ; ++i,++c);//正确的写法
	//然后根据长度分配空间,并且将字符串的内容复制到空间中
	if(!i)
	{
		T.ch = NULL;
		T.length = 0;
	}
	else
	{
		if(!(T.ch = (char*)malloc(i*sizeof(char))))
		{
			exit(OVERFLOW);
		}
		for(j=0;j<i;j++)
		{
			T.ch[j] = chars[j];
		}
		T.length = i;
	}
	return OK;
}
    这里,求字符串的长度用了比较笨的一种方法,一个字符依次计算,直到读到字符结束符。
    这个循环我写错了两次:
    第一次:
    char c;
    for(i=0,c = chars[0]; c ; ++i,++chars);
    显然,c作为控制循环结束的条件,却一直没变。
    第二次:
     for(i=0, c = chars[0]; c ; ++i,c++);
    输入参数chars所指向的字符串中才具有结束符‘\0’,而我只是让c再不停的增加,c是我定义的一个char型变量,因此永远不会结束,或是按ASCII码加到255的时候才会结束。
    这个地方其实是用C语言的字符串处理函数strlen()也可以完成求长度的操作,

//比较两个字符串
int StrCompare(HString S, HString T)
{
	int i;
	for(i=0;i<S.length&&T.length;i++)
	{
		if(S.ch[i] != T.ch[i])
		{
			return S.ch[i] - T.ch[i];
		}
	}
	return S.length - T.length; //0是通过长度的比较产生的。
}
   无需多说,只需要注意相等的时候是通过两个字符串的长度比较完成的。

//字符串的连接操作
Status Concat(HString &T, HString S1, HString S2)
{
	int i = 0;
	if(T.ch)
	{
	    free(T.ch);
        }
	if(!(T.ch = (char*)malloc((S1.length + S2.length) * sizeof(char))))
	{
		exit(OVERFLOW);
	}
	for(i=0;i<S1.length;i++)
	{
		T.ch[i] = S1.ch[i];
	}
	T.length = S1.length + S2.length;
	for(i=S1.length;i<T.length;i++)
	{
		T.ch[i] = S2.ch[i-S1.length];
	}
	return OK;
}
    联结操作也很简单,分配所需空间,然后依次将字符赋值到合适的位置上即可。注意数组的下标的操作。

//定位获得一个子串
Status subString(HString &Sub,HString S, int pos, int len)
{
	int i = 0;
	if(pos<1 || pos>S.length || len <0 || len>S.length - pos + 1)
	{
		return ERROR;
	}
	if(Sub.ch)
	{
		free(Sub.ch);
	}
	//如果是空串
	if(!len)
	{
		Sub.ch = NULL;
		Sub.length = 0;
	}
	//如果非空串
	else
	{
		Sub.ch = (char*)malloc(len*sizeof(char));
		if(!Sub.ch)
		{
		   exit(OVERFLOW);
		}
		for(i=pos-1;i<pos+len-1;i++) //i的起始值,循环控制条件的结束值,总共是len个数据。
		{
			Sub.ch[i-pos+1] = S.ch[i];
		}
		//子串的长度设置
		Sub.length = len;
	}
	
	return OK;
    }
    获得子串的时候,要注意一些边界条件,防止用户输入参数有误带来的错误。 另外就是最后给子串赋值的循环操作,注意i的结束条件,注意子串数组下标的处理。
    当然, 这都是C语言中的处理方法,按照一个一个的字符来进行处理。
    
 3. 串的链式存储结构
    和链表的存储结构类似,只不过结构中的数据元素是字符串。这个时候仍然存在问题,那就是该为数据元素分配多大的空间。当然,可以预先分配一个较大的空间。如下:
    
    #define CHUNKSIZE  80
    typedef struct Chunk{
        char ch[CHUNKSIZE];
        struck Chunk *next;
    }
    也可以只定义一个字符串指针:
    
   typedef struct Chunk{
        string * ch;
        struck Chunk *next;
    }
    这个时候需要注意的是,每次需要为将要存入节点的字符串动态分配一个空间,然后让指针域ch只向这个存储空间。
   当然,以上只是定义了节点的数据类型,在实际应用中,需要定义串的结构:
   
    typedef struct{
        Chunk *head, *tail;
        int curlen; //字符串的长度
    }
     设尾指针的作用是方便进行连个链表的联结,但是要注意处理串尾的无效字符。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值