找回密码
 加入
搜索
查看: 12960|回复: 25

[效率算法] 字串问题 求解

 火.. [复制链接]
发表于 2013-2-27 00:17:55 | 显示全部楼层 |阅读模式
本帖最后由 henry10423 于 2013-2-27 00:28 编辑

我写了个程式,将阿拉伯数字转成中文数字...
只是有Bug...
举例:
输入1000 会输出为 "一千零百零十零"
输入120 会输出为"一百二十零"
输入130000 会输出为"一十三万零千零百零十零
"
#include <String.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$Form1 = GUICreate("Form1", 350, 123, 546, 267)
$InputNum = GUICtrlCreateInput("", 48, 24, 169, 21)
$showabel1 = GUICtrlCreateLabel("", 170, 72, 148, 33)
$btn2 = GUICtrlCreateButton("转换", 56, 72, 100, 33)
Dim $Number[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Dim $chNum[10] = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
Dim $getFinalNum[8]
GUISetState(@SW_SHOW)

While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit

                Case $btn2
                        Local $read = GUICtrlRead($InputNum)
                        Local $checkLen = StringLen($read)
                        Local $chNum, $show, $fullNum

                        For $i = 1 To $checkLen Step + 1
                                $checkNum = StringMid($read, $i, 1)
                                For $s = 0 To UBound($Number) - 1
                                        If $checkNum == $Number[$s] Then
                                                $getNum = $chNum[$s]
                                        EndIf
                                Next
                                $show &= $getNum
                        Next

                        $getFinalNum[0] = $show
                        $getFinalNum[1] = _StringInsert($show, "十", 1)
                        $getFinalNum[2] = _StringInsert(_StringInsert($show, "百", 1), "十", 3)
                        $getFinalNum[3] = _StringInsert(_StringInsert(_StringInsert($show, "千", 1), "百", 3), "十", 5)
                        $getFinalNum[4] = _StringInsert(_StringInsert(_StringInsert(_StringInsert($show, "万", 1), "千", 3), "百", 5), "十", 7)
                        $getFinalNum[5] = _StringInsert(_StringInsert(_StringInsert(_StringInsert(_StringInsert($show, "十", 1), "万", 3), "千", 5), "百", 7), "十", 9)
                        $getFinalNum[6] = _StringInsert(_StringInsert(_StringInsert(_StringInsert(_StringInsert(_StringInsert($show, "百", 1), "十", 3), "万", 5), "千", 7), "百", 9), "十", 11)
                        $getFinalNum[7] = _StringInsert(_StringInsert(_StringInsert(_StringInsert(_StringInsert(_StringInsert(_StringInsert($show, "千", 1), "百", 3), "十", 5), "万", 7), "千", 9), "百", 11), "十", 13)

                        For $i = 0 To UBound($getFinalNum) - 1
                                If $checkLen == ($i + 1) Then
                                        $fullNum = $getFinalNum[$i]
                                EndIf
                        Next

                        GUICtrlSetData($showabel1, $fullNum)

        EndSwitch
WEnd
求各位大侠的有效帮助
感谢了!
发表于 2013-2-27 08:54:21 | 显示全部楼层
 楼主| 发表于 2013-2-27 09:23:23 | 显示全部楼层
水木子 发表于 2013-2-27 08:54



太棒了,
完美解决,
感谢热情帮助!!
发表于 2013-2-27 14:38:04 | 显示全部楼层
回复 1# henry10423


    我也把以前给别人会计用的转换大写人民币,给你参考。
以前是用c写的,我转成au3了,添加了无数的'$',累死了


$iNum = InputBox("Arabic Number", "Input Arabic Number: ", "12,005,678.991")
$sCnNum = convertCurrency($iNum)
If $sCnNum Then MsgBox(0, "Result", $sCnNum)

Func convertCurrency($currencyDigits) 
        ;// Constants:  
        Local Const $MAXIMUM_NUMBER = 99999999999.99;  
        ;// Predefine the radix characters and currency symbols for output:  
        Local Const $CN_ZERO = "零";  
        Local Const $CN_ONE = "壹";  
        Local Const $CN_TWO = "贰";  
        Local Const $CN_THREE = "叁";  
        Local Const $CN_FOUR = "肆";  
        Local Const $CN_FIVE = "伍";  
        Local Const $CN_SIX = "陆";  
        Local Const $CN_SEVEN = "柒";  
        Local Const $CN_EIGHT = "捌";  
        Local Const $CN_NINE = "玖";  
        Local Const $CN_TEN = "拾";  
        Local Const $CN_HUNDRED = "佰";  
        Local Const $CN_THOUSAND = "仟";  
        Local Const $CN_TEN_THOUSAND = "万";  
        Local Const $CN_HUNDRED_MILLION = "亿";  
        Local Const $CN_SYMBOL = "人民币:";  
        Local Const $CN_DOLLAR = "圆";  
        Local Const $CN_TEN_CENT = "角";  
        Local Const $CN_CENT = "分";  
        Local Const $CN_INTEGER = "整";     
        ;// Variables:  
        Local $integral; // Represent integral part of digit number.  
        Local $decimal; // Represent decimal part of digit number.  
        Local $outputCharacters; // The output result.  
        Local $parts;  
        Local $digits, $radices, $bigRadices, $decimals;  
        Local $zeroCount;  
        Local $i, $p, $d;  
        Local $quotient, $modulus;  
        ;// Validate input string:  
        $currencyDigits = String($currencyDigits);  
        if ($currencyDigits == "") Then
                ConsoleWrite("Empty input!");  
                return "";  
        EndIf
        if StringRegExp($currencyDigits, '[^,.\d]') Then
                ConsoleWrite("Invalid characters in the input string!");  
                return "";  
        EndIf  
        if Not StringRegExp($currencyDigits, '^((\d{1,3}(,\d{3})*(\.((\d{3},)*\d{1,3}))?)|(\d+(\.\d+)?))$') Then
                ConsoleWrite("Illegal format of digit number!");  
                return "";  
        EndIf  
        ;// Normalize the format of input digits:  
        $currencyDigits = StringRegExpReplace($currencyDigits, ',', ""); // Remove comma delimiters.  
        $currencyDigits = StringRegExpReplace($currencyDigits, '^0+', ""); // Trim zeros at the beginning.  
        ;// Assert the number is not greater than the maximum number.  
        if Number($currencyDigits) > $MAXIMUM_NUMBER Then  
                ConsoleWrite("Too large a number to convert!");  
                return "";  
        EndIf  
        ;// Process the coversion from currency digits to characters:  
        ;// Separate integral and decimal parts before processing coversion:  
        $parts = StringSplit($currencyDigits, ".", 2);  
        if UBound($parts) > 1 Then
                 $integral = $parts[0];  
                 $decimal = $parts[1];  
                 ;// Cut down redundant decimal digits that are after the second.  
                 $decimal = StringMid($decimal, 1, 2); 
        else  
                $integral = $parts[0];  
                $decimal = "";  
        EndIf 
        ;// Prepare the characters corresponding to the digits:  
        Local $digits[10] = [$CN_ZERO, $CN_ONE, $CN_TWO, $CN_THREE, $CN_FOUR, $CN_FIVE, $CN_SIX, $CN_SEVEN, $CN_EIGHT, $CN_NINE];  
        Local $radices[4] = ["", $CN_TEN, $CN_HUNDRED, $CN_THOUSAND];  
        Local $bigRadices[3] = ["", $CN_TEN_THOUSAND, $CN_HUNDRED_MILLION];  
        Local $decimals[2] = [$CN_TEN_CENT, $CN_CENT];  
        ;// Start processing:  
        $outputCharacters = "";  
        ;// Process integral part if it is larger than zero:  
        if Number($integral) > 0 Then  
                $zeroCount = 0;  
                for $i = 0 To StringLen($integral) - 1 
                        $p = StringLen($integral) - $i - 1;  
                        $d = StringMid($integral, $i + 1, 1);  
                        $quotient = $p / 4;  
                        $modulus = Mod($p, 4);  
                        if $d == "0" Then 
                                $zeroCount += 1;  
                        else
                                if $zeroCount > 0 Then   
                                        $outputCharacters &= $digits[0];  
                                EndIf
                                $zeroCount = 0;  
                                $outputCharacters &= $digits[Number($d)] & $radices[$modulus];  
                        EndIf
                        if $modulus == 0 And $zeroCount < 4 Then 
                                $outputCharacters &= $bigRadices[$quotient];  
                        EndIf 
                Next
                $outputCharacters &= $CN_DOLLAR;  
        EndIf
        ;// Process decimal part if there is:  
        if $decimal <> "" Then 
                for $i = 0 To StringLen($decimal) - 1
                        $d = StringMid($decimal, $i + 1, 1);  
                        if $d <> "0" Then 
                                $outputCharacters &= $digits[Number($d)] & $decimals[$i];  
                        EndIf
                Next
        EndIf
        ;// Confirm and return the final output string:  
        if $outputCharacters == "" Then 
                $outputCharacters = $CN_ZERO & $CN_DOLLAR;  
        EndIf
        if $decimal == "" Then  
                $outputCharacters &= $CN_INTEGER;  
        EndIf
        $outputCharacters = $CN_SYMBOL & $outputCharacters;  
        return $outputCharacters;  
EndFunc
发表于 2013-2-27 14:44:45 | 显示全部楼层
本帖最后由 afan 于 2013-2-27 14:56 编辑

来个简单的
$Form1 = GUICreate('Form1', 350, 123, 546, 267)
$InputNum = GUICtrlCreateInput('12000000000000000', 48, 24, 140, 21,0x2000);$ES_NUMBER = 0x2000
GUICtrlSetLimit(-1, 17)
$showabel1 = GUICtrlCreateLabel('最大支持17位', 20, 72, 330, 30)
$btn2 = GUICtrlCreateButton('转换', 200, 24, 100, 22)
GUISetState()
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case -3
                        Exit
                Case $btn2
                        $sRt = _Num2Cn(GUICtrlRead($InputNum))
                        GUICtrlSetData($showabel1, $sRt)
        EndSwitch
WEnd

Func _Num2Cn($Num)
        Local $aNum[10] = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
        Local $aCn[17] = ['个', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '兆', '十', '百', '千', '京']
        Local $iNLen = StringLen($Num), $sNum
        If $iNLen > 17 Then Return SetError(1, '', '超出最高17位数')
        For $i = 1 To $iNLen
                $sNum &= StringMid($Num, $i, 1) & $aCn[$iNLen - $i]
        Next
        $sNum = StringTrimRight($sNum, 1)
        $sNum = StringRegExpReplace(StringRegExpReplace($sNum, '0[千百十个]', '0'), '0000\D', '0')
        $sNum = StringRegExpReplace($sNum, '(?<=十)0+([百千万亿兆])|(?<=百)0+([千万亿兆])|(?<=千)0+([万亿兆])|(?<=万)0+([亿兆])', '\1\2\3\4')
        $sNum = StringRegExpReplace($sNum, '0[亿万千百十个]', '0')
        $sNum = StringRegExpReplace(StringRegExpReplace($sNum, '0+$', ''), '0+', '零')
        For $i = 0 To 9
                $sNum = StringRegExpReplace($sNum, $i, $aNum[$i])
        Next
        Return $sNum
EndFunc   ;==>_Num2Cn
 楼主| 发表于 2013-2-27 18:13:40 | 显示全部楼层
来个简单的
afan 发表于 2013-2-27 14:44



    afan 哥 ,谢啦..果真不错! 厉害!
 楼主| 发表于 2013-2-27 18:14:52 | 显示全部楼层
回复  henry10423


    我也把以前给别人会计用的转换大写人民币,给你参考。
以前是用c写的,我转成 ...
happytc 发表于 2013-2-27 14:38



    这个有点复杂了,看来我要熟悉一下了...
都是高手,果然思维就是不凡..
发表于 2013-3-3 04:21:58 | 显示全部楼层
本帖最后由 netegg 于 2013-3-3 07:02 编辑

[au3]Local $num = 157800056690
global $aNum[10] = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
Local $unit[4] = ['', '万', '亿']
Local $i = 0
Global $retc = ''
While StringRight($num, 4)
        Switch StringLen(StringRight($num, 4))
                Case 4
                        $retc = convert(StringRight(StringRight($num, 4), 1), StringMid(StringRight($num, 4), 3, 1), StringMid(StringRight($num, 4), 2, 1), StringLeft(StringRight($num, 4), 1)) & $unit[$i] & $retc
                Case 3
                        $retc = convert(StringRight(StringRight($num, 3), 1), StringMid(StringRight($num, 3), 2, 1), StringLeft(StringRight($num, 3), 1)) & $unit[$i] & $retc
                Case 2
                        $retc = convert(StringRight(StringRight($num, 2), 1), StringLeft(StringRight($num, 2), 1)) & $unit[$i] & $retc
                Case 1
                        $retc = convert($num) & $unit[$i] & $retc
        EndSwitch
        $num = StringTrimRight($num, 4)
        $i += 1
WEnd
MsgBox(0, 0, $retc)
Func convert($s4='',$s3='',  $s2='', $s1 = '')
        Local  $ret = ''
        If $s1<>0 Then $ret &= $aNum[$s1] & '仟'
        If $s2<>0 Then $ret &= $aNum[$s2] & '佰'
        If $s3<>0 Then $ret &= $aNum[$s3] & '拾'
        If $s4<>0 then $ret &= $aNum[$s4]
        ConsoleWrite($ret & @cr)
        Return $ret
EndFunc   ;==>convert
[/au3]
发表于 2013-3-3 10:39:56 | 显示全部楼层
回复 8# netegg


    貌似后面加个1就不对了 Local $num = 1578000566901
发表于 2013-3-3 10:56:38 | 显示全部楼层
本帖最后由 netegg 于 2013-3-3 11:38 编辑

回复 9# afan
单位超了,四个为一组,最多到千亿,后面的需要加大$unit的元素,图片只是演示下
这个问题不是很大,不过需要想想,原来曾经想过,要循环使用unit数组。逻辑需要设计设计
如果指的是百位和十位的零那好办,判断部分的子函数稍改下就行
Func convert($s4 = 0, $s3 = 0, $s2 = 0, $s1 = 0)
        Local $ret = ''
        If Not StringInStr($s1, '0') Then $ret &= $aNum[$s1] & '仟'
        If Not StringInStr($s2, '0') Then $ret &= $aNum[$s2] & '佰'
        If Not StringInStr($s3, '0') Then $ret &= $aNum[$s3] & '拾'
        If Not StringInStr($s4, '0') Then
                If Not $i Then
                        $ret &= $aNum[Not (BitXOR(StringInStr($ret, '拾'), 1))] & $aNum[$s4]
                Else
                        $ret &= $aNum[$s4]
                EndIf
        EndIf
        ConsoleWrite($ret & @CR)
        Return $ret
EndFunc   ;==>convert
前面的$i用global声明

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2013-3-3 14:18:02 | 显示全部楼层
本帖最后由 netegg 于 2013-3-3 15:28 编辑

整个简单些的
[au3]Local $num = 157760974098056690
Global $aNum[10] = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
Local $unit[6] = ['', '万', '亿', '兆', '京']
Local $i = 0
Global $retc = ''
If Not IsInt(StringLen($num) / 4) Then
        $format = '%0' & Ceiling(StringLen($num) / 4) * 4 & 's'
        $num = StringFormat($format, $num)
        MsgBox(0, 0, $num)
EndIf
While StringRight($num, 4)
        $retc = StringFormat('%s仟%s佰%s拾%s', $aNum[Number(StringLeft(StringRight($num, 4), 1))], _
                        $aNum[Number(StringMid(StringRight($num, 4), 2, 1))], $aNum[Number(StringMid(StringRight($num, 4), 3, 1))], $aNum[Number(StringRight(StringRight($num, 4), 1))]) & $unit[$i] & $retc
        $num = StringTrimRight($num, 4)
        $i += 1
WEnd
While 1
        $number = StringInStr($retc, '零')
        If Not $number Then ExitLoop
        ConsoleWrite(StringMid($retc, $number + 1, 1) & @CR)
        If StringInStr('万亿兆京', StringMid($retc, $number + 1, 1)) Then
                $last = StringTrimLeft($retc, $number)
        Else
                $last = StringTrimLeft($retc, $number + 1)
        EndIf
        $first = StringLeft($retc, $number - 1)
        If $number Then $retc = $first & $last
WEnd
MsgBox(0, 0, $retc)


[/au3]
 楼主| 发表于 2013-3-3 14:45:21 | 显示全部楼层
回复 11# netegg


    猛!
发表于 2013-3-3 15:25:02 | 显示全部楼层
整个简单些的
netegg 发表于 2013-3-3 14:18



    似乎都少了“零”界,比如“玖佰壹” 和 “玖佰零壹”相差10倍
发表于 2013-3-3 15:29:36 | 显示全部楼层
本帖最后由 netegg 于 2013-3-3 16:11 编辑

回复 13# afan
再试试,嗯,好像是,不过这个问题不大,判断处理下有没有,加下就行了
还有,忘了题目了,如果是纯数字的话需要处理,如果是金额的话好像不用

[au3]#include<array.au3>
Local $num = 1577609740980566901
Global $aNum[10] = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
Local $unit[6] = ['', '万', '亿', '兆', '京']
Local $i = 0
Global $retc = ''
If Not IsInt(StringLen($num) / 4) Then
        $format = '%0' & Ceiling(StringLen($num) / 4) * 4 & 's'
        $num = StringFormat($format, $num)
EndIf
While StringRight($num, 4)
        $retc = StringFormat('%s仟%s佰%s拾%s', $aNum[Number(StringLeft(StringRight($num, 4), 1))], _
                        $aNum[Number(StringMid(StringRight($num, 4), 2, 1))], _
                        $aNum[Number(StringMid(StringRight($num, 4), 3, 1))], _
                        $aNum[Number(StringRight(StringRight($num, 4), 1))]) & $unit[$i] & $retc
        $num = StringTrimRight($num, 4)
        $i += 1
WEnd
$ling = StringSplit($retc, '零', 2)
For $i = 0 To UBound($ling) - 1
        If StringLen($ling[$i]) = 1 Then _ArrayDelete($ling, $i)
Next
_ArrayTrim($ling, 1)
MsgBox(0, 0, _ArrayToString($ling, '零', 1))
[/au3]
再试试
发表于 2013-3-3 16:18:38 | 显示全部楼层
回复  afan
再试试,嗯,好像是,不过这个问题不大,判断处理下有没有,加下就行了
还有,忘了题目了,如 ...
netegg 发表于 2013-3-3 15:29



    测试 15700970090560901 看看,应该存在3个零才是
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-11-16 01:20 , Processed in 0.145098 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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