答案1
可以定义listings
样式并将其内容放入 TikZ 节点中。这样可以实现框架效果,然后将它们链接起来。
\documentclass{article}
%\url{https://tex.stackexchange.com/q/419759/86}
\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\newcounter{tmlistings}
\newcommand\makenode[2]{%
\tikz[baseline=0pt, remember picture] { \node[fill=gray!50,thick,rounded corners,anchor=base,#1/.try] (listings-\the\value{tmlistings}) {#2}; }%
\stepcounter{tmlistings}%
}
\tikzset{
keyword/.style={
fill=gray!75,
draw=black
}
}
\lstset{
keywordstyle=\makenode{keyword},
stringstyle=\makenode{string},
identifierstyle=\makenode{identifier},
}
\begin{document}
\begin{lstlisting}[language=c]
int gilligan (int j) {
for (int i = 1; i < j; i++) {
if (i % 2 == 0) {
cout << i
}
}
}
\end{lstlisting}
\begin{tikzpicture}[remember picture,overlay,>=Latex]
\draw[->] (listings-8) to[out=45,in=45,looseness=2] (listings-3);
\draw[->] (listings-13) -- (listings-11);
\draw[->] (listings-11) -- (listings-6);
\draw[->] (listings-6) to[out=-45,in=-135] (listings-7);
\draw[->] (listings-7) to[out=-45,in=-135] (listings-9);
\end{tikzpicture}
\end{document}
(不幸的是,我不知道如何将符号放入节点。我对此没有那么多经验listings
。)
答案2
您可以在底部继续添加行
\documentclass[tikz, border = 4pt]{standalone}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}
\begin{document}
\begin{tikzpicture}[
font = \ttfamily,
node distance = 1ex,
minimum height = 13pt,
outer sep = 0pt,
sq code/.style = {draw, fill = gray!20, opacity = 0.7},
ci code/.style = {draw, rounded corners, opacity = 0.7},
]
% line 1
\path node (function type) [sq code] {int}
node (function name) [right = of function type] {gilligan (}
node (argument j type) [sq code, right = of function name] {int}
node (argument j name) [ci code, right = of argument j type] {j}
node (function open) [right = of argument j name] {) \{};
\begin{pgfonlayer}{background}
\draw[sq code] ($ (function type.south west) + (-0.1, -0.1)$) rectangle (function
open.north east);
\end{pgfonlayer}
% line 2
\path node (for) [sq code, below right = of function type]{for}
node (open parenthesis) [right = of for]{(}
node (i type) [sq code, right = of open parenthesis]{int}
node (i init) [ci code, right = of i type]{i}
node (i init assign) [sq code, right = of i init]{=}
node (i init value) [right = of i init assign]{1;}
node (i stop) [ci code, right = of i init value]{i}
node (i stop assign) [sq code, right = of i stop]{<}
node (i stop value) [ci code, right = of i stop assign]{j}
node (i stop sep) [right = of i stop value]{;}
node (i step) [right = of i stop sep]{i}
node (i step value) [sq code, right = of i step]{++}
node (close parenthesis) [right = of i step value]{) \{};
\begin{pgfonlayer}{background}
\draw[sq code] ($ (i step.south west) + (-0.1, -0.1)$) rectangle
($ (i step value.north east) + (0.1, 0.1)$);
\end{pgfonlayer}
% line ...
\path (i stop value) edge[out = 90, in = 90, ->] (argument j name)
(i init) edge[out = -50, in = -140, ->] (i stop)
(i stop) edge[out = -50, in = -140, ->] (i step value);
\end{tikzpicture}
\end{document}