マクロでの繰り返し文について教えて下さい

マクロでの繰り返し文について教えて下さい

- 山田 太郎 の投稿
返信数: 21
図を3つ並べて表示するマクロを作成しようとしたところ、引数を10個取ってしまい作成できなかったので、繰り返し文を使い以下のようなマクロを作成しました。

--------------------------------------------------------------
¥ProvidesPackage{thfig}
 
¥newcommand{¥thfig}[4][width=4cm]{
¥newcounter{cnt}
¥setcounter{cnt}{0}
¥begin{figure}[htbp]
¥loop ¥ifnum ¥vaule{cnt}<4
¥begin{minipage}{.33¥textwidth}
 ¥centering
 ¥includegraphics[#1]{#2}
 ¥caption{#3}
 ¥label{fig:#4}
¥end{minipage}
¥stepcounter{cnt}
¥repeat
¥end{figure}
}
--------------------------------------------------------------


¥thfig{hoge.jpg}{hogeです}{hoge}{puge.jpg}{pugeです}{puge}{fuge.jpg}{fugeです}{fuge}

本文中に上記ような命令で図を3つ並べて表示したいのですが、
Undefind control sequence.
¥iterate -> ¥ifnum ¥value

といったエラーが出てしまいうまくいきません。
どなたか教えてはいただけないでしょうか?


山田 太郎 への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
マクロの中でスペルが違っているだけで
\vaule は \value の間違いでは。

それと
\newcounter{cnt}
は \thfig という命令の定義の中に書くべきでないと思います。

\newcounter が中に書いてあるということは \thfig という命令を実行するたびに
毎回 cnt というカウンタを無駄に用意し続けることを意味します。

追記:
一旦 \setcounter{cnt}{0} も中ではないと書きましたが撤回します。
また、\value と \newcounter を直したら即そのまま期待どおりの出力に
なるのかどうかは知りません。多分これだと hoge の図が 3 回繰り返す
だけですよね。
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
今回の目的だと「引数10個」なので繰り返しなどなくとも

\newcommand{\thfig}[1][width=4cm]{%
  \def\thincludegraphics{\includegraphics[#1]}%
  \thsubfig
}
\newcommand{\thsubfig}[9]{%
  \begin{figure}[htbp]
  \begin{minipage}{.33\textwidth}%
    \centering
    \thincludegraphics{#1}%
    \caption{#2}%
    \label{fig:#3}%
  \end{minipage}%
  \begin{minipage}{.33\textwidth}%
    \centering
    \thincludegraphics{#4}%
    \caption{#5}%
    \label{fig:#6}%
  \end{minipage}%
  \begin{minipage}{.33\textwidth}%
    \centering
    \thincludegraphics{#7}%
    \caption{#8}%
    \label{fig:#9}%
  \end{minipage}%
  \end{figure}%
}

でも十分な気がしますね。
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- 山田 太郎 の投稿
こちらのやり方で試してみたところ、1つは正常に表示されるのですが、最初の2つがとても大きく重なり合うように表示されてしまいます
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- Z. R. の投稿

蛇足ですが:

\newcounter が中に書いてあるということは \thfig という命令を実行するたびに 毎回 cnt というカウンタを無駄に用意し続けることを意味します。

\newcounter{ctr} を2回実行すると、2回目は重複定義でエラーになります。

Z. R. への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
> \newcounter{ctr} を2回実行すると、2回目は重複定義でエラーになります。

ああ混同していました、そうでした。

> 1つは正常に表示されるのですが、最初の2つがとても大きく
> 重なり合うように表示されてしまいます

仰ることがよくわかりません。お書きになったソース全体と、出てきた結果の
pdf かスクリーンショットでも添付してください。百聞は一見にしかずです
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- 山田 太郎 の投稿
ソースコードとしては

¥thfig{huge.BMP}{huge}{huge}{puge.BMP}{puge}{puge}{fuge.BMP}{fuge}{fuge1}


styファイルは

¥ProvidesPackage{thfig}

¥newcommand{¥thfig}[1][width=4cm]{
¥def¥thincludegraphics{¥includegraphics[#1]}
¥thsubfig
}

¥newcommand{¥thsubfig}[9]{
¥begin{figure}[H]
¥begin{minipage}{.33¥textwidth}
 ¥centering
 ¥includegraphics{#1}
 ¥caption{#2}
 ¥label{fig:#3}
¥end{minipage}
 ¥begin{minipage}{.33¥textwidth}
 ¥centering
 ¥includegraphics{#4}
 ¥caption{#5}
 ¥label{fig:#6}
¥end{minipage}
 ¥begin{minipage}{.33¥textwidth}
 ¥centering
 ¥includegraphics[width = 4cm]{#7}
 ¥caption{#8}
 ¥label{fig:#9}
¥end{minipage}
¥end{figure}
}

です。
山田 太郎 への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
なぜ私がせっかく書いたマクロを書き変えていらっしゃるのか
サッパリ理解できません。よくわからないのに書き変えたら、
そりゃあ変なことになるよなあ。

今回の場合、山田太郎さんのソースだと、[width=4cm] が
最初の二つの図に対して効いていないことに気づきませんか。

\documentclass{jsarticle}
\usepackage[dvipdfmx]{graphicx}
\newcommand{\thfig}[1][width=4cm]{%
  \def\thincludegraphics{\includegraphics[#1]}%
  \thsubfig
}
\newcommand{\thsubfig}[9]{%
  \begin{figure}[htbp]
  \begin{minipage}{.33\textwidth}%
    \centering
    \thincludegraphics{#1}%
    \caption{#2}%
    \label{fig:#3}%
  \end{minipage}%
  \begin{minipage}{.33\textwidth}%
    \centering
    \thincludegraphics{#4}%
    \caption{#5}%
    \label{fig:#6}%
  \end{minipage}%
  \begin{minipage}{.33\textwidth}%
    \centering
    \thincludegraphics{#7}%
    \caption{#8}%
    \label{fig:#9}%
  \end{minipage}%
  \end{figure}%
}
\begin{document}

\thfig{test01.jpg}{huge}{huge}{test02.png}{puge}{puge}{test03.jpg}{fuge}{fuge1}

\thfig[width=2cm]{test01.jpg}{huge}{huge}{test02.png}{puge}{puge}{test03.jpg}{fuge}{fuge1}

\end{document}

これでいいはずでは。

最初の一つの引数(オプション引数)を3つ全ての図に使いまわしたい
という意図だと推測して、私は昨晩このマクロを提示したわけです。
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- 山田 太郎 の投稿
私の確認不足でした。

無事解決しました。ありがとうございます。
山田 太郎 への返信

Re: マクロでの繰り返し文について教えて下さい

- 北見 けん の投稿
解決したようでよかったですね。みなさんお疲れさまです。

今回の問題とは関係ないのですが、
> なぜ私がせっかく書いたマクロを書き変えていらっしゃるのか
> サッパリ理解できません。
に関して謎解きを試みてみます。

書き換えられていたのは、
(1) 各行末の「%」を省いた
(2) \thincludegraphics を \includegraphics にした
(3) 最後の \includegraphics にオプション引数 [width=..] を付け加えた
(4) \begin{figure}のオプション引数を [H] にした
でしょうか。

(2) については次のようなことかと思いました。
まず、この方は、アプリケーション間でコピー&ペーストを使って
テキストを移す習慣がないのだと思います。(例えば、
初めの投稿でエラーメッセージが手打ちのようです)
それで、おそらく、示されたコードを手で入力する際に、
もともと手元にあったソースから
使える部分はコピー&ペーストして利用したのだと思います。(これは
エディタ内の作業なので身についている)
それで、手元のソースになかったマクロ定義部分では、
正しく \thincludegraphics とキーボードから入力したけれど、
下のほうの繰り返し部分については、
\centering
\thincludegraphics{#1}%
\caption{#2}%
\label{fig:#3}%
が手元のソースにあった部分とよく似ていたために、\thinclude... と \include.. の
違いに気付かずに、手元の \include.. のほうをまとめてコピー&ペースト したのだと思います。

そうすると、マクロ呼び出し時のオプション引数が引き継がれなくなるので、
中の \includegraphics にオプション引数を直打ちしてみるわけですが、
これも慣れていないので三つあるうちの最後のところにつけてみて
(3) のようになってしまった。

(1) については、「%」はコメントを表すのだから、なくても良いはずと考えて、
なくともよいなら初めから入力しなくて良いだろうと取ってしまった。

一見するとわざわざ書き換えたように見えて、いったいなぜだと思えますが、
上記のような事情であれば、あながち理解できなくもないかなあ、と思いました。
かなり憶測交じりですけれど、いかがでしょうか。
北見 けん への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
確かにコピペの習慣がない可能性はありますね。
なるべく私はコピペするようにしていますが、個人差があるのでしょうか。

> (例えば、初めの投稿でエラーメッセージが手打ちのようです)

これについては、たとえばエラーが表示されるシェル「だけ」コピペの仕方がわからない
という状況があり得ると思っていたため、特に不自然に感じていませんでした。
(たとえば Windows のコマンドプロンプトとかは、メッセージ上を右クリックしても
一見コピペできなそう。しかし、実際はメニューバーを右クリックすることでコピペの
メニューが出てくる)。
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
> なぜ私がせっかく書いたマクロを書き変えていらっしゃるのか
> サッパリ理解できません。よくわからないのに書き変えたら、
> そりゃあ変なことになるよなあ。

これまた憶測ですが、もしかしたらネットを見るブラウザ環境と、実際に
LaTeX を使っているパソコンなどが違っていて、見比べながら写していた、
ということも考えられるかもしれないと思いました。

ちょっときつい言い方だったかな?気を悪くされていたらすみません。
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- ut の投稿

# アセトアミノフェンさんへの返信ではないのですが、ここにぶら下げさせてください。

既に問題は解決済みなので、単純に興味本位でのお尋ねになるのですけれど、質問者の方が当初意図されたようなことって、実現できるのでしょうか?

例えば、すごく素朴に考えてみますと、

\newcounter{MyNum}

\newcommand{\cmdA}[1][foo]{%
  \setcounter{MyNum}{0}
  \loop \ifnum \value{MyNum} < 3\relax
  \stepcounter{MyNum}
  \cmdB{#1}
  \repeat
}

\newcommand{\cmdB}[4]{%
  (#1)(#2)(#3)(#4)%
}

みたいに定義したら、

\cmdA{a}{b}{c}{d}{e}{f}{g}{h}{i}
  ↓
  ↓
\cmdB{foo}{a}{b}{c}\cmdB{foo}{d}{e}{f}\cmdB{foo}{g}{h}{i}

とか、

\cmdA[bar]{a}{b}{c}{d}{e}{f}{g}{h}{i}
  ↓
  ↓
\cmdB{bar}{a}{b}{c}\cmdB{bar}{d}{e}{f}\cmdB{bar}{g}{h}{i}

という風になることを期待されてたんじゃないかなと思うのですけれど、実際には、これではうまくいきませんよね…。
ut への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
(さっき一旦書いたものは間違っていたので削除して、改めて。)

> 質問者の方が当初意図されたようなことって、実現できるのでしょうか?

ループをどうやって引き起こすかちょっと悩んだのですが、
素朴に考えると汚いマクロができました(^^;)

\documentclass{jsarticle}

\newcounter{MyNum}
% ユーザ向けマクロ
\newcommand{\maincmd}[1][bar]{%
  \def\cmdC{\cmd[#1]}%
  \setcounter{MyNum}{0}%
  \renewcommand{\cmdB}[3]{\cmdC{##1}{##2}{##3}\cmdA}%
  \cmdA
}
% 以下は内部マクロ
\newcommand{\cmdB}{}
\newcommand{\cmdA}{%
  \ifnum\value{MyNum}=2\relax
    \renewcommand{\cmdB}[3]{\cmdC{##1}{##2}{##3}}%
  \else
    \stepcounter{MyNum}%
  \fi
  \cmdB
}
% \includegraphics みたいにオプション引数を取る外部マクロ
\newcommand{\cmd}[4][foo]{%
  (1:#1,2:#2,3:#3,4:#4)%
}

\begin{document}

\maincmd{a}{b}{c}{d}{e}{f}{g}{h}{i}

\maincmd[hoge]{a}{b}{c}{d}{e}{f}{g}{h}{i}

\end{document}


# 個人的には引数10個は見づらいので、もしやるとしても
# \maincmd{{a}{b}{c}}{{d}{e}{f}}{{g}{h}{i}}
# みたいな書式の方が好みですが。
# この手のものは XyMTeX がよく使っていた気がします。
ut への返信

Re: マクロでの繰り返し文について教えて下さい

- Z. R. の投稿

「自分が素直に書けばこうなる」というコードを載せておきます。といっても、個数が固定の場合にループを使うのはそれ自身が“素直でない”ので、個数を可変にしました。

%-------------------------
%% 宣言
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{multifig}

%% 変数
\newcount\xx@mfcnt     % 画像の個数
\newdimen\xx@mfwidth   % 個々の領域の横幅

%% \multifig[<画像オプション>]{<個数>}
%%     {<ファイル名>}{<キャプション>}{<ラベル名>}...
\newcommand{\multifig}[2][width=4cm]{%
  % 前処理部分
  \begin{figure}[htbp]%
    \xx@mfcnt=#2\relax
    \xx@mfwidth\textwidth \divide\xx@mfwidth\xx@mfcnt
    \def\xx@include{\includegraphics[#1]}%
    \let\xx@next\xx@multifig@a
    \xx@next}
\def\xx@multifig@a#1#2#3{%
  % ループ部分
  \begin{minipage}{\xx@mfwidth}%
    \centering
    \xx@include{#1}%
    \caption{#2}%
    \label{fig:#3}%
  \end{minipage}%
  % カウントダウンしてゼロなら後処理に切り替える
  \advance\xx@mfcnt\m@ne
  \ifnum\xx@mfcnt=\z@
    \let\xx@next\xx@multifig@b
  \fi
  \xx@next}% 末尾再帰
\def\xx@multifig@b{%
  % 後処理部分
  \end{figure}}
%<EOF>----------------------------------

使用例:

% pLaTeX 文書
\documentclass[dvipdfmx,a4paper]{jsarticle}
\usepackage{graphicx,multifig}
\begin{document}
\multifig{3}
  {1F431.pdf}{ねこ}{cat}
  {1F363.pdf}{\TeX}{tex}
  {2603.pdf}{\LaTeX}{latex}
\end{document}
Z. R. への返信

Re: マクロでの繰り返し文について教えて下さい

- ut の投稿

アセトアミノフェンさん、Z. R. さん、お返事をありがとうございます!

手元で少し考えてみたときには、「展開の順番を制御しなきゃならないのかなー」 などと思っていたのですが、別にそういうわけではなかったのですね。

あと、そもそもの方針について、

> # 個人的には引数10個は見づらいので、

とか、

> 個数が固定の場合にループを使うのはそれ自身が“素直でない”

というのはまったくその通りだと思いますし、また、引数の書き方についても、(万一 9 個必要な場合には) 私でも、

> # \maincmd{{a}{b}{c}}{{d}{e}{f}}{{g}{h}{i}}

とか、

> \multifig{3}
>  {1F431.pdf}{ねこ}{cat}
>  {1F363.pdf}{\TeX}{tex}
>  {2603.pdf}{\LaTeX}{latex}

みたいに書くと思います。

余計な追加質問に早々に回答をお寄せくださって、本当にありがとうございます。
ut への返信

Re: マクロでの繰り返し文について教えて下さい

- 北見 けん の投稿
出遅れましたが、マクロ談義は大好きなので、
枯れ木もなんとやらということで置かせてください。

アセト アミノフェンさんのコードと差し替えて動くようにしてあります。

\newcommand{\maincmd}[1][bar]{%
\setcounter{MyNum}{1}%
\cmdB[#1]%
}
\newcommand{\cmdB}[4][]{%
\cmd[#1]{#2}{#3}{#4}%
\stepcounter{MyNum}%
\csname
cmd%
\ifnum\value{MyNum}<3
B%
\fi
\endcsname[#1]%
}

最初のところで取ったオプション引数をテンポラリマクロに保存せずに、
次の展開時に送り渡すのが TeX っぽくて好きですね。
あと、\csname を使ったトリックも。
(追記:あれ?コードのインデントが消えちゃった。他の方のは入っているのに、なぜ?)
北見 けん への返信

Re: マクロでの繰り返し文について教えて下さい

- aminophen の投稿
\csname … \endcsname なるほど。

プレインテキストフォーマットにすると
インデントが残ります。
Moodle オートフォーマットは消えます。
aminophen への返信

Re: マクロでの繰り返し文について教えて下さい

- 北見 けん の投稿
これでインデントが効くかな?
  \csname
    test
  \endcsname

この入力フォームの下にある、投稿のフォーマットを選べるはずのところを見てみたら、
HTMLフォーマットになったまま固定されているようで、ドロップダウンリストもなく、
しばらく悩みました。アカウントの設定のほうを調べると投稿文の編集についての設定があって、
HTML編集フォームを使うような設定になっていました。この設定を解除すると、
無事にプレインテキストフォーマットが選べるようになりました。
フォームの見た目も全然変わってHTML装飾用のツールボタンがなくなったり、
そういえば以前はこのシンプルなフォームだった気が。
## 以前 anonymous で書き込めたときがそうだったのかな?

HTMLフォームになっていたときは、テキスト編集エリアをクリックしてもカーソルも出ずにいて、
まず段落の設定の右揃えボタンや中央揃えボタンをどれか操作しないと記入が始められない
というような挙動にも悩まされていましたが、今回、それも解消できました。

アセト アミノフェンさん、ありがとうございました。
(オフトピックで失礼しました > みなさん)
ut への返信

Re: マクロでの繰り返し文について教えて下さい

- ワトソン の投稿
引数の数が増えてしまうときの工夫としてもう1つ思いつくものに (x)keyval パッケージの key-value リストを利用する方法がありますね.

個人的に LaTeX において {hoge} の形の引数が可変個というのはちょっと非直感的な仕様にも思えるので

\multifig{
  files = {1F431.pdf, 1F363.pdf, 2603.pdf},
  titles = {ねこ, \TeX, \LaTeX},
  labels = {cat, tex, latex}}

のようなインターフェースを用意したくなります(時間的な都合で実装例は省略).
これならば,例えば各画像を1:1:2の幅比で出力できるようなオプションを追加することも自然な形でできそうです.
ワトソン への返信

Re: マクロでの繰り返し文について教えて下さい

- 本田 知亮 の投稿
おんなじことを夕べ書いてて
眠気に負けました(^^;

{}のなかに順番を要求すると
私は絶対に間違えるので

\multifig{%
  {%
    file  = {1F431.pdf},
    title = [option]{ねこ},
    label = {cat}%
  },
  {%
    file  = {1F363.pdf},
    title = [option]{\TeX},
    label = {tex}%
  }%
  {%
    file  = {2603.pdf},
    title = [option]{\LaTeX},
    label = {latex}%
  }%
}

こういう感じでどうかなと思います.

\@for(\@tfor,カンマ区切りどっちだったっけ)と
keyval系でできるんじゃないかなとは思います
(optionとれるkeyval系マクロがあったような・・)