簡體   English   中英

(Invalid_argument“索引超出范圍”)同時將單詞編碼為摩爾斯電碼

[英](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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM