找回密码
 加入
搜索
查看: 16828|回复: 38

[效率算法] 练习001 - 计算字符串长度

 火... [复制链接]
发表于 2009-12-19 09:46:07 | 显示全部楼层 |阅读模式
本帖最后由 pusofalse 于 2010-2-26 23:38 编辑

以后会陆续地不定期出一些题目给新手做,当然老鸟也可以出手,但请先给新手发挥的空间。

001 - 计算字符串长度。

出题目的:“表驱动法”的初步认识。

题解:在InputBox中,用户输入不定长度的任意字符串,编程输出其长度(注,此处1个全角字符的长度同为1)。

要求:
此题中禁止使用的内置函数、API函数:
ObjCreate
ObjGet
StringSplit
StringRegExp
StringLen
strlen
lstrlenA
lstrlenW
使用纯AU3编写,禁止调用其他语言(如VBS、JAVA等)。

加分:视思路加分,10-60分不等。

拓展:
在此基础上加深难度,除上述不能使用的函数之外,再禁止使用If ... EndIf语句。

相关参考:
http://www.google.cn/search?hl=z ... 8%E9%A9%B1%E5%8A%A8

-------------------------------------------------------------------------------------
至此,诸位都有了精彩的代码,总结如下:
1、临时文件法:将字符串写入文件之后,再读取文件大小。又,此题中1个中文字符的长度同为1,但是大小却是2个字节,所以必须用正则将中文字符替换为单字节字符。此法具体见4#代码。
2、逐字符判断法:从左向右依次截取一个字符,并判断是否为空,同时记录截取的次数。直到截取到空值,输出记录次数。此法是目前应用最多的方法,但在效率上会存在问题。具体见5#、8#、10#、13#。
3、变量转化法:先将字符串转为2进制,从左向右依次截取2个字节,判断字节的低位是否为00,为00则基本确定为半角字符,否则为全角。并同时记录次数。直到循环截取完毕。具体见7#。
4、2分法:一次按2个字符进行截取,同时记录截取次数,直到截取到空值,最后根据截取次数的奇偶输出其长度。具体见12#代码。
5、表驱动法:省去一系列逻辑判断,不必创建数组,通过构造表格的方式输出长度。具体见9#、11#、14#代码。

感谢诸位参与。

评分

参与人数 1威望 +20 金钱 +100 贡献 +50 收起 理由
kn007 + 20 + 100 + 50 支持下,辛苦了

查看全部评分

发表于 2009-12-19 10:29:24 | 显示全部楼层
要求那几点也真是够苛刻的,暂未想到方法。
发表于 2009-12-19 11:18:10 | 显示全部楼层
同楼上,一点头绪都没有,直觉要用得数组.
发表于 2009-12-19 11:30:14 | 显示全部楼层
本帖最后由 马甲 于 2009-12-19 11:31 编辑

StringRegExpReplace 这个可以用是吧。
$Str = InputBox("","")
MsgBox(0,"",getlen($Str))

Func getlen($Str)
        $file = FileOpen(@ScriptDir&"\len.txt",2)
        FileWrite($file,StringRegExpReplace($Str, '[^\x00-\xff]', '0'))
        FileClose($file)
        Return FileGetSize(@ScriptDir&"\len.txt")
EndFunc
$Str = InputBox("","")
MsgBox(0,"",getlen($Str))

Func getlen($Str)
        $file = FileOpen(@ScriptDir&"\len.txt",18)
        FileWrite($file,$Str)
        FileClose($file)
        Return FileGetSize(@ScriptDir&"\len.txt")
EndFunc

评分

参与人数 1金钱 +30 收起 理由
pusofalse + 30 老鸟也来拿分~

查看全部评分

发表于 2009-12-19 11:40:08 | 显示全部楼层
方法应该很多,只是没详细测试,不知道都能用不
$Str = InputBox("","")
MsgBox(0,"",getlen($Str))

Func getlen($Str)
        $Str = StringReplace($Str," ","0")
        $len = 0
        While 1
                If $Str = "" Then Return $len
                $Str = StringTrimLeft($Str,1)
                $len = $len + 1
        WEnd
EndFunc

评分

参与人数 1金钱 +15 收起 理由
pusofalse + 15

查看全部评分

发表于 2009-12-19 12:25:45 | 显示全部楼层
本帖最后由 make2855 于 2009-12-19 12:38 编辑

看错题目了,算了
发表于 2009-12-19 13:03:12 | 显示全部楼层
有用了if,计算输入数据的字节长度
Local $Len=0,$i=1
$String = InputBox("输入数据","输入数据")
$Byte = StringToBinary ($String,2)
$Byte_Len = BinaryLen($Byte)
For $i=3 To $Byte_Len*2 Step 4
        If StringMid($Byte,$i+2,2)="00" Then
                $Len += 1
        Else
                $Len += 2
        EndIf
Next        
MsgBox(0,"输入数据的字节长:",$Len)

评分

参与人数 1金钱 +20 收起 理由
pusofalse + 20 学习了。

查看全部评分

发表于 2009-12-19 13:09:54 | 显示全部楼层
本帖最后由 landays 于 2009-12-19 13:14 编辑
$Str = InputBox ("","")
$Fi = 1
For $i = 1 to 100
IF StringTrimLeft ($Str,$i) <> "" Then $Fi = $Fi + 1 
IF StringTrimLeft ($Str,$i) = "" Then ExitLoop
Next
MsgBox (64,"",$FI)
喔 没注意看清楚不能使用IF 再想想

评分

参与人数 1金钱 +15 收起 理由
pusofalse + 15 学习了。

查看全部评分

发表于 2009-12-19 13:53:05 | 显示全部楼层
这个没有用if,使用的版主说的表驱动法
Local $A_Len[256] = [0]
Local $A_Byte[256] = [""]
Local $Len = 0,$n = 1
For $i=1 To 255
        $A_Len[$i] = 1
        $A_Byte[$i] = Hex($i,2)
Next
$String = InputBox("输入数据","输入数据","输入数据14:“《》.1ddfer23")
$Byte = StringToBinary ($String,2)
$Byte_Len = BinaryLen($Byte)
While $n < $Byte_Len*2
        $sSearch = StringMid($Byte,$n+2,2)
        For $i= 0 To 255
                StringReplace($sSearch, $A_Byte[$i], $A_Len[$i])
                $Len += @extended
        Next        
        $n += 2
WEnd
MsgBox(0,"输入数据的字节长:",$Len)

评分

参与人数 1金钱 +30 收起 理由
pusofalse + 30 学习了。

查看全部评分

发表于 2009-12-19 14:05:21 | 显示全部楼层
本帖最后由 破帽遮颜 于 2009-12-19 14:07 编辑
喔 没注意看清楚不能使用IF 再想想
landays 发表于 2009-12-19 13:09
$Str = InputBox("","")
MsgBox(0,"",getlen($Str))

Func getlen($Str)
        $len = 0
        While True
                IF StringTrimLeft ($Str,$len) = '' Then Return $len
                $len += 1
                IF StringTrimLeft ($Str,$len) <> '' Then $len = $len + 1
        WEnd
EndFunc
只是帮上面改改~

评分

参与人数 1金钱 +15 收起 理由
pusofalse + 15 学习了。

查看全部评分

 楼主| 发表于 2009-12-19 15:01:23 | 显示全部楼层
9#的代码确实是属于“表驱动”的范畴了,但在执行效率方面有些问题。

表驱动的一个简单例子:
$sString = "false"
$sVar = "0123456789" & $sString
Msgbox(0, "长度", StringLeft(StringRight($sVar, 10), 1))
发表于 2009-12-19 15:06:21 | 显示全部楼层
本帖最后由 fongshun 于 2009-12-20 08:15 编辑

我还没看懂表驱动。先应付下:
(注:此处1个全角字符长度为1。那1个汉字长度亦当做1计算了 :) )
Global $mChar=InputBox("来吧","(注:此处1个全角字符的长度为1"&@CRLF &"  此处1个汉字的长度同为1)")
Global $pos=1,$tempChar
;Global $mLength

While StringMid($mChar,1)==""
        MsgBox(0,"0字节","空字符串")
        Exit
WEnd        

Do
        $tempChar=StringMid($mChar,$pos*2)
        $pos += 1
Until $tempChar = ""

$pos -=1
$tempChar=StringMid($mChar,$pos*2-1)
Select
        Case $tempChar==""
                MsgBox(0,"字符串长度:",Int($pos*2-2))
        Case $tempChar <> ""
                MsgBox(0,"字符串长度:",Int($pos*2-1))
EndSelect
Exit

评分

参与人数 1金钱 +30 收起 理由
pusofalse + 30 学习思路。

查看全部评分

发表于 2009-12-19 23:26:58 | 显示全部楼层
本帖最后由 C.L 于 2009-12-19 23:36 编辑

哇,看上面的代码,差不多都找不到其他的办法了,不过想了想,我也做了一个练习,应该方法和上面的不同:
$sStr = InputBox("","")
$sStr &= @CR
MsgBox(0,"len",len($sStr))
Func len ($sStr)
        Dim $i=0
        While StringRight(StringLeft($sStr,$i),1) <> @CR
                $i+=1
        WEnd
        $i-=1
        Return $i
EndFunc

评分

参与人数 1金钱 +15 收起 理由
pusofalse + 15 学习了。

查看全部评分

 楼主| 发表于 2009-12-20 09:53:42 | 显示全部楼层
本帖最后由 pusofalse 于 2009-12-20 09:58 编辑
Local $sTable, $sVar, $sString, $iLen

For $i = 0 To 65535
        $sTable &= Hex($i, 4)
Next

$sString = InputBox("", "")
$sVar = $sTable & $sString & $sString & $sString & $sString
$iLen = StringLeft(StringRight($sVar, 65536 * 4), 4)

Msgbox(0, '', Dec($iLen))
$sString = InputBox("", "")
Msgbox(0, '', BinaryLen(StringToBinary($sString, 2)) / 2)
发表于 2009-12-20 10:50:54 | 显示全部楼层
不知何种情况下更适合用“表驱动”?不懂~~~
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-8 04:54 , Processed in 0.087282 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表