如何命令 LaTeX 将非值视为 0

如何命令 LaTeX 将非值视为 0

我有这个命令

\newcommand{\lines}[1]{\multido{}{#1}{\vskip 5mm \makebox[\linewidth]{\dotfill}} \vskip 8mm\setlength{\rightmargin}{5em}}

它让我能够轻松地创建虚线。例如:

当我写入 \lines{3} 时,它会产生:

.........................................
.........................................
.........................................

如何告诉 LaTeX 将 \lines{} 视为 \lines{0}

谢谢。

答案1

只需在前导零处加一个,这样循环次数就是0#1。当#1为空时,则为零,否则为#1

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \lines { m }
  {
    \int_step_inline:nn { 0#1 }
      { \vskip 5mm~\noindent \makebox[\linewidth]{\dotfill} }
    \vskip 8mm~\setlength{\rightmargin}{5em}%
  }
\ExplSyntaxOff
\begin{document}
a\lines{}

b\lines{3}
\end{document}

这是一个稍微复杂一些的版本,它接受\count寄存器和一些边缘情况(绝对不是万无一失的)?

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \lines { m }
  {
    \int_step_inline:nn { \tl_if_blank:eT {#1} { 0 } #1 }
      { \vskip 5mm~\noindent \makebox[\linewidth]{\dotfill} }
    \vskip 8mm~\setlength{\rightmargin}{5em}%
  }
\ExplSyntaxOff
\begin{document}
a\lines{}

b\lines{3}

c\lines{ 3 }

\count178=3
d\lines{\count178}

\newcount\x\x=3
e\lines{\x}

\chardef\x=3
f\lines{\x}

g\lines{\numexpr 1+1+1}

h\lines{\dimexpr 0.00005pt}

\def\empty{}
i\lines{\empty}

\def\empty{}
j\lines{ \empty}

% Still fails in this case, but then you're asking for it ;-)
\protected\def\empty{}
% k\lines{\empty}

\end{document}

答案2

我会做些不同的事情,将参数设为\lines可选参数,默认值为零。这样可以\lines打印零条虚线并\lines[3]打印线条等。

修改后的代码如下:

\documentclass{article}
\usepackage{multido}

\newcommand{\lines}[1][0]{%
  \multido{}{#1}{\vskip 5mm \makebox[\linewidth]{\dotfill}}%
  \vskip 8mm\setlength{\rightmargin}{5em}%
}

\begin{document}

  \lines

  \lines[3]

  \lines[6]

\end{document}

顺便说一句,发布完整的代码片段总是比发布代码片段更好最小工作示例因为这可以让人们更轻松地使用和修改您的代码。

编辑 如果在您的用例中您需要\line{}与以下相同,\line{0}那么您可以使用\detokenize

\documentclass{article}
\usepackage{multido}
\usepackage{xparse}

\newcommand{\lines}[1]{%
\multido{}{\if\relax\detokenize{#1}\relax0\else#1\fi}{\vskip 5mm \makebox[\linewidth]{\dotfill}}%
  \vskip 8mm\setlength{\rightmargin}{5em}%
}

\begin{document}

  \lines{}

  \lines{3}

  \lines{6}

\end{document}

\detokenize{#1}“中和” 中出现的所有类别代码,这样#1就不会出现意外。 将 的“内容”#1与 进行比较\relax。 如果#1为空,则\detokenize{#1}为空,因此\if语句扩展为\if\relax\relax0\else#1\fi。换句话说,如果#1为空,则\if-语句扩展为0,否则扩展为#1

答案3

-command的用法\multido是:

\multido{⟨variables⟩}{⟨repetitions⟩}{⟨stuff⟩}

似乎⟨重复⟩可以通过任何产生 TeX-⟨数字⟩-数量。

如果⟨重复⟩为负数,⟨变量⟩将会倒数计算。

因此与您的代码示例\lines{3}\lines{-3}收益相同。

如果⟨重复⟩以某种形式提供,例如,表示一个\count-寄存器或一个\countdef-token,只是添加0⟨重复⟩-argument 会导致一些! Missing number, treated as zero.-error。如果⟨重复⟩以字母常量的形式提供,只需添加0⟨重复⟩- 参数也不能产生预期的结果。

因此我建议\multido只在以下情况下应用 -thing

\romannumeral\number\number⟨number⟩␣0

\romannumeral-\number\number⟨number⟩␣0

結果空虚。

\romannumeral如果要转换的数字不是正数,则不会默默返回任何标记。所以,让我们通过0-trickery附加将要转换的数字和要转换的负数都乘以 10 ,以确保事情能够顺利进行,例如(之后需要一个空格来分隔 20,这是 -register 的数字)。\number\number⟨number⟩␣0\count20\count如果持有的论点⟨number⟩包含某些东西,则会产生⟨可选标志⟩只有持有空或空白/产生空或空白的参数的情况⟨number⟩才属于这一类——附加项0会将表达式转换为有效的 ⟨number⟩数量,其值为0

\documentclass[a4paper]{article}

% Vertically adjust the page layout so that the example creates exactly one page:
\csname@ifundefined\endcsname{pdfpagewidth}{}{\pdfpagewidth=\paperwidth\relax}%
\csname@ifundefined\endcsname{pdfpageheight}{}{\pdfpageheight=\paperheight\relax}%
\csname@ifundefined\endcsname{pagewidth}{}{\pagewidth=\paperwidth\relax}%
\csname@ifundefined\endcsname{pageheight}{}{\pageheight=\paperheight\relax}%
\pagestyle{plain}%
\headheight=0ex\relax
\headsep=0ex\relax
\topmargin=1cm\relax
\footskip=.5\topmargin\relax
\begingroup\normalfont
\expandafter\endgroup\expandafter\advance\expandafter
\footskip\the\dimexpr.5\ht\strutbox\relax\relax
\textheight=\paperheight\relax
\advance\textheight-2\topmargin\relax
\advance\topmargin-1in\relax
%%%%%%%%%%%%% Page layout adjustments done. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\usepackage{multido}

\makeatletter
\newcommand\exchange[2]{#2#1}%
\newcommand{\lines}[1]{%
  \if Y\expandafter\exchange\expandafter{\romannumeral\number\number#1 0}%
       {\expandafter\@firstofone\expandafter{\romannumeral-\number\number#1 0}}Y%
    \expandafter\@gobble\else\expandafter\@firstofone\fi
  {\multido{}{#1}{\vskip 5mm \makebox[\linewidth]{\dotfill}}}%
  \vskip8mm \setlength{\rightmargin}{5em}%
}%
\makeatother


\begin{document}

\verb*|\somecount=3|:

\verb*|\lines{\somecount}|:

\newcount\somecount
\somecount=3

\lines{\somecount}

\hrule\kern\dp\strutbox

\verb*|\lines{\the\somecount}|:

\lines{\the\somecount}

{
\hrule\kern\dp\strutbox

\verb*|\count90=3|

\verb*|\lines{\count90}|:

\count90=3 
\lines{\count90}

\hrule\kern\dp\strutbox

\verb*|\lines{\count90 }|:

\lines{\count90 }

}

\hrule\kern\dp\strutbox

\verb*|\lines{3}|:

\lines{3}

\hrule\kern\dp\strutbox

\verb*|\lines{-000003}|:

\lines{-000003}

\hrule\kern\dp\strutbox

\verb*|\lines{}|:

\lines{}

\hrule\kern\dp\strutbox

\verb*|\lines{0}|:

\lines{0}

\hrule\kern\dp\strutbox

\end{document}

在此处输入图片描述

但仍然存在问题:

  • 无论是使用您的示例中提供的 -command 的变体\line还是使用上述示例中提供的 -command 的变体,\line您都会收到很多overfull \hbox-warnings,因为通过点填充的线\makebox获得 with\linewidth时没有考虑到水平\parindent-glue 的插入。
  • 由于您的示例适用,因此\vskip您可能希望确保垂直模式。
  • 您可能还希望避免插入水平\parindent-glue 和垂直\parskip-glue,方法是在排版行时不让 TeX 进入不受限制的水平模式。
  • 线之间的垂直距离将不再是 5mm,而是 5mm+ \baselineskip。这可以通过应用来纠正\offinterlineskip
  • 我不清楚 的意思是什么\setlength{\rightmargin}{5em}

我想您希望有一个可以指定的命令

  • 行数——在下面的例子中,这是的强制参数\lines
  • 线之间的距离——在下面的例子中,这是Distance between lines=...可选参数的键\lines(默认为\dimexpr5mm+\baselineskip\relax),
  • 增加\vskip构成上一行文本的框底部与第一条虚线之间的距离 - 在以下示例中,这是Distance at top=...可选参数的键\lines(默认值为 8mm),
  • 增加\vskip最后一条虚线与形成下一行文本的框顶部之间的距离 - 在以下示例中,这是Distance at bottom=...可选参数的键\lines(默认值为 8mm),
  • 在没有排版虚线的情况下,增加\vskip上一行文本框底部与下一行文本框顶部之间的距离——在下面的例子中,这是Gap if no dotted lines=...可选参数的键\lines(默认值为 8mm),
  • 从右侧缩进虚线——在下面的例子中,这是Indent from the right=...可选参数的 -key \lines(默认为 0em),
  • 从左侧缩进虚线 - 在下面的例子中,这是Indent from the left=...可选参数的 -key \lines(默认为 0em)。

 

\documentclass{article}
\usepackage{keyval}
\usepackage{multido}

\makeatletter
\newcommand\exchange[2]{#2#1}%
\@ifdefinable\lines@DistanceBetweenLines{\edef\lines@DistanceBetweenLines{\the\dimexpr5mm+\baselineskip\relax}}%
\define@key{dottedlines}{Distance between lines}{\edef\lines@DistanceBetweenLines{\the\dimexpr#1\relax}}%
\@ifdefinable\lines@DistanceAtTop{\edef\lines@DistanceAtTop{\the\dimexpr8mm\relax}}%
\define@key{dottedlines}{Distance at top}{\edef\lines@DistanceAtTop{\the\dimexpr#1\relax}}%
\@ifdefinable\lines@DistanceAtBottom{\edef\lines@DistanceAtBottom{\the\dimexpr8mm\relax}}%
\define@key{dottedlines}{Distance at bottom}{\edef\lines@DistanceAtBottom{\the\dimexpr#1\relax}}%
\@ifdefinable\lines@GapIfNoLines{\edef\lines@GapIfNoLines{\the\dimexpr8mm\relax}}%
\define@key{dottedlines}{Gap if no dotted lines}{\edef\lines@GapIfNoLines{\the\dimexpr#1\relax}}%
\@ifdefinable\lines@IndentFromTheRight{\edef\lines@IndentFromTheRight{\the\dimexpr0em\relax}}%
\define@key{dottedlines}{Indent from the right}{\edef\lines@IndentFromTheRight{\the\dimexpr#1\relax}}%
\@ifdefinable\lines@IndentFromTheLeft{\edef\lines@IndentFromTheLeft{\the\dimexpr0mm\relax}}%
\define@key{dottedlines}{Indent from the left}{\edef\lines@IndentFromTheLeft{\the\dimexpr#1\relax}}%
\newcommand{\lines}[2][]{%
  \begingroup
  \ifvmode\else\par\fi
  \setkeys{dottedlines}{#1}%
  \offinterlineskip
  \if Y\expandafter\exchange\expandafter{\romannumeral\number\number#2 0}%
       {\expandafter\@firstofone\expandafter{\romannumeral-\number\number#2 0}}Y%
    \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
  {%
    \vskip\dimexpr\lines@DistanceAtTop-\lines@DistanceBetweenLines\relax
    \multido{}{#2}{%
      \vskip\lines@DistanceBetweenLines
      \hbox to\hsize{\kern\lines@IndentFromTheLeft\relax\dotfill\kern\lines@IndentFromTheRight\relax\null}%
    }%
    \vskip\lines@DistanceAtBottom\relax
  }%
  {\vskip\lines@GapIfNoLines\relax}%
  \par
  \endgroup
}%
\makeatother

\begin{document}

\hrule\kern\dp\strutbox

\verb*|\somecount=3|:

\verb*|\lines{\somecount}|:

\newcount\somecount
\somecount=3

\lines{\somecount}

\hrule\kern\dp\strutbox

\verb*|\lines{\the\somecount}|:

\lines{\the\somecount}

{
\hrule\kern\dp\strutbox

\verb*|\count90=3|

\verb*|\lines{\count90}|:

\count90=3 
\lines{\count90}

\hrule\kern\dp\strutbox
\kern-\topsep

\begin{verbatim*}
\lines[Distance between lines=5mm,
       Distance at top=1cm,
       Distance at bottom=1cm,
       Gap if no dotted lines=0cm,
       Indent from the left=2cm,
       Indent from the right=4cm]{\count90 }:
\end{verbatim*}
\kern-\topsep\kern-\partopsep
\lines[Distance between lines=5mm,
       Distance at top=1cm,
       Distance at bottom=1cm,
       Gap if no dotted lines=0cm,
       Indent from the left=2cm,
       Indent from the right=4cm]{\count90 }
\hrule\kern\dp\strutbox
}

\newpage

\hrule\kern\dp\strutbox

\verb*|\lines{3}|:

\lines{3}

\hrule\kern\dp\strutbox

\verb*|\lines{ 3 }|:

\lines{ 3 }

\hrule\kern\dp\strutbox

\verb*|\lines{-000003}|:

\lines{-000003}

\hrule\kern\dp\strutbox

\verb*|\lines{}|:

\lines{}

\hrule\kern\dp\strutbox

\verb*|\lines{ }|:

\lines{ }

\hrule\kern\dp\strutbox

\verb*|\lines{0}|:

\lines{0}

\hrule\kern\dp\strutbox

\end{document}

在此处输入图片描述

在此处输入图片描述

(任何产生的序列都被视为。)\lines{⟨optional signs⟩}\lines{0}

答案4

这也行得通:

\documentclass{book}
\usepackage{multido}

\begin{document}

\newcommand{\lines}[1]{%
\if!#1!\relax\else
  \multido{}{#1}{\vskip 5mm \makebox[\linewidth]{\dotfill}}%
\fi
  \vskip 8mm\setlength{\rightmargin}{5em}%

}

\lines{}

\lines{3}

\end{document}

相关内容