PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LaTeX: Probleme mit \newcommand + Argumente



fmidon
15-05-2007, 14:02
************************************************** **************
GELÖST (siehe letzter Post)
************************************************** **************


Hi,

ich habe weniger Probleme mit der Definition eines neuen Befehl, vielmehr
mit den Argumenten.

Der Kontext: Ich schreibe gerade ein Pflichtenheft. Ich habe mir eine
neue Umgebung für die Produkt-Funktionen gebaut, die die Funktionen
mit /F 00x/ nummeriert. Das funktioniert einwandfrei, bloss möchte
ich, sobald ich über \ref{} auf eine Funktion verweise, auch im Text
"/F 00x/" stehen haben.

Aber erstmal die relevanten Code-Ausschnitte:

Hauptdatei:


\usepackage{fmtcount} % Brauch ich, um Counter zu manipulieren

% counter müssen (anscheinend ?) in der Haupt-Datei definiert werden.
\newcounter{function}
\setcounter{function}{0}
\newcounter{functionhelper}
\setcounter{functionhelper}{0}

\newcounter{functionref}
\setcounter{functionref}{0}


Die Kommandos werden in einer externen Datei definiert:


% The item for the new environment 'funlist'
\newcommand{\fun}[1]{\item \textbf{\textsf{#1}} }

\newcommand{\funref}[1]{/F\padzeroes[3]\decimalnum{#1}/} % ***

\newenvironment{funlist}
{% This is the begin code
\begin{list}{\textbf{\textsf{\textit{/F\padzeroes[3]\decimal{function}/}}}}
{\usecounter{function} \setlength{\rightmargin}{\rightmargin}}
\setcounter{function}{\thefunctionhelper}
}
{% This is the end code
\setcounter{functionhelper}{\thefunction}
\end{list}
}

In der Umgebung musste ich ein bisschen tricksen, weil der Zähler bei \end{} immer zurückgesetzt wurde.

Im Text sollte das dann so ausschauen:


\begin{funlist}
(...)
\fun{Bla}\label{bla-label}
(...)
\end{funlist}


Referenziert soll das dann so werden (Definition: siehe ***):


(...)Bla,bla wie \funref{\ref{bla-label}}


Dabei kommt die Fehlermeldung:


! Missing number, treated as zero.


Nach googeln hab ich herausgefunden, dass das mit fehlenden
Argumenten oder falscher Argument-Reihenfolge zu tun haben soll.
Naja...Ich denke meine Definition und Verwendung ist in Ordnung.

Möglicherweise liegt der Hund im Paket fmtcount begraben. Übergebe ich
nämlich \funref eine Zahl, funktioniert das einwandfrei.

Ich hatte noch andere Ansätze, bei der ich z.B. \funref nur das Label übergeben habe, aber auch diese scheiterten meist mit der gleichen Fehlermeldung.

Vielen Dank schon mal für das Durchlesen :)

Markus

P.S.: Die vielen code-Umgebungen möge man mir verzeihen. Ich mach künftig weniger, wenn das zuviel ist.

Stefan_K
15-05-2007, 14:20
Hi Markus,

die Code-Ausschnitte sollten übersetzbar sein und \funref funktionieren. Evtl. liegt der Fehler woanders, und die Stelle ist unter den Ausschnitten hier nicht aufgeführt? Erstelle doch einmal ein Minimalbeispiel (http://www.minimalbeispiel.de/) und poste es hier.

Grüße,

Stefan

fmidon
15-05-2007, 14:44
Hi,

entschuldigung, wusste nach den Board-Regeln zwar, dass sich das gehört,
dachte aber das ganze ist zu umfangreich.

Das beispiel verwendet bei mir unicode. Könnte bei euch Probleme machen. Hab die Stelle mal gekennzeichnet.
Hier mal (kompilierbar, die nicht-funktionierenden Versionen sind auskommentiert) ein einfaches Beispiel:


\documentclass[a4paper,pointlessnumbers]{scrartcl}
\usepackage[utf8]{inputenc} % <--- Könnte Probleme machen.
\usepackage[ngerman]{babel}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage{fmtcount}

% paragraph formatting:
\setlength{\parindent}{0ex}
\setlength{\parskip}{1ex plus0.3ex minus0.1ex}

\newcounter{function}
\setcounter{function}{0}
\newcounter{functionhelper}
\setcounter{functionhelper}{0}

\newcounter{functionref}
\setcounter{functionref}{0}


\newcommand{\fun}[1]{\item \textbf{\textsf{#1}} }

\newcommand{\funref}[1]{ /F\padzeroes[3]\decimalnum{#1}/}

\newcommand{\ofunref}[1]{/F\padzeroes[3]\decimalnum{\ref{#1}}/}

\newenvironment{funlist}
{% This is the begin code
\begin{list}{\textbf{\textsf{\textit{/F\padzeroes[3]\decimal{function}/}}}}
{\usecounter{function} \setlength{\rightmargin}{\rightmargin}}
\setcounter{function}{\thefunctionhelper}
}
{% This is the end code
\setcounter{functionhelper}{\thefunction}
\end{list}
}

\title{Beispiel}
\author{Icke}

\begin{document}
\restylefloat{figure}

\clubpenalty = 10000
\widowpenalty = 10000
\displaywidowpenalty = 10000

\maketitle
\newpage
\section{Produkt-Funktionen}
Bei dieser, funktionierenden, Version kann der Befehl funref das label nicht auflösen.
Das Kommando ofunref funktioniert nicht, es soll aber so (zumindest in der Richtung)
funktionieren.
\subsection{Diese Funktionen}
\begin{funlist}
\fun{Ich will referenziert werden}\label{label}
Ich bin wichtig.
\end{funlist}

\subsection{Andere Funktionen}
Und noch richtig Text.
\begin{funlist}
\fun{Hier geht es um die Wurst}
Ich möchte Funktion \funref{1} referenzieren.
Aber \begin{verbatim}
\funref{\ref{label}}
\end{verbatim}
funktioniert nicht. Vgl. %\funref{\ref{label}}
Oder ofunref mit Parameter label: %\ofunref{label}
\end{funlist}



\end{document}


Hoffentlich hilft das.
Und Danke nochmals..

Markus

sommerfee
15-05-2007, 15:45
Hoffentlich hilft das.

Ja, tut es, danke. Ich habe einfach mal ein wenig aufgeräumt und dies hier daraus gemacht:



\documentclass[a4paper,pointlessnumbers]{scrartcl}
\usepackage[ngerman]{babel}
\usepackage{fmtcount}

\newcounter{function}
\renewcommand\thefunction{/F\padzeroes[3]\decimal{function}/}

\newcommand{\fun}[1]{\item \textbf{\textsf{#1}} }

\newenvironment{funlist}
{% This is the begin code
\begin{list}{\textbf{\textsf{\textit{\thefunction} }}}%
{\refstepcounter{function}\setlength{\rightmargin} {\leftmargin}}%
}
{% This is the end code
\end{list}
}

\begin{document}

\section{Produkt-Funktionen}
Bei dieser, funktionierenden, Version kann der Befehl funref das label nicht aufloesen.
Das Kommando ofunref funktioniert nicht, es soll aber so (zumindest in der Richtung)
funktionieren.
\subsection{Diese Funktionen}
\begin{funlist}
\fun{Ich will referenziert werden}\label{label}
Ich bin wichtig.
\end{funlist}

\subsection{Andere Funktionen}
Und noch richtig Text.
\begin{funlist}
\fun{Hier geht es um die Wurst}
Ich moechte Funktion \ref{label} referenzieren.
Und \begin{verbatim}
\ref{label}
\end{verbatim}
funktioniert nun.
\end{funlist}

\end{document}


Es funktioniert, ich weiß aber nicht, in wie weit dies deinen Vorstellungen entspricht?

Und noch etwas: Wozu hast du das \restylefloat{figure} in deinem Quelltext?

Liebe Grüße,
Axel

fmidon
15-05-2007, 17:56
Hi.

Ups...tatsächlich...hab ich den Quelltext von der Quelle nicht ganz korrekt übernommen (das \leftmargin). Leider löst das aber das Problem nicht.

\ref hat schon immer funktioniert, gibt aber lediglich die Funktions-Nummer aus.

\restylefloat{figure} ist nur ein Relikt aus alten tex-dateien von mir. Angeblich positioniert latex dann die Bilder eher dort wo sie definiert sind und nicht so "willkürlich" wie es sonst erscheint. Ist aber schon lange her, dass ich das eingefügt habe.

Schade. Hat leider nicht geholfen.

Trotzdem danke.

Markus

sommerfee
15-05-2007, 19:59
\ref hat schon immer funktioniert, gibt aber lediglich die Funktions-Nummer aus.

Nein, hast du dir mein Beispiel wirklich angesehen & ausprobiert?

Da gibt \ref{label} nämlich /F 001/ aus!



\restylefloat{figure} ist nur ein Relikt aus alten tex-dateien von mir. Angeblich positioniert latex dann die Bilder eher dort wo sie definiert sind und nicht so "willkürlich" wie es sonst erscheint.

Das kann ich sicher dementieren, wirf es am besten weg, es ist nur ein potentieller Konflikt mit vielen anderen Paketen (wie threeparttable, picins etc.)

Liebe Grüße,
Axel

fmidon
19-05-2007, 15:39
Hi.

Entschuldige, dass ich erst so spät antworte, kam bis jetzt aber nicht dazu.

Hmpf. Stimmt...habe deine Lösung nicht genau genug angesehen. Nun ja. Deine Lösung funktioniert fast.

Leider nur fast, da jede Funktion in einer funlist-Umgebung die gleiche Nummer hat.

Aber das Problem war leicht gelöst:

Das \refstepcounter{function} gehört zu der Definition von \fun. Dann wird bei jedem \item auch der counter erhöht.

Das hat vorher, denke ich, das \usecounter{function} in der list-umgebung gemacht. Dafür musste ich dann tricksen, damit die Funktionen fortlaufend (also über Umgebungs-Grenzen hinweg) numeriert werden. Aber die funktionierende Version ist jetzt (nach deinem Beispiel):



\documentclass[a4paper,pointlessnumbers]{scrartcl}
\usepackage[ngerman]{babel}
\usepackage{fmtcount}

\newcounter{function}
\renewcommand\thefunction{/F\padzeroes[3]\decimal{function}/}

\newcommand{\fun}[1]{\refstepcounter{function}\item \textbf{\textsf{#1}} }

\newenvironment{funlist}
{% This is the begin code
\begin{list}{\textbf{\textsf{\textit{\thefunction} }}}%
{\setlength{\rightmargin}{\leftmargin}}%
}
{% This is the end code
\end{list}
}

\begin{document}

\section{Produkt-Funktionen}
Bei dieser, funktionierenden, Version kann der Befehl funref das label nicht aufloesen.
Das Kommando ofunref funktioniert nicht, es soll aber so (zumindest in der Richtung)
funktionieren.
\subsection{Diese Funktionen}
\begin{funlist}
\fun{Ich will referenziert werden}\label{label}
Ich bin wichtig.
\end{funlist}

\subsection{Andere Funktionen}
Und noch richtig Text.
\begin{funlist}
\fun{Hier geht es um die Wurst}
Ich moechte Funktion \ref{label} referenzieren.
Und \begin{verbatim}
\ref{label}
\end{verbatim}
funktioniert nun.
\fun{Noch ne Funktion}
Läuft.
\end{funlist}

\end{document}


Vielen, vielen Dank nochmal. Das hat mir wirklich geholfen. Ich weiss zwar immer noch nicht, warum der Fehler aufgetreten ist, aber jetzt funktionierts und das ist doch das wichtigste :)

Viele Grüße

Markus

PS.: Wie kann ich den Thread als gelöst kennzeichnen? Reicht das, Gelöst in den ersten Post einzutragen. Oder kann man irgendwie den Titel ändern?

sommerfee
19-05-2007, 17:46
Moin Markus,



Leider nur fast, da jede Funktion in einer funlist-Umgebung die gleiche Nummer hat.

Stimmt, da habe ich geschlampt, aber das hast du ja gut erkannt und gut gelöst.



Ich weiss zwar immer noch nicht, warum der Fehler aufgetreten ist

Falls es dich interessiert: Ich hatte mich ja um das eigentliche Problem von dir herumgemogelt, indem ich \thefunction einfach so umdefiniert habe, daß \ref die gewünschte Ausgabe tätigt. Hätte man dies nicht getan und wollte man sich ein \funref wie bei deinem ersten Beispiel definieren, würde man auf folgendes Problem stoßen:

\ref{xxx} sieht zwar so aus, als würde es einfach eine Zahl (oder ähnliches) ausgeben, in Wirklichkeit steht aber einiges an Code dahinter, denn wenn das Label beim ersten LaTeX-Durchlauf noch nicht definiert ist, dann wird eine passende Warnung ausgegeben, ein Flag gesetzt, damit am Ende des Durchlaufes ein Hinweis auf noch nicht definierte Labels ausgegeben wird und noch einiger Kleinkram.

Wenn man also z.B. versucht, das Ergebnis von \ref{xxx} expandiert in ein anderes Makro zu packen, bekommt man eine Ahnung davon, daß das alles nicht so ganz einfach ist:

\edef\aaa{\ref{label}}

- oder -

\newcounter{aaa}
\setcounter{aaa}{\ref{label}}

tut einfach nicht so wie man naiverweise annehmen würde, sondern spukt Fehlermeldungen aus, die ohne Wissen der Internata unverständlich sind. Ebenso wenig kann man ein \ref{label} einfach als Zahl oder Counter weiterverwerten, so wie du es versucht hattest. \ref taugt wirklich (fast) nur dazu, es so zu nehmen, wie es ist.

Wollte man das ändern, müsste man das Label selber auswerten, also mehr oder weniger das selber tun, was \ref intern macht, etwa so:



\makeatletter
\newcounter{@funref} % Hilfszähler
\newcommand\funref[1]{%
\@ifundefined{r@#1}{% Label schon definiert?
\setcounter{@funref}{0}% Nein: erstmal "0" nehmen
% TODO: Warnung ausgeben
\protect\G@refundefinedtrue % Meldung am Ende erzwingen
}{%
\setcounter{@funref}{% Ja: Label nehmen
\expandafter\expandafter\expandafter\@firstoftwo
\csname r@#1\endcsname}%
}%
/F\padzeroes[3]\decimal{@funref}/}
\makeatother

(Nicht sehr elegant, auf die Schnelle zusammengehackt.)

Und wenn man jetzt denkt, daß das alles ist, baut man noch ein \usepackage{hyperref} in sein Dokument ein und merkt, daß da wohl noch einige Anpassungen auf einen zukommen...

(Vielleicht geht das aber auch viel einfacher und ich weiß es auch nicht besser!?)

Resümee: Am besten nutzt man den bestehenden Mechanismus aus \refstepcounter, \label und \ref, alles andere artet unnötig in Arbeit aus.

Liebe Grüße,
Axel