[英](Invalid_argument "index out of bounds") while encoding a word to a Morse code
Bonjour.我正在努力解決 function code_word 。 這個 function 的目的是在輸入上獲取字符串類型的消息和莫爾斯字母本身,它應該在 output 上返回相同類型的編碼字。 例如:
code_mot: string->(char * string)list -> string
code_word "SOS" alphabet;;
-: string list = ["... --- ..."]
PS:單詞的每個編碼字母都必須用空格分隔。
我創建了一個 function(如下所示),但是每次我傳遞一個參數時,我總是得到一個錯誤:
Exception: (Invalid_argument "index out of bounds")
老實說,我已經嘗試了所有可能的組合來解決這個問題。 盡管如此,我沒有找到合適的解決方案。因此,我想尋求幫助:錯誤的根源是什么,我該如何解決?
let alphabet =
[ ('A', "._" ); ('B', "_..." ); ('C', "_._.") ;
('D', "_.." ); ('E', "." ); ('F', ".._." );
('G', "__." ); ('H', "...." );( 'I', ".." );
('J', ".___" ); ('K', "_._" ); ('L', "._.." );
('M', "__" ); ('N', "_." ); ('O', "___" );
('P', ".__."); ( 'Q', "__._" );( 'R', "._.") ;
('S', "..." ); ('T', "_" ); ('U', ".._" );
('V', "..._" ); ('W', ".__" ); ('X', "_.._") ;
('Y', "_.__" ); ('Z', "__.." )
];;
let code_word s alpha =
let rec cw_aux s i alpha word =
match alpha with
| [] -> word
| (cha, l)::r ->
if s.[i] = cha then
cw_aux s (i+1) alpha (l^" "^word)
else
cw_aux s (i+1) r word
in
cw_aux s 0 alpha " " ;
您的代碼需要遍歷兩件事:傳入的字符串和莫爾斯電碼列表。 但是你只有一個終止條件,莫爾斯電碼表的結尾。 換句話說,您不會在任何地方檢查何時到達字符串的末尾。 因此,您使用(i + 1)
進行的遞歸調用最終將超過字符串的末尾並導致您的錯誤。
在我看來,您也有合並兩個搜索的問題。 當您沒有找到字符串的當前字符的代碼時,您想要移動到字符串中的下一個字符是不正確的。
換句話說,這個調用在我看來是錯誤的:
cw_aux s (i+1) r word
您不想在此處移動到傳入字符串的下一個字符。 您想首先找到當前字符的正確代碼。
這是使用Map
到 map 字符到摩爾斯電碼的好地方。 然后只需將字符串中的每個字符映射到 map 中該字符的綁定即可。 通過讓庫函數處理對字符串的循環,索引錯誤不會發生。
您可以將List.assoc
與您的列表一起使用,但這是 O(n),而 map 中的查找是 O(log n)。 出於簡單的目的,可能幾乎沒有實際差異,但對於較大的字符串,這將很重要。
module CMap = Map.Make (Char)
然后,使用您的元組列表:
let alphabet =
[ ('A', "._" ); ('B', "_..." ); ('C', "_._.");
('D', "_.." ); ('E', "." ); ('F', ".._." );
('G', "__." ); ('H', "...." );( 'I', ".." );
('J', ".___" ); ('K', "_._" ); ('L', "._.." );
('M', "__" ); ('N', "_." ); ('O', "___" );
('P', ".__."); ( 'Q', "__._" );( 'R', "._.");
('S', "..." ); ('T', "_" ); ('U', ".._" );
('V', "..._" ); ('W', ".__" ); ('X', "_.._");
('Y', "_.__" ); ('Z', "__.." )
]
在Seq
(序列)模塊的幫助下,我們可以根據您創建的映射創建 map。
let map = alphabet |> List.to_seq |> CMap.of_seq
(注意|>
運算符允許我們編寫上面的代碼,而不是CMap.of_seq (List.to_seq alphabet)
。這在下面的代碼中變得更有幫助。)
現在,實際上我們只需要 map 每個字符的摩爾斯電碼輸入字符串。 為此,我們將字符串轉換為序列 map,然后轉換為列表。
"Hello"
|> String.to_seq
|> Seq.map Char.uppercase_ascii
|> Seq.map (fun ch -> CMap.find ch map)
|> List.of_seq
結果:
["...."; "."; "._.."; "._.."; "___"]
您現在只需將它們連接成一個字符串。
如果您嘗試對包含沒有摩爾斯電碼映射的字符的字符串進行編碼,您可能仍會收到Not_found
異常。 您要么想要處理此異常,要么向 map 添加更多摩爾斯電碼綁定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.