用 latex3 创建表:错误额外对齐选项卡

用 latex3 创建表:错误额外对齐选项卡

我想用宏创建一个表。不幸的是,我得到了一个错误。下面是一个简单的例子:

\documentclass[a4paper,12pt]{article} 
 
\begin{document} 
 
\ExplSyntaxOn 
 
%%% Create a new table nxn 
%%% First parameter: number of lines and columns 
%%% Second parameter: entries of the table 
\NewDocumentCommand{\TableCreate}{mm}{ 
    \int_set:Nn \l_tmpa_int {1} 
    \begin{tabular}{|c|c|c|c|} 
    \hline 
        \int_do_until:nNnn {\l_tmpa_int} > {#1} 
        { 
            %%% Test if this the last column of the line 
            \int_compare:nNnTF {\l_tmpa_int} = {#1} 
            { 
                %%% This is the last colum 
                \clist_item:nn {#2} {\l_tmpa_int} & \\ \hline 
            } 
            { 
                %%% This is not the last column 
                \clist_item:nn {#2} {\l_tmpa_int}  & 
            } 
        } 
        \hline 
    \end{tabular} 
} 
 
\ExplSyntaxOff 
 
    \TableCreate{4}{1,2,3,4} 

\end{document} 

这里我有一个宏TableCreate{4}{1,2,3,4}。我想创建一个一行四列的表格。当我想在单元格中写入内容时,我必须测试它是否是最后一列。这就是我使用的原因

\int_do_until:nNnn {\l_tmpa_int} > {#1}

我使用变量\l_tmpa_int来迭代列。我使用宏的第一个参数来了解我有多少列。稍后我想创建列数与行数不相同的表。当我编译此代码时,我得到:

! Extra alignment tab has been changed to \cr.
<recently read> \endtemplate 
                             
l.33    \TableCreate{4}{1,2,3,4}

我不明白为什么会出现这个错误。

感谢您的帮助。

答案1

正如 David 所说,您在处理组时遇到了问题(而且您缺少\int_incr:N实际逐步执行的clist)。代码中的最小更改变体是简单地使用全局变量而不是本地 int 变量。请注意,我将调用放在\int_gincr:N每个单元格前面,并使用来-1补偿这一点。这是必要的,因为如果您将它放在后面,\\ \hline您最终会在第二行的第一个单元格中得到不可扩展的材料,并在输出中获得第二行。

此外,以下代码不使用硬编码的 4 列数,而是*{#1}{c|}使用所需的精确列数。

\documentclass[a4paper,12pt]{article}

\ExplSyntaxOn

\int_new:N \g_LucArmand_tmp_int
%%% Create a new table nxn
%%% First parameter: number of lines and columns
%%% Second parameter: entries of the table
\NewDocumentCommand \TableCreate { m m }
  {
    \int_gset_eq:NN \g_LucArmand_tmp_int \c_one_int
    \begin{tabular}{|*{#1}{c|}}
      \hline
      \int_do_until:nNnn {\g_LucArmand_tmp_int} > {#1}
        {
          \int_gincr:N \g_LucArmand_tmp_int
          \clist_item:nn {#2} { \g_LucArmand_tmp_int - 1 }
          %%% Test if this the last column of the line
          \int_compare:nNnTF { \g_LucArmand_tmp_int - 1 } = {#1}
            { %%% This is the last column
              \\ \hline
            }
            { %%% This is not the last column
              &
            }
        }
    \end{tabular}
  }

\ExplSyntaxOff

\begin{document}

\TableCreate{4}{1,2,3,4}

\end{document}

但我们可以进一步改进这一点。为什么需要指定元素的数量,我们可以让 TeX 为我们进行计数(这使用一个可选参数默认为 的数量clist):

\documentclass[a4paper,12pt]{article}

\ExplSyntaxOn

\int_new:N \g_LucArmand_tmp_int
%%% Create a new table nxn
%%% First parameter: number of lines and columns
%%% Second parameter: entries of the table
\NewDocumentCommand \TableCreate { O{\clist_count:n{#2}} m }
  {
    \int_gset_eq:NN \g_LucArmand_tmp_int \c_one_int
    \begin{tabular}{|*{#1}{c|}}
      \hline
      \int_do_until:nNnn {\g_LucArmand_tmp_int} > {#1}
        {
          \int_gincr:N \g_LucArmand_tmp_int
          \clist_item:nn {#2} { \g_LucArmand_tmp_int - 1 }
          %%% Test if this the last column of the line
          \int_compare:nNnTF { \g_LucArmand_tmp_int - 1 } = {#1}
            { %%% This is the last column
              \\ \hline
            }
            { %%% This is not the last column
              &
            }
        }
    \end{tabular}
  }

\ExplSyntaxOff

\begin{document}

\TableCreate[3]{1,2,3,4}

\end{document}

但是第一段和第二段代码都没有实现你在文档注释中指定的行为(行数列),为此,最简单的解决方案是添加一个\int_mod:nn调用:

\documentclass[a4paper,12pt]{article}

\ExplSyntaxOn

\int_new:N \g_LucArmand_tmp_int
%%% Create a new table nxn
%%% First parameter: number of lines and columns
%%% Second parameter: entries of the table
\NewDocumentCommand \TableCreate { O{\clist_count:n{#2}} m }
  {
    \int_gset_eq:NN \g_LucArmand_tmp_int \c_one_int
    \begin{tabular}{|*{#1}{c|}}
      \hline
      \int_do_until:nNnn {\g_LucArmand_tmp_int} > { \clist_count:n {#2} }
        {
          \int_gincr:N \g_LucArmand_tmp_int
          \clist_item:nn {#2} { \g_LucArmand_tmp_int - 1 }
          %%% Test if this the last column of the line
          \int_compare:nNnTF
            { \int_mod:nn { \g_LucArmand_tmp_int - 1 } {#1} } = \c_zero_int
            { %%% This is the last column
              \\ \hline
            }
            { %%% This is not the last column
              &
            }
        }
    \end{tabular}
  }

\ExplSyntaxOff

\begin{document}

\TableCreate[2]{1,2,3,4}

\end{document}

答案2

另一个答案为这项工作提供了充分的理由和好的代码,但还有一种更巧妙的方法。

\documentclass[a4paper,12pt]{article}

\ExplSyntaxOn

\int_new:N \l__lucarmand_tablecreate_cols_int
\seq_new:N \l__lucarmand_tablecreate_body_seq

%%% First parameter: number of lines and columns
%%% Second parameter: entries of the table
\NewDocumentCommand \TableCreate { O{\clist_count:n{#2}} m }
  {
    \int_set:Nn \l__lucarmand_tablecreate_cols_int { #1 }
    \seq_set_from_clist:Nn \l__lucarmand_tablecreate_body_seq { #2 }
    \begin{tabular}{|*{#1}{c|}}
      \hline
      \seq_map_indexed_function:NN \l__lucarmand_tablecreate_body_seq \__lucarmand_tablecreate:nn
    \end{tabular}
  }

\cs_new_protected:Nn \__lucarmand_tablecreate:nn
  {
    #2 % the entry
    \int_compare:nTF { \int_mod:nn { #1 } { \l__lucarmand_tablecreate_cols_int } == 0 }
      {% end of row
        \\ \hline
      }
      {% still columns to go
        &
      }
  }

\ExplSyntaxOff

\begin{document}

\TableCreate[2]{1,2,3,4}
\TableCreate[4]{a,b,c,d,e,f,g,h,i,j,k,l}

\end{document}

表体一次性创建,\\\hline当索引是列数的倍数时插入,否则&追加。

在此处输入图片描述

我们还可以添加检查,确保项目数是列数的倍数;这里的补救措施是添加?项目。

\documentclass[a4paper,12pt]{article}

\ExplSyntaxOn

\int_new:N \l__lucarmand_tablecreate_cols_int
\seq_new:N \l__lucarmand_tablecreate_body_seq

%%% First parameter: number of lines and columns
%%% Second parameter: entries of the table
\NewDocumentCommand \TableCreate { O{\clist_count:n{#2}} m }
  {
    \int_set:Nn \l__lucarmand_tablecreate_cols_int { #1 }
    \seq_set_from_clist:Nn \l__lucarmand_tablecreate_body_seq { #2 }
    \int_compare:nF
      {% is the number of items a multiple of #1?
       \int_mod:nn { \seq_count:N \l__lucarmand_tablecreate_body_seq } { #1 } == 0
      }
      {% no! Add entries
       \prg_replicate:nn
         {% add the necessary
           #1 - \int_mod:nn { \seq_count:N \l__lucarmand_tablecreate_body_seq } { #1 } 
         }
         {% blank entries
          \seq_put_right:Nn \l__lucarmand_tablecreate_body_seq { ? }
         }
      }
    \begin{tabular}{|*{#1}{c|}}
      \hline
      \seq_map_indexed_function:NN \l__lucarmand_tablecreate_body_seq \__lucarmand_tablecreate:nn
    \end{tabular}
  }

\cs_new_protected:Nn \__lucarmand_tablecreate:nn
  {
    #2 % the entry
    \int_compare:nTF { \int_mod:nn { #1 } { \l__lucarmand_tablecreate_cols_int } == 0 }
      {% end of row
        \\ \hline
      }
      {% still columns to go
        &
      }
  }

\ExplSyntaxOff

\begin{document}

\TableCreate[2]{1,2,3,4}
\TableCreate[4]{a,b,c,d,e,f,g,h,i,j,k,l}

\bigskip

\TableCreate[4]{a,b,c,d,e,f,g,h,i,j,k,l,m}

\end{document}

在此处输入图片描述

相关内容