我正在尝试在我的一篇论文中为某个算法集成一个美观的控制流图:
static void PrintEven(int x)
{
int c = 0;
while (c <= x)
{
if (c % 2 == 0)
Console.WriteLine(c);
c++;
}
Console.WriteLine("Done.");
}
我首先创建了 cfghttp://www.webgraphviz.com/看起来太可怕了:
我被告知要用 tikz 创建图表,这样看起来会更好。我被告知这是在论文中实现 CFG 的首选方法。所谓好看,是指一个漂亮的垂直结构,入口节点位于顶部,出口节点(Console.WriteLine("Done"))位于底部。此外,如果箭头不是圆形的,而是看起来像这张图片中那样,那就太好了:
有人能告诉我如何使用 tikz 为我的算法创建 CFG 吗?
答案1
这不一定是一个答案,而是一种试图将上述讨论引向不同方向的尝试。此站点上有很多流程图类型的图表。一个很好的例子是这个答案,我在这里添加了一个略微的变化。(请注意,我不是程序员,因此我很可能对该流程图的元素使用了错误的样式。这是将其设为社区 wiki 的另一个原因。)
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning}
\usetikzlibrary{shapes.geometric}
\begin{document}
\begin{tikzpicture}[node distance=1cm,font=\sffamily,
startstop/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30},
process/.style={rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30},
decision/.style={diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30},
arr/.style={very thick,-latex}
]
\node (int) [startstop] {\texttt{int c=0;}};
\node (while) [process,below=of int] {\texttt{while (c <= x)}};
\draw[arr] (int) -- (while);
\node (if) [decision,below=of while] {\texttt{if (c \% 2 == 0)}};
\draw[arr] (while) -- (if);
\node (write) [process,right=of if] {\texttt{Console.WriteLine(c);}};
\draw[arr] (if) -- (write) node[midway,above]{yes};
\node (pp) [process,below=of if] {\texttt{c++;}};
\draw[arr] (if) -- (pp) node[midway,left]{no};
\draw[arr] (write) |- (pp);
\draw[arr] (pp.west) -- ++ (-1,0) |- (while) node[pos=0.25,left]{$c\le x$};
\end{tikzpicture}
\end{document}
这里我还有一个“替代方案”......(......“替代方案”似乎意味着一个人从另一篇文章中复制而不提及它,保留 90% 并在这里和那里做一些小的修改。好的,那么这是一个“替代方案”,;-)
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning,shapes.geometric}
\begin{document}
\begin{tikzpicture}[node distance = 9mm and 14mm,
nodes= {draw, minimum width=8em, minimum height=2em,
font=\ttfamily},
startstop/.style = {fill=red!30, rounded corners},
process/.style = {fill=orange!30},
io/.style = {fill=blue!30,
trapezium, trapezium stretches body,
trapezium left angle=70, trapezium right angle=110},
decision/.style = {fill=green!30, diamond, aspect=1.5},
exp/.style={draw=none,font=\sffamily,minimum width=1em},
arr/.style = {very thick,-latex}
]
\node (int) [io] {int c=0;};
\node (while) [process,below=of int] {while (c <= x)};
\draw[arr] (int) -- (while);
\node (if) [decision,below=of while] {if (c \% 2 == 0)};
\draw[arr] (while) -- node[exp,right] {$c\le x$} (if);
\node (write) [process,below=of if] {Console.WriteLine(c);};
\draw[arr] (if) -- (write) node[exp,pos=0.5,left] {yes};
\node (pp) [process,below=of write] {c++;};
\draw[arr] (write) -- (pp);
\draw[arr] (if.east) -- ++ (1,0) node[exp,pos=0.5,above] {no} |- (pp) ;
\node (done) [startstop,below right=of write] {Console.WriteLine("Done");};
\draw[arr] (while) -| (done) node[exp,pos=0.25,above] {$c> x$};
\draw[arr] (pp.west) -- ++ (-1,0) |- (while);
\end{tikzpicture}
\end{document}
答案2
基于我的一个旧解决方案回答类似问题。与之相比,下面的 MWE 尝试复制您问题中的第一个图像:
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{positioning,
shapes.geometric}
\begin{document}
\begin{tikzpicture}[
node distance = 8mm and 12mm,
base/.style = {draw, fill=#1,
minimum width=28mm, minimum height=7mm,
font=\ttfamily},
startstop/.style = {base=red!30, rounded corners},
process/.style = {base=orange!30},
io/.style = {base=blue!30,
trapezium, trapezium stretches body,
trapezium left angle=70, trapezium right angle=110},
decision/.style = {base=green!30, diamond, aspect=1.5},
arr/.style = {semithick,-latex}
]
\node (int) [io] {int c=0;};
\node (while) [process,below=of int] {while (c <= x)};
\draw[arr] (int) -- (while);
\node (if) [decision,below=of while] {if (c \% 2 == 0)};
\draw[arr] (while) -- node[right] {$c\le x$} (if);
\node (write) [process,below=of if] {Console.WriteLine(c);};
\draw[arr] (if) -- node[left] {yes} (write);
\node (pp) [process,below=of write] {c++;};
\draw[arr] (write) -- (pp);
\draw[arr] (if.east) -- node[above] {no} ++ (1,0) |- (pp);
\node (done) [startstop,
below right=of write] {Console.WriteLine("Done");};
\draw[arr] (while) -| (done) node[pos=0.25,above] {$c> x$};
\draw[arr] (pp.west) -- ++ (-1,0) |- (while);
\end{tikzpicture}
\end{document}