免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2816 | 回复: 9
打印 上一主题 下一主题

这个convertChinese函数是什么意思呢? [复制链接]

论坛徽章:
8
白羊座
日期:2015-01-21 18:35:03巳蛇
日期:2015-02-03 17:30:37处女座
日期:2015-02-03 17:31:02羊年新春福章
日期:2015-02-03 17:31:21巨蟹座
日期:2015-02-05 16:01:06申猴
日期:2015-02-05 16:01:31摩羯座
日期:2015-02-05 16:01:41酉鸡
日期:2015-02-05 16:02:37
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-11-30 10:41 |只看该作者 |倒序浏览
有个Perl程序,需要转换为C/C++程序,但是遇到了一个较为棘手的函数,根本就不知道他要做什么。
该函数如下:

  1. sub convertChinese
  2. {
  3.   my ($x,$n, $len, $l, $h);
  4.   my (@c, @d);

  5.   $x = shift;
  6.   return unless defined $x;

  7.   @c = unpack("C*", $$x);
  8.   @d = ();

  9.   $len = @c;
  10.   for ($n = 0; $n < $len; $n++)
  11.   {
  12.                 if ($c[$n] == 194)
  13.                 {
  14.                   next;
  15.                 }
  16.                 elsif ($c[$n] == 195)
  17.                 {
  18.                   $l = $c[$n+1] % 16;
  19.                   $h = ($c[$n+1] - $l)/16;
  20.                   push (@d, (12+($h-8))*16+$l);
  21.                   $n++;
  22.                 }
  23.                 else
  24.                 {
  25.                   push(@d, $c[$n]);
  26.                 }
  27.   }
  28.   $$x = pack "C*",@d;
  29. }
复制代码


请赐教!

论坛徽章:
8
白羊座
日期:2015-01-21 18:35:03巳蛇
日期:2015-02-03 17:30:37处女座
日期:2015-02-03 17:31:02羊年新春福章
日期:2015-02-03 17:31:21巨蟹座
日期:2015-02-05 16:01:06申猴
日期:2015-02-05 16:01:31摩羯座
日期:2015-02-05 16:01:41酉鸡
日期:2015-02-05 16:02:37
2 [报告]
发表于 2005-11-30 10:48 |只看该作者
函数里面用到了pack、unpack,我也看了这篇 pack/unpack用法----心得筆記 ,可是还不明白是什么意思。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
3 [报告]
发表于 2005-11-30 14:06 |只看该作者
[quote]原帖由 feeling 于 2005-11-30 10:41 发表
有个Perl程序,需要转换为C/C++程序,但是遇到了一个较为棘手的函数,根本就不知道他要做什么。
该函数如下:

  1. sub convertChinese
  2. {
  3.   my ($x,$n, $len, $l, $h);
  4.   my (@c, @d);

  5.   $x = shift;
  6. ... [/quote]
  7. [code]
  8. sub convertChinese
  9. {
  10. #--$x 是一个reference to scalar variable
  11. my ($x,$n, $len, $l, $h);
  12.   my (@c, @d);
  13. #---从第一个叁数抓进来...
  14.   $x = shift;
  15.   return unless defined $x;
  16. #把$$x 依unsign integer unpack出来.....
  17. #存放在@c中...
  18.   @c = unpack("C*", $$x);
  19.   @d = ();

  20.   $len = @c;
  21. #--针对每一个char....去比对数值.....
  22.   for ($n = 0; $n < $len; $n++)
  23.   {
  24.                 if ($c[$n] == 194)
  25.                 {
  26.                   next;
  27.                 }
  28.                 elsif ($c[$n] == 195)
  29.                 {
  30.                   $l = $c[$n+1] % 16;
  31.                   $h = ($c[$n+1] - $l)/16;
  32.                   push (@d, (12+($h-8))*16+$l);
  33.                   $n++;
  34.                 }
  35.                 else
  36.                 {
  37.                   push(@d, $c[$n]);
  38.                 }
  39.   }
  40. #---处理完後...将数值在pack回原来的$$x....
  41.   $$x = pack "C*",@d;
  42. }
复制代码


注意这个subroutine...因为对reference 作动作..所以即便他没有return任何数值..
但是$$x的数值已经更动了.....
他应该是在作过滤的动作吧.....

论坛徽章:
8
白羊座
日期:2015-01-21 18:35:03巳蛇
日期:2015-02-03 17:30:37处女座
日期:2015-02-03 17:31:02羊年新春福章
日期:2015-02-03 17:31:21巨蟹座
日期:2015-02-05 16:01:06申猴
日期:2015-02-05 16:01:31摩羯座
日期:2015-02-05 16:01:41酉鸡
日期:2015-02-05 16:02:37
4 [报告]
发表于 2005-11-30 15:31 |只看该作者
原帖由 apile 于 2005-11-30 14:06 发表
注意这个subroutine...因为对reference 作动作..所以即便他没有return任何数值..
但是$$x的数值已经更动了.....
他应该是在作过滤的动作吧.....


多谢指教,应该是对文本流中的特殊字符做过滤的吧。
这个程序在调用该函数后对文本流做了截取操作:

  1.     convertChinese($Msg);
  2.     @at = ();
  3.     for ($i = 0; $i < 16; $i++)
  4.     {
  5.       $str = substr($Msg, $i*254, 254);
  6.       if (!defined($str) || length($str) <= 0)
  7.       {
  8.         push(@at, "");
  9.       }
  10.       else
  11.       {
  12.         push(@at, "$str");
  13.       }
  14.     }
复制代码


根据该函数名称大致上可以推断是针对中文字符的一些操作,因为后面有substr的操作,如果有中文字符的话可能会出错。

论坛徽章:
0
5 [报告]
发表于 2005-11-30 18:31 |只看该作者


  1.                 if ($c[$n] == 194)
  2.                 {
  3.                   next;
  4.                 }
  5.                 elsif ($c[$n] == 195)
  6.                 {
  7.                   $l = $c[$n+1] % 16;
  8.                   $h = ($c[$n+1] - $l)/16;
  9.                   push (@d, (12+($h-8))*16+$l);
  10.                   $n++;
  11.                 }
  12.                 else
  13.                 {
  14.                   push(@d, $c[$n]);
  15.                 }
复制代码

意思是过滤0xC2,过滤0xC3并且把他后面的紧跟着的字节高4位“12+($h-)*16”,
不知道什么用,

  1.     @at = ();
  2.     for ($i = 0; $i < 16; $i++)
  3.     {
  4.       $str = substr($Msg, $i*254, 254);
  5.       if (!defined($str) || length($str) <= 0)
  6.       {
  7.         push(@at, "");
  8.       }
  9.       else
  10.       {
  11.         push(@at, "$str");
  12.       }
  13.     }
复制代码

分成254字节每块的字符串,

没有上下问,看不明白convertChinese有什么用,

想不出c2,c3有什么特别,

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
6 [报告]
发表于 2005-12-01 08:44 |只看该作者
原帖由 angleeye 于 2005-11-30 18:31 发表
[code]

                if ($c[$n] == 194)
                {
                  next;
                }
                elsif ($c[$n] == 195)
                {
                  $l = $c[$n+1 ...


我也不知道..
但是如果他是 "\" 或是某些特殊字符...
也许他们代码碰到这些字符...会有问题...
那这样过滤就有意义了....

论坛徽章:
8
白羊座
日期:2015-01-21 18:35:03巳蛇
日期:2015-02-03 17:30:37处女座
日期:2015-02-03 17:31:02羊年新春福章
日期:2015-02-03 17:31:21巨蟹座
日期:2015-02-05 16:01:06申猴
日期:2015-02-05 16:01:31摩羯座
日期:2015-02-05 16:01:41酉鸡
日期:2015-02-05 16:02:37
7 [报告]
发表于 2005-12-26 17:03 |只看该作者
最后是要执行一个数据库的入库操作,如果有特殊字符可能会有问题吧。

论坛徽章:
0
8 [报告]
发表于 2005-12-27 21:45 |只看该作者
很讨厌可读性差的代码,虽然效率很高

论坛徽章:
0
9 [报告]
发表于 2005-12-27 21:48 |只看该作者
原帖由 RobinHoo 于 2005-12-27 21:45 发表
很讨厌可读性差的代码,虽然效率很高


什么叫做可读性差?那是对你而言吧?
多数人并不觉得pack/unpack可读性差。

论坛徽章:
0
10 [报告]
发表于 2005-12-28 10:12 |只看该作者
unpack和pack不是很难理解的!
不知道是自己的习惯还是真的阅读能力上有问题。我认为好的/有可读性的代码是从变量命名就开始做起的。大量无意义的变量名,令人很头痛。即使我能像机器一样分析出代码执行的结果,但那时对于代码的物理理解,不是对于它解决问题的算法的理解。最近我在用perl重写CNPRINT,一个中国人写得很好的一个解决UNIX下汉字/日文/韩文打印的程序。他的源代码是公布出来的,但是可读性很差。我不能责备他,因为这只是一个医学博士的业余爱好而已。不过,这么好的解决方法没有被推广和被主流linux用于解决CJK打印很大程度上由于代码的可读性。我之所以要用perl重写是想有人能看懂我代码后再用C改写成功能更强大的代码。下面是我代码的片断。可能很不perl化。但是很容易读懂。
<CODE>
#!/usr/bin/perl -w
our @ParameterList;
our $ValidParameters="SioHtc";
our $DEBUG=1;
our $SILENT=0;
our @Input;
our @InputBuff;
our @Output;
our @OutputBuff;
our $Language="auto";
our @CodeTypes=("shiftjis","gb2312","big5","gbk","jis");
our @CharUsage;
our $InUseCode;

sub convert2Unicode
{
        my $code=shift;
        my $code_type=shift;
        local $FileName;
        local $CodeType;
        foreach $CodeType (@CodeTypes)
        {
                $FileName="/CNPRN/CODE/".$CodeType.".txt";
                next if (($code_type ne "auto") and ($CodeType ne $code_type));
                if (!(open(CodeFile,$FileName)))
                {
                        print STDERR "Unicode covert file open error of codetype $CodeType!\nPlease check the file path $FileName!\n";
                        return 0 if ($code_type ne "auto");
                }
                my @FileBuff=<CodeFile>;
                close(CodeFile);
                foreach my $LineBuff (@FileBuff)
                {
                        next if ($LineBuff!~/^0[xX]/);
                        chomp $LineBuff;
                        ($Code,$Unicode)=(split(/\t/,$LineBuff));
                        if ($code==hex($Code))
                        {
                                $InUseCode=$CodeType;
                                close(CodeFile);
                                return hex($Unicode);
                        }
                }
        }
        return 0;
}

sub updateCharUsage
{
        my $Code=shift;
        local $i;
        for($i=0;$i<@CharUsage;$i++)
        {
                last if ($CharUsage[$i]{Code}==$Code);
        }
        $CharUsage[$i]{Code}=$Code;
        $CharUsage[$i]{Freq}++;
        $CharUsage[$i]{CodeType}=$InUseCode;
}

sub getCharFreq
{
        my $Code=shift;
        local $i;
        for($i=0;$i<@CharUsage;$i++)
        {
                return $CharUsage[$i]{Freq} if ($CharUsage[$i]{Code}==$Code);
        }
        return 0;
}

sub getCharOrd
{
        my $Code=shift;
        local $i;
        for($i=0;$i<@CharUsage;$i++)
        {
                return $i if ($CharUsage[$i]{Code}==$Code);
        }
        return -1;
}

sub errorHandler
{
        my $ErrorMsg=shift;
        my @ErrorPrg=caller;
        my $DisplayMsg=($SILENT==0)?$ErrorMsg."\n".($DEBUG?"In function $ErrorPrg[0]() of file $ErrorPrg[1] at line #$ErrorPrg[2].\n":""):"";
        system("time /T");
        die($DisplayMsg);       
}

sub getParameterValue
{
        my $Item=shift;
        for(my $i=0;$i<@ParameterList;$i++)
        {
                return $ParameterList[$i]{"Value"} if ($ParameterList[$i]{"Parameter"} eq $Item);
        }
        return -1;
}

sub getInput
{
        my $FileName=getParameterValue("i");
        if (length($FileName)==0)
        {
                errorHandler("Can not open the STANDARD or PIPE\n") if (!(open(INPUT,STDIN)));               
        }
        else
        {
                errorHandler("Can not open the input file $FileName\n") if (!(open(INPUT,$FileName)));
        }
        @InputBuff=<INPUT>;
        close(INPUT);
}

sub unicodeFile
{
        local $Index;
        for($Index=0;$Index<@InputBuff;$Index++)
        {
                local $LineBuff=$InputBuff[$Index];
                chomp $LineBuff;
                local $Counter=1;
                for(my $SubIndex=0;$SubIndex<length($LineBuff);$SubIndex++)
                {
                        local $BinaryCode=ord(substr($LineBuff,$SubIndex,1));
                        local $Unicode;
                        $Unicode=convert2Unicode($BinaryCode,$Language);
                        updateCharUsage($Unicode) if (($Unicode!=$BinaryCode) and ($Unicode!=0));
                        if ($Unicode==0)
                        {
                                $SubIndex++;
                                $BinaryCode=$BinaryCode*256+ord(substr($LineBuff,$SubIndex,1)) ;
                                $Unicode=convert2Unicode($BinaryCode,$Language);
                        }
                        errorHandler("Can not convert $Language code $BinaryCode to Unicode, which is located in line $Index column $SubIndex!\n") if ($Unicode==0);
                        $Input[$Index][$Counter]=$Unicode;
                        updateCharUsage($Unicode);
                        $Counter++;                       
                }
                $Input[$Index][0]=$Counter-1;
        }
}
</CODE>
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP