LaTeX:Lstlisting自动识别代码片段

6

我正在编写一个程序(使用C语言,但我认为这并不是很重要),与LaTeX文档相关。我希望文档中包含来自我的原始代码的代码片段。

为了包含源代码并使其保持最新状态,我在文档中执行以下操作:

\lstinputlisting[firstline=200, lastline=210]{../src/source.c)

这会自动加载位于../src/source.c的第200到210行(包含一个函数)到我的文件中。
但是,如果我在第200行之前添加了一些行,这意味着第200行“向下移动了一些行”,因此我必须进行调整才能获得原始函数。
所以我的问题是:有人知道如何动态地告诉lstinputlisting(或任何适当的替代品)要选择哪些行吗?
我想象中的解决方案是:我在我的C源代码中添加特殊注释,这些注释将被lstinputlisting识别。
/// lstinputlisting "myfunc" BEGIN
int myFunction(int x){
  return x+2;
}
/// lstinputlisting "myfunc" END

然后,lstlisting会扫描文件,并仅包含BEGINEND之间的行。
4个回答

15

我是在你的帖子发布几个月后回答的,但是我下面描述的 lstlistings 功能已经在该软件包中存在了几年。

要查找的关键字是选项 linerange,以及为方便起见的 rangeprefixrangesuffix

这里是一个完整的示例。

\documentclass{article}
\usepackage{fullpage,times,listings}
\lstloadlanguages{C++}

\lstset{language=C++,keywordstyle=\bfseries,commentstyle=\itshape,
  rangeprefix=//----------------,rangesuffix=----------------,
  includerangemarker=false,columns=spaceflexible}

\begin{document}
We first show the main function.
\lstinputlisting[linerange=main0-main1]{code.cpp}
Then we show the implementation.
\lstinputlisting[linerange=fact0-fact1]{code.cpp}
\end{document}

然后将以下内容保存在code.cpp中:

#include <cassert>

//----------------fact0----------------
// A recursive implementation of factorial
int factorial(int i)
{
    if(i)
        return i * factorial(i-1);
    else
        return 1;
}
//----------------fact1----------------

//----------------main0----------------
// Test the implementation.
int main()
{
    assert(factorial(5) == 120);
}
//----------------main1----------------

这是一个好的解决方法,因为人们不可避免地会编辑代码,然后更新TeX文件中的行号变得繁琐。使用符号可以解决这个问题,但它也会在代码本身留下痕迹,如果行数或宽度太多发生变化,需要确认排版输出看起来仍合理。

最后,在编辑代码后,只有在标记块内插入/删除时才需要重新对latex文件进行排版。


1

在 C 语言中使用 #include 不是更简单吗?

虽然不完美,但已经足够好了。

这里有一个例子(无法编译,因为我上次写 C 语言已经是 5 年前了):

C 主程序:

    #include <stdio.h>

    //function included from separate file -- will be included in LaTeX too
    #include "fun_x.c"         

    int main() 
    {
      int d = 0;
      printf("%d", fun_x(d));

    //code included from separate file -- will be included in LaTeX too
    #include "calc.c"

      return 0;
    }

fun_x.c 文件:

int fun_x(int c) 
{
  c++;
  return c;
}

calc.c 文件:

d = 99;
d = fun_x(d);

LaTeX源代码:

\begin{document}
...

\lstinputlisting{../src/fun_x.c)

...

\lstinputlisting{../src/calc.c)

...

\end{document}

1
我能想到的唯一合理的方法是创建一个 makefile 并让它负责生成正确的输出。假设 sourcefile.c 在 ./src 中,LaTeX 文件在 ./tex 中,则 ./tex/Makefile 可以如下所示:
doc.tex: sourcefile.grep
        <command to compile doc.tex>
sourcefile.grep: 
        <command to grep/whatever to dump from 
        ../src/sourcefile.c to ./tex/sourcefile.grep>

doc.tex 中的 lstlistings 将指向 ./src/sourcefile.grep


是的,我也想到了这点,但对我来说似乎有些过度设计。看到你的编辑:grep可能是一个选项。 - phimuemue

1

一段时间以前像这样的东西在TeX SE上被讨论过, 一个答案使用了 catchfilebetweentags 这个包。虽然这并没有直接解决你的问题,但或许你可以使用它来将你想要的片段传递给\lstlistings,再通过一个临时文件实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接