다음은 대화형 모드(interactive mode)에서 진법 변환(radix conversion)하는 OCaml 소스 코드이다.
주: 이 소스는 Python 용으로 만들어 둔 소스를 F# 언어로 바꾸고, 다시 이를 Ocaml
언어로 바꾸느라 OCaml 언어의 명령형 언어 특징을 위주로 짜여져 있다.
메뉴는 주메뉴 Command: (S)et radix, (A)bout, (Q)uit or E(x)it
와 부메뉴 SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
로 구성되어 있으며, 진법 변환의 핵심은 소스 코드에 자체 작성된 함수 atoi 와 itoa 의 사용이다.
let value = atoi str srcRdx
let str = itoa value destRdx
지원되는 진법은 2진법에서 36진법까지이다.
- (*
- * Filename: convertRadix.ml
- * Convert radix in an interactive mode.
- *
- * Execute: ocaml convertRadix.ml
- *
- * Or
- *
- * Compile: ocamlc -o convertRadix.exe convertRadix.ml
- * Execute: convertRadix
- *
- * Date: 2013. 1. 28.
- * Author: P. Kim ( pkim _AT_ scripts.pe.kr )
- *)
- open Printf;;
- exception RuntimeError of string
- exception ValueError of string
- exception Exit
- let println s =
- printf "%s\n" s ;;
- let print s =
- printf "%s" s ;;
- let printUsage() =
- println "Usage: convertRadix" ;
- println "Convert radix in a interactive mode, where the maximum radix is 36." ;;
- let printAbout() =
- println " About: Convert radix in a interactive mode." ;;
- let printMainMenu() =
- println " Command: (S)et radix, (A)bout, (Q)uit or E(x)it" ;;
- let printMainPrompt() =
- print " Prompt> " ;;
- let printSubMenu srcRadix destRadix =
- println (sprintf " Convert Radix_%d to Radix_%d\n" srcRadix destRadix ) ;
- println (" SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit" ) ;;
- let printSubPrompt() =
- print " Input Value>> " ;;
- let split_char sep str =
- let rec indices acc i =
- try
- let i = succ(String.index_from str i sep) in
- indices (i::acc) i
- with Not_found ->
- (String.length str + 1) :: acc
- in
- let is = indices [0] 0 in
- let rec aux acc = function
- | last::start::tl ->
- let w = String.sub str start (last-start-1) in
- aux (w::acc) (start::tl)
- | _ -> acc
- in
- aux [] is ;;
- let sBASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;;
- let contains s1 s2 =
- try
- let len = String.length s2 in
- for i = 0 to (String.length s1) - len do
- if String.sub s1 i len = s2 then raise Exit
- done;
- false
- with Exit -> true ;;
- let join list sep =
- let rec join' list acc =
- match list with
- | [] -> ""
- | [single] -> single
- | one::[two] ->
- if acc = "" then one ^ sep ^ two
- else acc ^ one ^ sep ^ two
- | first::others -> join' others (acc ^ first ^ ", ")
- in
- join' list "" ;;
- let str_reverse str =
- let len = String.length str in
- let res = String.create len in
- for i = 0 to pred len do
- let j = pred len - i in
- res.[i] <- str.[j]
- done;
- res ;;
- let itoa num radix =
- let isNegative = ref false in
- let num1 = num + 0 in
- let numx = ref num1 in
- if num < 0 then begin
- isNegative := true ;
- numx := (-num)
- end ;
- let nnumx = !numx in
- let q1 = nnumx in
- let q = ref q1 in
- let r = ref 0 in
- let slen = ref 1 in
- while (!q >= radix) do
- r := !q mod radix ;
- q := !q / radix ;
- slen := !slen + 1
- done ;
- let sslen = !slen in
- let str = String.create sslen in
- let p1 = nnumx in
- let p = ref p1 in
- for i = 0 to sslen - 1 do
- r := !p mod radix ;
- p := !p / radix ;
- str.[i] <- sBASE36.[!r]
- done ;
- let str2 = str_reverse str in
- str2;;
- let atoi s radix =
- let ret = ref 0 in
- let isNegative = ref false in
- let len = String.length s in
- let valx = ref 0 in
- let c1 = s.[0] in
- let c = ref c1 in
- if !c = '-' then
- isNegative := true
- else if (!c >= '0' && !c <= '9') then
- ret := (int_of_char !c) - (int_of_char '0')
- else if (!c >= 'A' && !c <= 'Z') then
- ret := (int_of_char !c) - (int_of_char 'A') + 10
- else if (!c >= 'a' && !c <= 'z') then
- ret := (int_of_char !c) - (int_of_char 'a') + 10 ;
- if (!ret >= radix) then
- raise (ValueError (sprintf "Can not read \"%s\" (as radix %d): '%c' is invalid." s radix !c ) ) ;
- for i = 1 to len - 1 do
- c := s.[i] ;
- ret := (!ret)*radix ;
- if (!c >= '0' && !c <= '9') then
- valx := int_of_char !c - int_of_char '0'
- else if (!c >= 'A' && !c <= 'Z') then
- valx := int_of_char !c - int_of_char 'A' + 10
- else if (!c >= 'a' && !c <= 'z') then
- valx := int_of_char !c - int_of_char 'a' + 10 ;
- if (!valx >= radix) then
- raise (ValueError (sprintf "Can not read \"%s\" (as radix %d): '%c' is invalid." s radix !c ) ) ;
- ret := (!ret) + (!valx)
- done;
- if (!isNegative) then
- ret := (-(!ret) ) ;
- !ret ;;
- let convertRadix s srcRdx destRdx =
- let valx = (atoi s srcRdx) in
- let ret = (itoa valx destRdx) in
- let ret2 = String.uppercase ret in
- ret2 ;;
- let doConvert srcRadix destRadix =
- println "" ;
- printSubMenu srcRadix destRadix ;
- let stop_flag = ref false in
- try
- while not (!stop_flag) do
- printSubPrompt() ;
- let tt = read_line() in
- let cmd = ref tt in
- while (String.length !cmd) = 0 do
- let tt2 = read_line() in
- cmd := tt2
- done;
- if "main()" = !cmd then begin
- stop_flag := true ;
- raise ( RuntimeError "" )
- end
- else if "exit()" = !cmd || "quit()" = !cmd then begin
- exit 0
- end ;
- try
- let srcStr = !cmd in
- let destStr = (convertRadix srcStr srcRadix destRadix) in
- println (sprintf " ( %s )_%d ---> ( %s )_%d" srcStr srcRadix destStr destRadix ) ;
- println ""
- with ValueError ex -> println (sprintf " Error caused by: %s\n" ex)
- done
- with RuntimeError ex -> println (sprintf " %s " ex);
- println "" ;;
- let doStart() =
- let onlyOnce = ref true in
- try
- while true do
- print "" ;
- if (!onlyOnce) then begin
- println " The supported maximum radix is 36." ;
- onlyOnce := false
- end ;
- printMainMenu() ;
- printMainPrompt() ;
- let tcmds = read_line() in
- let cmds = ref tcmds in
- while (String.length !cmds) = 0 do
- let tt = read_line() in
- cmds := tt
- done;
- let cmd = !cmds.[0] in
- if (contains "qQxX" (sprintf "%c" cmd)) && (String.length !cmds) = 1 then begin
- exit 0
- end
- else if (contains "aA" (sprintf "%c" cmd)) && (String.length !cmds) = 1 then begin
- printAbout()
- end
- else if (contains "sS" (sprintf "%c" cmd)) && (String.length !cmds) = 1 then begin
- print " Input the source and target radices (say, 16 2): " ;
- let tt = read_line() in
- let line = ref tt in
- let ta = (split_char ' ' !line) in
- let st = ref ta in
- while (List.length !st) < 2 do
- print " Input the source and target radices (say, 16 2): " ;
- let tt2 = read_line() in
- let ta2 = (split_char ' ' tt2) in
- st := ta2
- done;
- let st2 = Array.of_list !st in
- let srcRadix = int_of_string (st2.(0)) in
- let destRadix = int_of_string (st2.(1)) in
- doConvert srcRadix destRadix
- end ;
- print ""
- done
- with RuntimeError ex -> println (sprintf "%s Error found!!" ex);;
- (* Begin here *)
- let main() =
- let cmdArgs = Sys.argv in
- if (Array.length cmdArgs > 1) && ("-h" = cmdArgs.(1)) then begin
- printUsage() ;
- exit 1
- end
- else begin
- doStart()
- end ;;
- main();;
컴파일> ocamlc -o convertRadix.exe convertRadix.fs
실행> convertRadix
The supported maximum radix is 36.
Command: (S)et radix, (A)bout, (Q)uit or E(x)it
Prompt> s
Input the source and target radices (say, 16 2): 10 8
Convert Radix_10 to Radix_8
SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
Input Value>> 200
( 200 )_10 ---> ( 310 )_8
Input Value>> main()
Command: (S)et radix, (A)bout, (Q)uit or E(x)it
Prompt> S
Input the source and target radices (say, 16 2): 8 10
Convert Radix_8 to Radix_10
SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit
Input Value>> 2666
( 2666 )_8 ---> ( 1462 )_10
Input Value>> main()
Command: (S)et radix, (A)bout, (Q)uit or E(x)it
Prompt> x
'프로그래밍 > OCaml' 카테고리의 다른 글
OCaml 에 Extlib 설치하고 사용하는 예 (0) | 2013.01.29 |
---|---|
진법(radix) 표 만들기 예제 with OCaml (0) | 2013.01.28 |
황금비율(golden ratio) 구하기 with OCaml (0) | 2013.01.27 |
현재 시각 알아내기 for OCaml (0) | 2013.01.27 |
80컬럼 컨솔에 19단표 출력하기 예제 for OCaml (0) | 2013.01.27 |