다음은  대화형 모드(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진법까지이다.

 

  1. (*
  2.  *  Filename: convertRadix.ml
  3.  *            Convert radix in an interactive mode.
  4.  *
  5.  *  Execute: ocaml convertRadix.ml
  6.  *
  7.  *   Or
  8.  *
  9.  *  Compile: ocamlc -o convertRadix.exe convertRadix.ml
  10.  *  Execute: convertRadix
  11.  *
  12.  *      Date:  2013. 1. 28.
  13.  *    Author:  P. Kim   ( pkim _AT_ scripts.pe.kr )
  14.  *)
  15. open Printf;;
  16. exception RuntimeError of string
  17. exception ValueError of string
  18. exception Exit
  19. let println s =
  20.     printf "%s\n" s ;;
  21. let print s =
  22.    printf "%s" s  ;;
  23. let printUsage() =
  24.     println "Usage: convertRadix" ;
  25.     println "Convert radix in a interactive mode, where the maximum radix is 36." ;;
  26. let printAbout() =
  27.     println "    About: Convert radix in a interactive mode."  ;;
  28. let printMainMenu() =
  29.     println "  Command: (S)et radix, (A)bout, (Q)uit or E(x)it"  ;;
  30. let printMainPrompt() =
  31.     print "  Prompt> "  ;;
  32. let printSubMenu srcRadix destRadix =
  33.     println (sprintf "    Convert Radix_%d to Radix_%d\n" srcRadix destRadix )  ;
  34.     println ("    SubCommand: 'main()' to goto Main menu, 'exit()' or 'quit()' to exit" )  ;;
  35. let printSubPrompt() =
  36.     print "    Input Value>> " ;;
  37. let split_char sep str =
  38.   let rec indices acc i =
  39.     try
  40.       let i = succ(String.index_from str i sep) in
  41.       indices (i::acc) i
  42.     with Not_found ->
  43.       (String.length str + 1) :: acc
  44.   in
  45.   let is = indices [0] 0 in
  46.   let rec aux acc = function
  47.     | last::start::tl ->
  48.         let w = String.sub str start (last-start-1) in
  49.         aux (w::acc) (start::tl)
  50.     | _ -> acc
  51.   in
  52.   aux [] is ;;
  53. let sBASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"  ;;
  54. let contains s1 s2 =
  55.   try
  56.     let len = String.length s2 in
  57.     for i = 0 to (String.length s1) - len do
  58.       if String.sub s1 i len = s2 then raise Exit
  59.     done;
  60.     false
  61.   with Exit -> true ;;
  62. let join list sep =
  63.     let rec join' list acc =
  64.         match list with
  65.             | [] -> ""
  66.             | [single] -> single
  67.             | one::[two] ->
  68.                         if acc = "" then one ^ sep ^ two
  69.                                     else acc ^ one ^ sep ^ two
  70.             | first::others -> join' others (acc ^ first ^ ", ")
  71.                                         in
  72.                                         join' list "" ;;
  73. let str_reverse str =
  74.     let len = String.length str in
  75.     let res = String.create len in
  76.     for i = 0 to pred len do
  77.         let j = pred len - i in
  78.         res.[i] <- str.[j]
  79.     done;
  80.     res ;;
  81. let itoa num radix =
  82.    let isNegative = ref false in
  83.    let num1 = num + 0 in
  84.    let numx = ref num1 in
  85.    if num < 0 then begin
  86.       isNegative := true ;
  87.       numx := (-num)
  88.    end ;
  89.    let nnumx = !numx in
  90.    let q1 = nnumx in
  91.    let q = ref q1 in
  92.    let r = ref 0 in
  93.    let slen = ref 1 in
  94.    while (!q >= radix) do
  95.        r := !q mod radix ;
  96.        q := !q / radix ;
  97.        slen := !slen + 1
  98.    done ;
  99.    let sslen = !slen in
  100.    let str = String.create sslen in
  101.    let p1 = nnumx in
  102.    let p = ref p1 in
  103.    for i = 0 to sslen - 1 do
  104.        r := !p mod radix ;
  105.        p := !p / radix ;
  106.        str.[i] <- sBASE36.[!r]
  107.    done ;
  108.    let str2 = str_reverse str in
  109.    str2;;
  110. let atoi s radix =
  111.     let ret = ref 0 in
  112.     let isNegative = ref false in
  113.     let len = String.length s in
  114.     let valx = ref 0 in
  115.     let c1 = s.[0] in
  116.     let c = ref c1 in
  117.     if !c = '-' then
  118.         isNegative := true
  119.     else if (!c >= '0' && !c <= '9') then
  120.         ret := (int_of_char !c) - (int_of_char '0')
  121.     else if (!c >= 'A' && !c <= 'Z') then
  122.         ret := (int_of_char !c) - (int_of_char 'A') + 10
  123.     else if (!c >= 'a' && !c <= 'z') then
  124.         ret := (int_of_char !c) - (int_of_char 'a') + 10 ;
  125.     if (!ret >= radix) then 
  126.         raise (ValueError (sprintf "Can not read \"%s\" (as radix %d): '%c' is invalid." s radix !c ) ) ;
  127.     for i = 1 to len - 1 do
  128.         c := s.[i] ;
  129.         ret := (!ret)*radix  ;
  130.         if (!c >= '0' && !c <= '9') then
  131.             valx := int_of_char !c - int_of_char '0' 
  132.         else if (!c >= 'A' && !c <= 'Z') then
  133.             valx := int_of_char !c - int_of_char 'A' + 10
  134.         else if (!c >= 'a' && !c <= 'z') then
  135.             valx := int_of_char !c - int_of_char 'a' + 10 ;
  136.         if (!valx >= radix) then 
  137.             raise (ValueError (sprintf "Can not read \"%s\" (as radix %d): '%c' is invalid." s radix !c ) ) ;
  138.         ret := (!ret) + (!valx)
  139.     done;
  140.     if (!isNegative) then
  141.         ret := (-(!ret) ) ;
  142.     !ret ;;
  143. let convertRadix s srcRdx destRdx =
  144.     let valx = (atoi s srcRdx) in
  145.     let ret = (itoa valx destRdx) in
  146.     let ret2 = String.uppercase ret in
  147.     ret2 ;;
  148. let doConvert srcRadix destRadix =
  149.     println "" ;
  150.     printSubMenu srcRadix  destRadix ;
  151.     let stop_flag = ref false in
  152.     try
  153.         while not (!stop_flag) do
  154.             printSubPrompt() ;
  155.             let tt = read_line() in
  156.             let cmd = ref tt in
  157.             while (String.length !cmd) = 0 do
  158.                 let tt2 = read_line() in
  159.                 cmd := tt2
  160.             done;
  161.             if "main()" = !cmd then begin
  162.                 stop_flag := true ;
  163.                 raise ( RuntimeError "" )
  164.             end
  165.             else if "exit()" = !cmd || "quit()" = !cmd then begin
  166.                 exit 0
  167.             end ;
  168.             try 
  169.                 let srcStr = !cmd in
  170.                 let destStr = (convertRadix srcStr srcRadix destRadix) in
  171.                 println (sprintf "        ( %s )_%d   --->   ( %s )_%d" srcStr srcRadix destStr destRadix ) ;
  172.                 println ""
  173.             with ValueError ex -> println (sprintf "    Error caused by: %s\n"  ex)
  174.         done
  175.     with RuntimeError ex -> println (sprintf " %s     "  ex);
  176.     println "" ;;
  177. let doStart() =
  178.     let onlyOnce = ref true in
  179.     try
  180.         while true do
  181.             print "" ;
  182.             if (!onlyOnce) then begin
  183.                 println "  The supported maximum radix is 36." ;
  184.                 onlyOnce := false
  185.             end ;
  186.             printMainMenu() ;
  187.             printMainPrompt() ;
  188.             let tcmds = read_line() in
  189.             let cmds = ref tcmds in
  190.             while (String.length !cmds) = 0 do
  191.                 let tt = read_line() in
  192.                 cmds := tt
  193.             done;
  194.             let cmd = !cmds.[0] in
  195.             if (contains  "qQxX" (sprintf "%c" cmd)) && (String.length !cmds) = 1 then begin
  196.                 exit 0
  197.             end
  198.             else if (contains  "aA" (sprintf "%c" cmd)) && (String.length !cmds) = 1 then begin
  199.                 printAbout()
  200.             end
  201.             else if (contains  "sS" (sprintf "%c" cmd)) && (String.length !cmds) = 1 then begin
  202.                 print "  Input the source and target radices (say, 16 2): "  ;
  203.                 let tt = read_line() in
  204.                 let line = ref tt in
  205.                 let ta = (split_char ' ' !line) in
  206.                 let st = ref ta in
  207.                 while (List.length !st) < 2 do
  208.                     print "  Input the source and target radices (say, 16 2): "  ;
  209.                     let tt2 = read_line() in
  210.                     let ta2 = (split_char ' ' tt2) in
  211.                     st := ta2
  212.                 done;
  213.                 let st2 = Array.of_list !st in
  214.                 let srcRadix = int_of_string (st2.(0)) in
  215.                 let destRadix = int_of_string (st2.(1)) in
  216.                 doConvert srcRadix destRadix
  217.             end ;
  218.             print ""
  219.        done 
  220.     with RuntimeError ex -> println (sprintf "%s Error found!!" ex);;
  221. (* Begin here *)
  222. let main() =
  223.     let cmdArgs = Sys.argv in
  224.     if (Array.length cmdArgs > 1) && ("-h" = cmdArgs.(1)) then begin
  225.         printUsage() ;
  226.         exit 1
  227.     end
  228.     else begin
  229.         doStart()
  230.     end ;;
  231. 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


Posted by Scripter
,