![](/img/trans.png)
[英]How do I redraw a string array graphically without overlapping the text?
[英]How can I represent an automaton graphically from a list of int*char*int representing the transitions without using loops
我做了一條稱為自動機的記錄,其中包含表示自動機所需的5個字段,我應該使用圖形來表示每個狀態和從轉換列表中的轉換,而無需使用for或while循環僅使用遞歸函數
transitions :(int*char*int) list;
使用graphviz進行實際繪圖可能是最簡單的。 它會自動從節點和邊的列表中繪制圖形,這正是您輸入的內容。 函數fmt_transition
生成一個邊,函數fmt_transitions
通過pp_print_list將其提升到轉換列表,並將其包裝到正確的標頭中。
let fmt_transition fmt (inedge,by,outedge) =
Format.fprintf fmt "@[%d -> %d [label=\"%c\"];@]" inedge outedge by
let fmt_transitions fmt =
Format.fprintf fmt "@[<v 2>digraph output {@,%a@,@]}@,@."
(Format.pp_print_list fmt_transition)
如果在某些測試數據上進行嘗試,則會得到所需的測試文件:
let test1 = [ (1,'a',2); (2,'b',1); (1,'b',1)] in
fmt_transitions Format.std_formatter test1;;
結果是:
digraph output
{
1 -> 2 [label="a"];
2 -> 1 [label="b"];
1 -> 1 [label="b"];
}
對graphviz的調用是:
dot -T pdf -o output.pdf < input.dot
如果直接從ocaml調用它,則還可以將數據直接管道傳輸到點中,而無需先將其寫入磁盤。
另外,您也可以使用類似gv的外部查看器:
let call_dot data =
let cmd = "dot -Tps | gv -" in
let (sout, sin, serr) as channels =
Unix.open_process_full cmd (Unix.environment ()) in
let fmt = Format.formatter_of_out_channel sin in
Format.fprintf fmt "%a@." fmt_transitions data;
channels
let cleanup channels =
(* missing: flush channels, empty buffers *)
Unix.close_process_full channels
調用call_dot test1 |> cleanup
將把數據發送到dot並打開ghostview。 為防止達到打開文件的限制,請等待一聲喊叫終止進程並關閉通道,這是在cleanup
完成的。
如果要改用圖像庫,則可能需要在調用clean之前將cmd的定義替換為“ dot -Tpng”並從stdin中讀取圖像數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.