tikz 노드 이름에 스택 데이터 전달

tikz 노드 이름에 스택 데이터 전달

스택 데이터 구조를 사용하려고 합니다(여기에 설명되어 있음:길이/치수를 푸시/팝하거나 저장하시겠습니까?) tikzmark 노드 이름 집합의 다양한 이름을 저장합니다(에서 설명한 대로).tikzmark수동) 내 텍스트 전체에 흩어져 있습니다.

별도로 스택 구현(WE1)과 \tikzmark(WE2)는 완벽하게 작동하지만 결합된 동작은 어떻게든 다중 오류와 충돌합니다.

\tikzmark팝된 스택 데이터 요소를 명령(아래 MWE) 내의 노드 이름으로 전달하려고 할 때 무엇이 ​​잘못되었는지 평생 알 수 없습니다 . 이것은 내 LaTeX 코드가 \pop 명령을 즉시 평가하지 않아서 발생하는 문제입니까(나는 이리저리 시도해 보았지만 성공 \expandafter하지 \edef못했습니다...)? 또한 \pop{\latexstack}a 에 전달하려고 시도했지만 \newcommand{}해당 방법도 작동하지 못했습니다.

MWE[잘못된 결합 동작...]

\documentclass{article}
\usepackage{blindtext, tikz}
    \newtoks\latexstack
    \latexstack={\empty}

    \def\push#1#2{
        \begingroup
        \toks0={{#1}}
        \edef\act{\endgroup\global#2={\the\toks0 \the#2}}\act
    }

    \def\pop#1{
        \begingroup
        \edef\act{\endgroup\noexpand\SplitOff\the#1(tail)#1}\act
    }

    \def\SplitOff#1#2(tail)#3{
        \ifx#1\empty
            \errhelp{Attempting to pop empty stack #3.}
            \errmessage{You can't pop an empty stack.}
        \else
            #1\global#3={#2}
        \fi
    }

    \newcommand\tikzmark[1]{\tikz[overlay,remember picture] \node(#1) {};}

\begin{document}
    \push{A1}{\latexstack}
    \push{B2}{\latexstack}

    \blindtext \tikzmark{\pop{\latexstack}}\\ 
    \blindtext \tikzmark{\pop{\latexstack}}\\ 

    \begin{tikzpicture}[remember picture,overlay,scale=0.5] 
        \draw[red] (A) -- (B);
    \end{tikzpicture}
\end{document}

WE1[스택 데이터 구조의 올바른 동작: A1, B2, C3 및 D4가 데이터 구조에서 순차적으로 푸시되고 팝됩니다.]

\documentclass{article}
    \newtoks\latexstack
    \latexstack={\empty}

    \def\push#1#2{
        \begingroup
        \toks0={{#1}}
        \edef\act{\endgroup\global#2={\the\toks0 \the#2}}\act
    }

    \def\pop#1{
        \begingroup
        \edef\act{\endgroup\noexpand\SplitOff\the#1(tail)#1}\act
    }

    \def\SplitOff#1#2(tail)#3{
        \ifx#1\empty
            \errhelp{Attempting to pop empty stack #3.}
            \errmessage{You can't pop an empty stack.}
        \else
            #1\global#3={#2}
        \fi
    }

\begin{document}
    \push{A1}{\latexstack}
    \push{B2}{\latexstack}
    \push{C3}{\latexstack}
    \push{D4}{\latexstack}

    \pop{\latexstack},\\ 
    \pop{\latexstack},\\ 
    \pop{\latexstack},\\ 
    \pop{\latexstack}.
\end{document}

WE2[올바른 동작 \tikzmark: 점 A와 B가 표시되고 빨간색 선으로 연결됩니다.]

\documentclass{article}
\usepackage{blindtext, tikz}

    \newcommand\tikzmark[1]{\tikz[overlay,remember picture] \node(#1) {};}

\begin{document}
    \blindtext \tikzmark{A}\\
    \blindtext \tikzmark{B}

    \begin{tikzpicture}[remember picture,overlay,scale=0.5] 
        \draw[red] (A) -- (B);
    \end{tikzpicture}
\end{document}

답변1

여기서 문제는 확장이라고 생각합니다. TikZ가 노드를 생성할 때 노드 이름은 \edef.

OP의 원래 코드를 가정하고 다음을 고려하십시오.

\push{A1}{\latexstack}
\push{B2}{\latexstack}
\edef\nodename{\pop{\latexstack}}
\show\nodename

이는 전체 확장을 보여주며 다음을 제공합니다(로그 파일에서).

! Undefined control sequence.
\pop #1^^@- \begingroup \edef \act 
                                 {\endgroup \noexpand \SplitOff \the #1(tail...
l.36     \edef\nodename{\pop{\latexstack}
                                       }
! Undefined control sequence.
\pop ... \noexpand \SplitOff \the #1(tail)#1}\act 

l.36     \edef\nodename{\pop{\latexstack}
                                       }
> \nodename=macro:
-> \begingroup \edef {\endgroup \SplitOff {B2}{A1}\empty (tail)\latexstack }.
l.37     \show\nodename

참고로 문제는~ 아니다그건 \act정의되지 않았습니다. \let\act=\relax가 프리앰블 어딘가에 배치되면 오류는 사라지 지만 그 내용은 \nodename여전히 ​​원하는 노드 이름이 아닌 LaTeX 코드 전체입니다.

\popto한 가지 해결책은 스택 맨 위에 있는 값을 매크로에 팝한 다음 노드 이름으로 사용하는 명령을 사용하는 것입니다 (주의. \push매크로도 다시 구현했습니다).

\def\push#1#2{%
  \def\tmp{{#1}}%
  \expandafter\expandafter\expandafter%
    #2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}

\def\popto#1#2{%
  \expandafter\SplitOffTo\the#1\stop{#1}{#2}%  
}

\def\SplitOffTo#1#2\stop#3#4{%
  \def\tmp{#1}%
  \ifx\tmp\empty%
    \errhelp{Attempting to pop empty stack #3.}%
    \errmessage{You can't pop an empty stack.}%
  \else%
    \def#4{#1}\global#3={#2}%
  \fi%
}

이는 다음과 같이 사용될 수 있습니다:

\newtoks\latexstack
\latexstack={\empty}
\push{A1}{\latexstack}
\push{B2}{\latexstack}

\popto{\latexstack}{\nodename}
\tikzmark{\nodename}
\show\nodename
Some text \tikzmark{\nodename}

\popto{\latexstack}{\nodename}
\tikzmark{\nodename}
\show\nodename
Some more text \tikzmark{\nodename}

로그 파일에는 다음과 같은 내용이 표시됩니다.

> \nodename=macro:
->B2.
l.31 \show\nodename

> \nodename=macro:
->A1.
l.34 \show\nodename

이 모든 것이 약간 성가신 것처럼 보이면 해당 \popto항목을 매크로에 묶을 수 있습니다 \tikzmarkpop.

\documentclass[border=5]{standalone}
\usepackage{tikz}

\def\push#1#2{%
  \def\tmp{{#1}}% 
  \expandafter\expandafter\expandafter%
    #2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
\ignorespaces}

\def\popto#1#2{%
  \expandafter\SplitOffTo\the#1\stop{#1}{#2}%  
}

\def\SplitOffTo#1#2\stop#3#4{% 
  \def\tmp{#1}
  \ifx\tmp\empty% 
    \errhelp{Attempting to pop empty stack #3.}%
    \errmessage{You can't pop an empty stack.}%
  \else%
    \def#4{#1}\global#3={#2}%
  \fi}


\def\tikzmarkpop#1{%
\popto{#1}{\nodename}%
\tikz[remember picture, overlay]\coordinate(\nodename);} 

\newtoks\latexstack
\latexstack={\empty}

\begin{document}

\push{A1}{\latexstack}
\push{B2}{\latexstack}  

Some text\tikzmarkpop{\latexstack}
Some more text\tikzmarkpop{\latexstack}

\begin{tikzpicture}[remember picture, overlay] 
  \draw [red, <->] (A1) -- (B2);
\end{tikzpicture}
\end{document}

여기에 이미지 설명을 입력하세요

관련 정보