我需要在lstlisting
C/C++ 代码中绘制漂亮的图形。我正在尝试制作类似这样的内容
这是我目前所做的
\documentclass[11pt]{article}
\usepackage{listingsutf8}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\newcommand{\tikzmark}[2]{%
\tikz[overlay,remember picture] \node[text=black,
inner sep=2pt] (#1) {#2};}
\begin{document}
\begin{lstlisting}[language=c,escapeinside={(*@}{@*)}]
#include <stdio.h>
int main (void)
{
int value1, value2, sum;//declaring
value1 = 50;//assign values
value2 = 25;
sum = value1 + value2;//sum them
//output
printf ("%d(*@\tikzmark{a}{} @*)+%d(*@\tikzmark{b}{} @*)= %d(*@\tikzmark{c}{} @*)\n", value1(*@\tikzmark{a1}{} @*), value2(*@\tikzmark{b1}{} @*), sum(*@\tikzmark{c1}{} @*));
(*@
\begin{tikzpicture}[overlay,remember picture]
\node (a) at (a.{east}) {};
\node (a1) at (a1.{north west}) {};
\node (b) at (b.{east}) {};
\node (b1) at (b1.{north west}) {};
\node (c) at (c.{east}) {};
\node (c1) at (c1.{north west}) {};
\draw[->,red,in=120,out=100] (a1) to (a);
\draw[->,red,in=120,out=100] (b1) to (b);
\draw[->,red,in=120,out=100] (c1) to (c);
\end{tikzpicture}
@*)
return 0;
}
\end{lstlisting}
\end{document}
如何使 tikz 节点和箭头更美观?
答案1
您可以调整in
和out
角度以及移动起点和终点的位置:
笔记:
- 我还添加了
basicstyle=\ttfamily
更多listings
类似的输出。 \tikzmark
左侧添加了A和每个标记的右侧,以简化中点的计算。
代码:
\documentclass[11pt]{article}
\usepackage{listingsutf8}
\usepackage{tikz}
\usetikzlibrary{decorations.text,calc}
\newcommand{\tikzmark}[2]{%
\tikz[overlay,remember picture] \node[text=black,
inner sep=2pt] (#1) {#2};}
\newcommand{\VerticalShiftForArrows}{0.0em,+2.75ex}%
\newcommand{\VerticalShiftForBar}{0.0em,+2.0ex}%
\newcommand{\Stub}{0.0em,-0.6ex}%
\newcommand{\DrawOverBar}[3][]{%
\coordinate (top left) at ($(#2) +(\VerticalShiftForBar)$);
\coordinate (start) at ($(top left) +(\Stub)$);
\coordinate (top right) at ($(#3) +(\VerticalShiftForBar)$);
\coordinate (end) at ($(top right)+(\Stub)$);
\draw [#1] (start) -- (top left) -- (top right) -- (end);
}%
\newcommand{\DrawArrows}[3][]{%
\coordinate (Start Mid) at ($(#2Left)!0.5!(#2Right) + (\VerticalShiftForArrows)$);
\coordinate (End Mid) at ($(#3Left)!0.5!(#3Right) + (\VerticalShiftForArrows)$);
\draw[-stealth, thick, #1] (Start Mid) to (End Mid);
}
\begin{document}
\begin{lstlisting}[language=c,escapeinside={(*@}{@*)},basicstyle=\ttfamily]
#include <stdio.h>
int main (void)
{
int value1, value2, sum;//declaring
value1 = 50;//assign values
value2 = 25;
sum = value1 + value2;//sum them
//output
printf ("(*@\tikzmark{aLeft}{}@*)%d(*@\tikzmark{aRight}{}@*)+(*@\tikzmark{bLeft}{}@*)%d(*@\tikzmark{bRight}{}@*)= (*@\tikzmark{cLeft}{}@*)%d(*@\tikzmark{cRight}{}@*)\n", (*@\tikzmark{value1Left}{}@*)value1(*@\tikzmark{value1Right}{}@*), (*@\tikzmark{value2Left}{}@*)value2(*@\tikzmark{value2Right}{}@*), (*@\tikzmark{sumLeft}{}@*)sum(*@\tikzmark{sumRight}{}@*));
(*@
\begin{tikzpicture}[overlay,remember picture]
\foreach \x/\y in {a/red, c/blue, value1/red, sum/blue} {
\DrawOverBar[-, \y, thick]{\x Left.north}{\x Right.north}
}
\foreach \x/\y in {b/brown, value2/brown} {% Needs special handling as we are putting this below
\renewcommand{\VerticalShiftForBar}{0.0em,-0.8ex}%
\renewcommand{\Stub}{0.0em,+0.6ex}%
\DrawOverBar[-, \y, thick]{\x Left.south}{\x Right.south}
}
\DrawArrows[red, in=20, out=160]{value1}{a}
\DrawArrows[blue, in=30, out=150, distance=6.5ex]{sum}{c}
\renewcommand{\VerticalShiftForArrows}{0.0em,-2.0ex}%Needs special handling as we are putting this below
\DrawArrows[brown, in=-30, out=-150]{value2}{b}
\end{tikzpicture}
@*)
return 0;
}
\end{lstlisting}
\end{document}