从外部数据文件读取整数以在 LaTeX 中记录编程代码

从外部数据文件读取整数以在 LaTeX 中记录编程代码

我试图用 LaTeX 记录我的 MATLAB 编程代码。为此,我使用mcode定义 MATLABlstlisting 环境的包。使用命令

\newcommand{\mfileMain}{main.m}
\newcommand{\mfileMainFirstNumber}{\mfileMainFirstLine}
\newcommand{\mfileMainFirstLine}{26}
\newcommand{\mfileMainLastLine}{33}
\lstinputlisting[firstnumber=\mfileMainFirstNumber,
                 firstline=\mfileMainFirstLine,
                 lastline=\mfileMainLastLine]{\mfileMain}

我设置了firstnumberfirstlinelastline参数,并使用它们将一段 MATLAB 代码导入到 LaTeX 文档中 \lstinputlisting。但是,当我在 之前添加一些代码 \mfileMainFirstLine(在本例中为 26)时,代码会移动,文档也会被破坏。要修复此问题,我必须更新行号。

我正在尝试通过向我的 MATLAB 程序添加“跟踪器”来解决这个问题。我使用命令

filename=['lstinputlisting_line_numbers_' mfilename '.txt'];
fileID=fopen(filename,'w');

使用命令创建一个文本文件,在其中存储代码记录的行号

dbstack_eval=dbstack;fprintf(fileID,[num2str(dbstack_eval.line+1) '\n']);

.这将生成一个文本文件lstinputlisting_line_numbers_.txt,内容如下

53
62
75
91

假设我想记录 MATLAB 程序的四个部分main.m

我现在想做的就是在命令中使用此行号数据 \lstinputlisting。也许可以将行号存储在 中\newcommands{}{},或者也许有更好、更优雅的方法。这样,如果我添加新的代码行,行号就会自动更新。因此,我的 LaTeX 文档仍然没问题,我不用自己更新行号,从而节省了很多时间。

最小工作示例如下所示。LaTeX 文件 main.tex将包含内容

\documentclass[a4paper]{article}
\usepackage[framed,numbered]{mcode}

% Data for the 'lstinputlisting' environments.
\newcommand{\mfileMain}{main.m}
\newcommand{\mfileMainFirstNumberA}{\mfileMainFirstLineA}
\newcommand{\mfileMainFirstLineA}{WHAT SHOULD I PUT HERE?}
\newcommand{\mfileMainLastLineA}{WHAT SHOULD I PUT HERE?}
\newcommand{\mfileMainFirstNumberB}{\mfileMainFirstLineB}
\newcommand{\mfileMainFirstLineB}{WHAT SHOULD I PUT HERE?}
\newcommand{\mfileMainLastLineB}{WHAT SHOULD I PUT HERE?}

\begin{document}
    In the code
    \lstinputlisting[firstnumber=\mfileMainFirstNumberA,
                     firstline=\mfileMainFirstLineA,
                     lastline=\mfileMainLastLineA]{\mfileMain}
    we calculate the .... 

    And in the code
    \lstinputlisting[firstnumber=\mfileMainFirstNumberB,
                     firstline=\mfileMainFirstLineB,
                     lastline=\mfileMainLastLineB]{\mfileMain}
    we calculate the.....
\end{document}

.MATLAB 文件main.m将包含以下内容

%% Line number output.

filename=['lstinputlisting_line_numbers_' mfilename '.txt'];
fileID=fopen(filename,'w');

dbstack_eval=dbstack;fprintf(fileID,[num2str(dbstack_eval.line+1) '\n']);    
%% Input to be specified by user.

alpha=10; % PDE parameter.
x_s=0; % Starting coordinate.
x_e=1; % End coordinate.
N_n=1e2+1; % (N)umber of (n)odes.
N_ip=2; % (N)umber of (i)ntegration (p)oints.

dbstack_eval=dbstack;fprintf(fileID,[num2str(dbstack_eval.line+1) '\n']);    
fclose(fileID); % Close the file 'fileID'.

答案1

我认为,使用会更简单、更可靠线范围标记listings您的 m 文件的注释中。请参见下面的示例。我使用了matlab-prettifier包而不是mcode,但该方法应该适用于其中任何一个。

基本上,您可以使用键为这些行范围标记定义一个前缀rangeprefix;在这里,我使用的前缀只是一个百分号(%)后跟一个空格字符:

rangeprefix=\%\ ,

请注意,这两个字符都必须在此处转义(但在 MATLAB 代码中则不必)。然后,在代码中使用一对描述性字符串来标记每个感兴趣范围的开始和结束。在下面的示例中,我使用paramendparam作为第一个感兴趣范围,使用param2endparam2作为第二个感兴趣范围。确保使用

includerangemarker=false

如果您不希望标记本身出现在输出中。

您可以在listings手动的。

在此处输入图片描述

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{matlab-prettifier}

\usepackage{filecontents}
\begin{filecontents*}{sample.m}
foo=3
bar=5
baz=foo
foo=bar
bar=baz
% param
% first set of parameters
alpha=10; % PDE parameter.
x_s=0; % Starting coordinate.
x_e=1; % End coordinate.
N_n=1e2+1; % (N)umber of (n)odes.
N_ip=2; % (N)umber of (i)ntegration (p)oints.
% endparam
clear baz
% param2
% second set of parameters
beta=20;
N = 42;
% endparam2
\end{filecontents*}

\lstset{
  style              = Matlab-editor,
  basicstyle         = \mlttfamily,
  rangeprefix        = \%\ ,
  includerangemarker = false,
}

\begin{document}
\lstinputlisting[linerange=param-endparam]{sample.m}
\lstinputlisting[linerange=param2-endparam2]{sample.m}
\end{document}

答案2

我不确定第 4 个数字应该是多少,但是这会读取数字并将它们分配给宏。

除此之外,我们还应该考虑一下 Jubob 的评论 ;-)

\documentclass[paper=a4,12pt]{scrbook}

\usepackage{etoolbox}%
\usepackage{blindtext}%
\usepackage[framed,numbered]{mcode}%

\newread\mylinenumbers

\newcommand{\mfileMain}{main.m}%

\def\mFileMainFirstLine{}
\def\mFileMainFirstNumber{}
\def\mFileMainLastLine{}


\AtBeginDocument{%
  \openin\mylinenumbers=lstinputlisting_line_numbers_.tex
  \read\mylinenumbers to \mFileMainFirstNumber
  \read\mylinenumbers to \mFileMainFirstLine
  \read\mylinenumbers to \mFileMainLastLine
  \closein\mylinenumbers
}%




\begin{document}

\lstinputlisting[firstnumber=\mFileMainFirstNumber,
                     firstline=\mFileMainFirstLine,
                     lastline=\mFileMainLastLine]{\mfileMain}

\end{document}

改良版

\ReadinLineNumbers在发生之前使用单独的命令\lstinputlisting,从而更新行号信息。

原则上,这可以直接添加到 \lstinputlisting` 命令中,但它会中断该命令的其他调用。

\documentclass[paper=a4,12pt]{scrbook}
\usepackage[framed,numbered]{mcode}%

\newread\mylinenumbers

\newcommand{\mfileMain}{main.m}%

\def\mFileMainFirstLine{}
\def\mFileMainFirstNumber{}
\def\mFileMainLastLine{}

% This command assumes that there always triples for the line number information
\newcommand{\ReadinLineNumbers}{%
  \read\mylinenumbers to \mFileMainFirstNumber
  \read\mylinenumbers to \mFileMainFirstLine
  \read\mylinenumbers to \mFileMainLastLine
}%

\AtBeginDocument{%
  \openin\mylinenumbers=lstinputlisting_line_numbers_.tex
}%

\AtEndDocument{%
  \closein\mylinenumbers
}%

\begin{document}

\ReadinLineNumbers

\lstinputlisting[firstnumber=\mFileMainFirstNumber,
                     firstline=\mFileMainFirstLine,
                     lastline=\mFileMainLastLine]{\mfileMain}

\ReadinLineNumbers

\lstinputlisting[firstnumber=\mFileMainFirstNumber,
                     firstline=\mFileMainFirstLine,
                     lastline=\mFileMainLastLine]{\mfileMain}

\end{document}

相关内容