Pascal混合字符串的比较

xier对我做的那个“Excel图片导入程序”又有意见了,说是导入后的次序不对,99居然比101还大。我晕,自己试了下,还真的排错了。我靠,BorlandVcl 是怎么搞的,文件的读取函数居然能读得这么糟糕。也罢,回家自己写下文件名的排序就行了。

本以为是件十分简单的事,随便弄个快速或者冒泡排序法进去就成了。没想到回家一弄,傻眼了,怎么排都错。对着排序法研究了大半夜,没错呀,是这样排的,可是排出来的怎么老是错……。偷偷的抽了根烟(可不能让xier知道),突然灵感焕发出智慧女神的光芒,问题就在于字符串大小的比较上。哈哈,哈哈哈哈,这下可有救了,差点就要被xier看扁——不过捉bug居然要靠灵感,还真越混越回去了。呵呵,不理了,先记下思路要紧(发现我的废话还真多)……

首先是字符串的分类,我自己把它分为四种:汉字、英文字母、数字、符号,这四种类型的大小次序是这样的:汉字 > 英文字母 > 数字 > 符号。对于两个字符串str1str2,每个字符串中可以含有不同中类型字符,可以有汉字+数字+符号,可以有英文字母+数字+汉字。对于这个混合的字符串,比较的方法如下:

1、  获取str1str2的首个字符的类型type1type2

2、  获取str1str2中与首个字符相连、并类型相同的后续字符,直接该字符类型与首字符不同为止,并与首字符合成一个临时的字符串tmp1tmp2

3、  比较type1type2是否不同,如果不同,通过“汉字 > 英文字母 > 数字 > 符号”比较,返回比较结果,程序结束。如果相同,进入下一歩。

4、  比较tmp1tmp2的长度,如果长度不等,较长的为大,返回比较结果,程序序结果,如果长度相等,执行下一歩。

5、  比较tmp1tmp2是否相等,如果不等,直接比较两个字符串大小,返回比较结果,程序结束。如果相等,执行下一步。

6、  str1截去开头的tmp1str2截去开头的tmp2,用剩下的字符串再从第一歩执行起(这就是传说中的递归)。

好了,看看代码(当然是Pascal了):

 

先看类型的定义:

 

type

  WCharType = (Chinese,Letter,Number,Symbol);  // 定义一个字符类型

       Chinese是汉字,Letter是字母,Number是数字,Symbol是符号。下面是获取字符串首字符的函数:

 

(**

  * 获取字符串首字符的类型

 **)

function GetFirstType(str : string) : WCharType;

var

  CType : WCharType;

begin

 

  if str[1] in ['0'..'9'] then CType := Number

  else if str[1] in ['a'..'z','A'..'Z'] then CType := Letter

       else if ord(str[1]) > 128 then CType := Chinese

            else CType := Symbol;

 

  result := CType;

end;

 

       嗯,再一个获取与首字符相同类型的后续字符,并组成字符串:

(**

  * 获取与首位字符同种类型的后续字符,直到字符类型变动

 **)

function GetFirstList(str : string) : string;

var

  i, len : Cardinal;

  firstType, otherType : WCharType;

  s : string;

begin

  i := 1;

  firstType := GetFirstType(str);

  len := Length(str);

 

  if firstType = Chinese then //如果是汉字,i要占两位

    inc(i,2)

  else

    inc(i,1);

 

  while i <= len do

  begin

    otherType := GetFirstType(str[i]);

 

    if otherType <> firstType then  break;

 

    if otherType = Chinese then

      inc(i,2)

    else

      inc(i,1);

 

  end;

 

  s := Copy(str,1,i-1);

 

  result := s;

end;

        下面看看比较函数的主函数:

 

(**

  * 比较两个混合字符串

 **)

function WCharCompare(str1, str2 : string ) : integer;

var

  tmp1, tmp2 : string;

  flag : integer;

begin

      

  flag := NullCompare(str1, str2); //空字符串的比较

  if flag <> 2 then result := flag

  else

  begin

    tmp1 := GetFirstList(str1);

    tmp2 := GetFirstList(str2);

 

    if GetFirstType(tmp1) = GetFirstType(tmp2) then

    begin       //相同类型的比较

      if Length(tmp1) = Length(tmp2) then

      begin       //等长比较

        if tmp1 > tmp2 then result := 1

        else if tmp1 < tmp2 then result := -1

          else      //两者相等

          begin

            tmp1 := Copy(str1,Length(tmp1)+1,Length(str1));

            tmp2 := Copy(str2,Length(tmp2)+1,Length(str2));

            result := WCharCompare(tmp1,tmp2);

          end;

      end

      else        //不等长比较

        if Length(tmp1) > Length(tmp2) then result := 1

        else result := -1;

    end

    else        //不同类型的比较

      result := NotSameCompare(tmp1,tmp2);

  end;

end;

上面是比较字符串的入口函数。另有个辅助的(怕弄在一个函数里面大长,不好看),用于首字符不同类型的字符串的比较,用在上面函数的倒数第三行

(**

  *两个不同类型的字符串比较

 **)

function NotSameCompare(str1, str2 : string) : integer;

var

  type1, type2 : WCharType;

begin

  type1 := GetFirstType(str1);

  type2 := GetFirstType(str2);

  case type1 of

    Chinese : result := 1;

 

    Letter :

    begin

      if type2 = Chinese then result := -1

      else result := 1;

    end;

 

    Number :

    begin

      if type2 = Symbol then result := 1

      else result := -1;

    end;

 

    Symbol : result := -1;

 

  else

    result := 0;

  end;

 

end;

      

       对了,还有呢,如果两个字符串中有一个是空的,或者两个都是空的呢?看下面:

 

(**

  * 含有零的字符串的比较

 **)

function NullCompare(str1, str2 : string) : integer;

begin

  if (Length(str1) > 0) and (Length(str2) > 0) then result := 2

  else if (Length(str1) >0) and (Length(str2) = 0) then result := 1

  else if (Length (str1) = 0) and (Length(str2) > 0) then result := -1

  else result := 0;

end;

 

       呵呵,完了。呀,咋这么多,惨了惨了,这么个比较法,再加上排序,再加上把图片导入Excel的过程(xier的图片都是上千计的),那真的要当机了,看再不给主程序加线程和进度栏是不行的了。

       不过是不是有更好的比较方法呢?等待着高手或者智慧女神的垂青了……

 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值