如何在列表中画箭头来解释位置关联?

如何在列表中画箭头来解释位置关联?

我需要在lstlistingC/C++ 代码中绘制漂亮的图形。我正在尝试制作类似这样的内容 printf函数讲解

这是我目前所做的

在此处输入图片描述

\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

您可以调整inout角度以及移动起点和终点的位置:

在此处输入图片描述

笔记:

  • 我还添加了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}

相关内容