1

I am creating a template for exams. I would like to use a \newcommand to create on one hand the exams with only the questions and space for the answers and on the other hand also the solutions. I have already defined the following command, but so far it only displays the question.

\newcommand{\OffeneFrage}[3]{
\begin{enumerate}[resume]
\begin{samepage}
    \item {#1} \unskip\hspace*{\fill}~{#3}~P
    \nopagebreak
    \multido{}{#2}{\item[] \dotfill 
    }
\end{samepage}
\end{enumerate}
}

The first argument stands for the question, the second for the number of answer lines and the third for the score.

I would like to have the command display the question only with the answer if an optional argument is listed in the same command, for example

\OffeneFrage[A dog has four legs.]{How many legs does a dog have?}{2}{1}

Below is an example of how it looks now and how it might look. Can anyone help me with this? Many thanks in advance.

\documentclass{article}
\usepackage[ngerman]{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{multido}
\usepackage{enumitem}

\newcommand{\OffeneFrage}[3]{ \begin{enumerate}[resume] \begin{samepage} \item {#1} \unskip\hspace*{\fill}~{#3}~P \nopagebreak \multido{}{#2}{\item[] \dotfill % Punkte } \end{samepage} \end{enumerate} }

\begin{document}

\OffeneFrage{How many legs does a dog have?}{2}{5}

\end{document}

enter image description here

simande
  • 1,002

1 Answers1

2

The following provides the functionality you requested - an optional first argument that provides the answer to the question. The condition \IfValueTF{#1} checks whether an answer is supplied or not, and sets either the answer, or the answer plus a number of blank lines (in an attempt to yield a similar vertical gap that when no answer is provided.

enter image description here

\documentclass{article}

\usepackage{multido,xcolor,xfp} \usepackage{enumitem}

\NewDocumentCommand{\OffeneFrage}{ o m m m }{% \begin{enumerate}[resume] \begin{samepage} \item #2% Set question \unskip\hspace*{\fill}~#4~P\par% Set marks/points \nopagebreak \IfValueTF{#1} {\item[] {\color{red}#1}% \multido{}{\inteval{#3-1}}{\item[]}}% An answer is provided {\multido{}{#3}{\item[] \dotfill}}% No answer provided \end{samepage} \end{enumerate} }

\begin{document}

\OffeneFrage{How many legs does a dog have?}{2}{5}

\OffeneFrage[A dog has four legs]{How many legs does a dog have?}{2}{5}

\OffeneFrage{How many legs does a cat have?}{2}{5}

\end{document}

You may need \usepackage{xparse} in the preamble if your LaTeX distribution is not up-to-date.


You might also be interested in a different, key-value interface to your questions:

\OffeneFrage{question=...,answer=..,lines=.,points=.}

The order is not important, and you can omit some values (the lines and points; they default to 4 and 1, respectively). If no question is provided, nothing is printed. And an answer is only printed when \printanswerstrue is set.

If you set \printanswerstrue, this is the output:

enter image description here

\documentclass{article}

\usepackage{multido,xcolor,xfp} \usepackage{enumitem,xkeyval}

\makeatletter \define@cmdkey{QA}{question}[\relax]{} \define@cmdkey{QA}{answer}[\relax]{} \define@cmdkey{QA}{lines}[4]{}% Default of 4 lines \define@cmdkey{QA}{points}[1]{}% Default of 1 point \newif\ifprintanswers

\NewDocumentCommand{\OffeneFrage}{ m }{% \setkeys{QA} {question,answer,lines,points,% Set default values #1}% Set user-specified values % Empty check: https://tex.stackexchange.com/q/53068/5764 \if\relax\detokenize\expandafter{\cmdKV@QA@question}\relax % No question was supplied; do nothing \else \begin{enumerate}[resume] \begin{samepage} \item \cmdKV@QA@question% Set question \unskip\hspace*{\fill}% \ifnum\cmdKV@QA@points>0 % Print points if > 0 ~\cmdKV@QA@points~P\par \fi % Empty check: https://tex.stackexchange.com/q/53068/5764 \if\relax\detokenize\expandafter{\cmdKV@QA@answer}\relax % No answer was supplied \multido{}{\cmdKV@QA@lines}{\item[] \dotfill}% No answer provided; set lines \else % Answer was supplied \ifprintanswers \item[] {\color{red}\cmdKV@QA@answer}% Set answer \multido{}{\inteval{\cmdKV@QA@lines-1}}{\item[]}% Set additional gap \else \multido{}{\cmdKV@QA@lines}{\item[] \dotfill}% Set answer lines \fi \fi \end{samepage} \end{enumerate} \fi } \makeatother

%\printanswerstrue

\begin{document}

\OffeneFrage{ question={How many legs does a dog have?}, lines=2, points=5 }

\OffeneFrage{ answer={A dog has four legs}, question={How many legs does a dog have?}, lines=2, points=5 }

\OffeneFrage{ lines=3, question={How many legs does a cat have?}, }

\end{document}

So you can toggle the questions/answers with a boolean.

Werner
  • 603,163
  • Wow, thats amazing! Your new Interface is really great! Thank you so much :) I only have one Problems. Often questions are divided into several sub-questions, where the main question has no lines and number of points. E.G. 1. A child at the schoolyard tells you: "Dogs, cats and spiders have four feet". a) Take a stand on this statement. 2P ............... ............... b) Name three other animals with four feet. 4P ............... …………… With my previous interface I could simply put an enumerate environment around the \open question, now it throws an error message. How can this be fixed? – simande Jan 15 '22 at 08:43
  • @simande: Try this code that now provides \MainFrage{...} ... \EndMainFrage. \MainFrage only considers the question key-value, although you can add the other elements there as well. They are just ignored. – Werner Jan 15 '22 at 13:23
  • 1
    @simande: I've updated my answer after (corrected some bugs). – Werner Jan 16 '22 at 20:22
  • I'd suggest one more change: Drop the question key and make that one a mandatory argument. A question should always have a question, imho it doesn't make much sense keeping that one optional. – Skillmon Jan 23 '22 at 17:57