- Questo topic ha 6 risposte, 2 partecipanti ed è stato aggiornato l'ultima volta 15 anni, 3 mesi fa da
robitex.
-
CreatoreTopic
-
1 Giugno 2011 alle 20:40 #59571::
Sto mettendo a punto un comando per disegnare il barcode con codifica code39 di una stringa. Il comando deve selezionare della stringa un carattere alla volta ed in questo caso ci risco con:
`\documentclass{minimal}
\makeatletter\def\makeup#1{%
\parsechar#1\@nil
}\def\parsechar#1#2\@nil{%
#1\\
\def\temp{#2}
\ifx\temp\empty
\else
\parsechar#2\@nil
\fi
}\makeatother
\begin{document}
\noindent\makeup{12q\$wert\%y+-}\end{document}`
Tuttavia se provo a rendere maiuscoli i caratteri (il code39 accetta solo caratteri maiuscoli), il codice non funziona più:
`% non funziona
\documentclass{minimal}\makeatletter
\def\makeup#1{%
\expandafter\parsechar\uppercase{#1}\@nil
}\def\parsechar#1#2\@nil{%
#1\\
\def\temp{#2}
\ifx\temp\empty
\else
\parsechar#2\@nil
\fi
}
\makeatother\begin{document}
\noindent\makeup{12q\$wert\%y+-}
\end{document}`Eppure l’effetto del primo \expandafter dovrebbe essere quello di espandere \uppercase e restituire al comando delimitato i token dei caratteri semplici ma resi maiuscoli.
L’errore è quello di un parentisi graffa aperta mancante.Ho provato anche a definire una macro \temp come \def\temp{\uppercase{#1}} ed espanderla dopo ma viene riportato lo stesso errore.
Grazie per l’aiuto.
R.
-
CreatoreTopic
-
AutoreRisposte
-
-
1 Giugno 2011 alle 21:38 #59572::
Sto mettendo a punto un comando per disegnare il barcode con codifica code39 di una stringa. Il comando deve selezionare della stringa un carattere alla volta ed in questo caso ci risco con:
`\documentclass{minimal}
\makeatletter\def\makeup#1{%
\parsechar#1\@nil
}\def\parsechar#1#2\@nil{%
#1\\
\def\temp{#2}
\ifx\temp\empty
\else
\parsechar#2\@nil
\fi
}\makeatother
\begin{document}
\noindent\makeup{12q\$wert\%y+-}\end{document}`
Tuttavia se provo a rendere maiuscoli i caratteri (il code39 accetta solo caratteri maiuscoli), il codice non funziona più:
`% non funziona
\documentclass{minimal}\makeatletter
\def\makeup#1{%
\expandafter\parsechar\uppercase{#1}\@nil
}\def\parsechar#1#2\@nil{%
#1\\
\def\temp{#2}
\ifx\temp\empty
\else
\parsechar#2\@nil
\fi
}
\makeatother\begin{document}
\noindent\makeup{12q\$wert\%y+-}
\end{document}`Eppure l’effetto del primo \expandafter dovrebbe essere quello di espandere \uppercase e restituire al comando delimitato i token dei caratteri semplici ma resi maiuscoli.
L’errore è quello di un parentisi graffa aperta mancante.Ho provato anche a definire una macro \temp come \def\temp{\uppercase{#1}} ed espanderla dopo ma viene riportato lo stesso errore.
Grazie per l’aiuto.
R.\uppercase non è espandibile. Quando TeX trova \uppercase{
}, interrompe ciò che sta facendo, converte i nell’equivalente maiuscolo (solo i caratteri espliciti) senza espandere nulla e rimette la lista di token ottenuta al posto di \uppercase{ }. La soluzione è eseguire prima \uppercase:
`\def\makeup#1{\uppercase{\parsechar#1\@nil}}`
C’è un modo migliore di definire \parsechar:
`\def\parsechar#1{%
\ifx#1\@nil\else
#1\\%
\expandafter\parsechar
\fi}`
che effettivamente consuma un token alla volta, mentre la tua rilegge ogni volta tutto quanto rimane dopo ogni passaggio.Nel caso di \makeup{12q\$wert\%y+-}, dopo l’esecuzione di \uppercase ci troviamo
`\parsechar 12Q\$WERT\%Y+-\@nil`
e #1 è 1, che non è \@nil. Perciò ci si trova con
`1\\\expandafter\parsechar\fi 2Q\$WERT\%Y+-\@nil`
I token 1 e \\ vengono spediti avanti e viene espanso \expandafter che a sua volta espande \fi, la cui espansione è vuota! Dunque ci troviamo
`\parsechar 2Q\$WERT\%Y+-\@nil`
esattamente come voluto.Ovviamente se inserisci nell’argomento di \makeup comandi con argomento o comandi non definiti ti trovi nei pasticci, ma non credo sia un problema. Esercizio: perché, con la mia definizione, \makeup{abc\ddt xyz} non dà errore a \ddt ma a \@nil, mentre con la tua lo dà a \ddt?
Ciao
Enrico
-
3 Giugno 2011 alle 7:25 #59573::
Esercizio: perché, con la mia definizione, \makeup{abc\ddt xyz} non dà errore a \ddt ma a \@nil, mentre con la tua lo dà a \ddt?
Ciao
EnricoPerché nella mia definizione \@nil è un token di delimitazione che non verrà mai espanso e quindi l’errore verrà provocato dall’espansione di \ddt.
Nel tuo codice invece, tutto dipende dal condizionale \ifx:
se \ifx si trova un carattere ed un token command sequence da confrontare darà come risultato falso senza espandere \@nil.
Se invece deve operare su due cs come quando incontra \ifx\ddt\@nil allora deve indagarne il significato cominciando ad espandere il secondo che quindi solleverà l’errore.
Giusto?
R.
-
3 Giugno 2011 alle 9:36 #59574::
Esercizio: perché, con la mia definizione, \makeup{abc\ddt xyz} non dà errore a \ddt ma a \@nil, mentre con la tua lo dà a \ddt?
Ciao
EnricoPerché nella mia definizione \@nil è un token di delimitazione che non verrà mai espanso e quindi l’errore verrà provocato dall’espansione di \ddt.
Nel tuo codice invece, tutto dipende dal condizionale \ifx:
se \ifx si trova un carattere ed un token command sequence da confrontare darà come risultato falso senza espandere \@nil.
Se invece deve operare su due cs come quando incontra \ifx\ddt\@nil allora deve indagarne il significato cominciando ad espandere il secondo che quindi solleverà l’errore.
Giusto?Sbagliato. 🙂 La risposta riguardo la tua definizione è corretta. Con l’altro metodo a un certo punto TeX incontra \ifx\ddt\@nil e confronta i due token senza espanderli; ma li considera uguali perché entrambi sono indefiniti e quindi la ricorsione termina. Quando poi TeX trova il \@nil che è rimasto emette il messaggio di errore di “Undefined control sequence”.
Se hai timore che nell’argomento di \makeup possano intrufolarsi token non definiti, è meglio usare come sentinella un token definito e inconsueto, per esempio \uchyph.
Ciao
Enrico
-
3 Giugno 2011 alle 14:38 #59575::
[quote]Esercizio: perché, con la mia definizione, \makeup{abc\ddt xyz} non dà errore a \ddt ma a \@nil, mentre con la tua lo dà a \ddt?
Ciao
EnricoPerché nella mia definizione \@nil è un token di delimitazione che non verrà mai espanso e quindi l’errore verrà provocato dall’espansione di \ddt.
Nel tuo codice invece, tutto dipende dal condizionale \ifx:
se \ifx si trova un carattere ed un token command sequence da confrontare darà come risultato falso senza espandere \@nil.
Se invece deve operare su due cs come quando incontra \ifx\ddt\@nil allora deve indagarne il significato cominciando ad espandere il secondo che quindi solleverà l’errore.
Giusto?Sbagliato. 🙂 La risposta riguardo la tua definizione è corretta. Con l’altro metodo a un certo punto TeX incontra \ifx\ddt\@nil e confronta i due token senza espanderli; ma li considera uguali perché entrambi sono indefiniti e quindi la ricorsione termina. Quando poi TeX trova il \@nil che è rimasto emette il messaggio di errore di “Undefined control sequence”.
Se hai timore che nell’argomento di \makeup possano intrufolarsi token non definiti, è meglio usare come sentinella un token definito e inconsueto, per esempio \uchyph.
Ciao
Enrico[/quote]Spiegazione completa a questo punto… grazie.
Quello che manca è raccontare come è andata a finire la questione.
Intanto ho adottato la soluzione di parsing a singolo carattere anche solo per aumentare l’efficienza (motivo del perché vorrei abbandonare la soluzione attuale basata su pstricks).Ecco come funziona il codice:
ho creato 43 macro diverse ognuna per i 43 simboli che possono essere rappresentati da code39. Queste macro sono state nominate con \barchar@.
Per esempio il carattere A è reso dalla macro \barchar@A, quindi quando la macro di parsing passa un singolo carattere costruisco la command sequence relativa per le cifre da 0 a 9 e per le 26 lettere.
Se tale token non è vuoto (come nella maggioranza dei casi), allora produco il disegno corrispondente delle barre, altrimenti verifico che non sia uno dei simboli speciali, e se non sono in uno di questi casi emetto un messaggio d’errore. Ecco il codice:
`
% user interface macro
\newcommand{\barcode}[1]{%
\ifx#1\empty
% package warning
\else
\barcode@Start
\expandafter\uppercase\expandafter{\expandafter\barcode@parsechar#1\@nil}
\barcode@Stop
\fi
}
%
\def\barcode@parsechar#1{%
\ifx#1\@nil\else
\def\tempsymb{*}
\ifx#1\tempsymb
% package error
\fi
% command sequence of the char
\expandafter\let\expandafter\tempchar\csname barchar@#1\endcsname
\ifx\tempchar\relax
\ifx#1\space
\barchar@space
\barstep@interchar
\else
\def\tempsymb{-}
\ifx#1\tempsymb
\barchar@bar
\barstep@interchar
\else
\def\tempsymb{.}
\ifx#1\tempsymb
\barchar@dot
\barstep@interchar
\else
\def\tempsymb{/}
\ifx#1\tempsymb
\barchar@slash
\barstep@interchar
\else
\def\tempsymb{+}
\ifx#1\tempsymb
\barchar@plus
\barstep@interchar
\else
\def\tempsymb{\%}
\ifx#\tempsymb
\barchar@percent
\barstep@interchar
\else
\def\tempsymb{\$}
\ifx#1\tempsymb
\barchar@dollar
\barstep@interchar
\else
% package error
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\else
\tempchar
\barstep@interchar
\fi
\expandafter\barcode@parsechar
\fi
}`La serie annidata di test condizionali è un po’ poco leggibile ma riguarda solo i simboli mentre con l’idea di \tempchar mi evito un problema maggiore mantenendo l’efficienza di esecuzione.
Se passo il codice da renderizzare a \barcode con una macro semplice funziona.
Grazie di nuovo.
R.
-
3 Giugno 2011 alle 15:15 #59576::
Ecco come funziona il codice:
ho creato 43 macro diverse ognuna per i 43 simboli che possono essere rappresentati da code39. Queste macro sono state nominate con \barchar@.
Per esempio il carattere A è reso dalla macro \barchar@A, quindi quando la macro di parsing passa un singolo carattere costruisco la command sequence relativa per le cifre da 0 a 9 e per le 26 lettere.
Se tale token non è vuoto (come nella maggioranza dei casi), allora produco il disegno corrispondente delle barre, altrimenti verifico che non sia uno dei simboli speciali, e se non sono in uno di questi casi emetto un messaggio d’errore. Ecco il codice:
`
% user interface macro
\newcommand{\barcode}[1]{%
\ifx#1\empty
% package warning
\else
\barcode@Start
\expandafter\uppercase\expandafter{\expandafter\barcode@parsechar#1\@nil}
\barcode@Stop
\fi
}
%
\def\barcode@parsechar#1{%
\ifx#1\@nil\else
\def\tempsymb{*}
\ifx#1\tempsymb
% package error
\fi
% command sequence of the char
\expandafter\let\expandafter\tempchar\csname barchar@#1\endcsname
\ifx\tempchar\relax
\ifx#1\space
\barchar@space
\barstep@interchar
\else
\def\tempsymb{-}
\ifx#1\tempsymb
\barchar@bar
\barstep@interchar
\else
\def\tempsymb{.}
\ifx#1\tempsymb
\barchar@dot
\barstep@interchar
\else
\def\tempsymb{/}
\ifx#1\tempsymb
\barchar@slash
\barstep@interchar
\else
\def\tempsymb{+}
\ifx#1\tempsymb
\barchar@plus
\barstep@interchar
\else
\def\tempsymb{\%}
\ifx#\tempsymb
\barchar@percent
\barstep@interchar
\else
\def\tempsymb{\$}
\ifx#1\tempsymb
\barchar@dollar
\barstep@interchar
\else
% package error
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\else
\tempchar
\barstep@interchar
\fi
\expandafter\barcode@parsechar
\fi
}`La serie annidata di test condizionali è un po’ poco leggibile ma riguarda solo i simboli mentre con l’idea di \tempchar mi evito un problema maggiore mantenendo l’efficienza di esecuzione.
Se passo il codice da renderizzare a \barcode con una macro semplice funziona.
Grazie di nuovo.
R.Non vedo perché tutti quei test, visto che ogni volta che il test ha successo inserisci la macro corrispondente e \barstep@interchar: non basterebbe mettere \barstep@interchar nella definizione di \barcode@dot, per esempio? Ma a quanto capisco quel carattere di separazione ci va sempre, quindi perché fare tanta fatica?
Ah, puoi benissimo dire
`\@namedef{barchar@.}{…}`
ed evitare di guardare se il successivo carattere è il punto. E anche
`\@namedef{barchar@\detokenize{\$}}{…}`
e non hai nemmeno bisogno di \tempsymb, purché tu usi
`\expandafter\let\expandafter\tempchar\csname barchar@\detokenize{#1}\endcsname`
e a questo punto non ti serve nemmeno \tempchar.Vediamo un po’ di snellire quel codice:
`\newcommand{\barcode@def}[1]{\@namedef{barcode@\detokenize{#1}} % zucchero sintattico
\barcode@def{A}{…}
…
\barcode@def{Z}{…}
\barcode@def{0}{…}
\barcode@def{9}{…}
\barcode@def{ }{…} % space
\barcode@def{\ }{…} % control space (serve per spazi multipli)
\barcode@def{-}{…} % period
\barcode@def{.}{…} % period
\barcode@def{/}{…} % slash
\barcode@def{+}{…} % plus
\barcode@def{\%}{…} % percent
\barcode@def{$}{…} % dollar
\barcode@def{\$}{…} % control dollar (non servirebbe)\def\barcode@parsechar#1{%
\ifx#1\@nil\else
\@ifundefined{barcode@\detokenize{#1}}{\ERROR}{%
\@nameuse{barcode@\detokenize{#1}}%
\barstep@interchar}%
\expandafter\barcode@parsechar
\fi}`
Prima di espandere la macro corrispondente al carattere vediamo se è definita; se non lo è emettiamo un messaggio di errore.Mi pare un pochino più compatto, non trovi? 🙂
Si potrebbe anche evitare di dare \% nelle stringhe, di sicuro \$ non serve e va benissimo anche $. Ho messo anche “\ ” perché altrimenti non puoi scrivere due spazi di seguito (a meno di non cambiare il codice di categoria dello spazio durante la lettura dell’argomento). Se definisci anche \barcode@a e così via fino a \barcode@z non hai nemmeno bisogno di \uppercase:
`\let\barcode@a\barcode@A
…
\let\barcode@z\barcode@Z`
Ciao
Enrico
-
3 Giugno 2011 alle 15:42 #59577::
Benissimo.
In realtà avevo pensato di evitare \uppercase con i \let e di provare di inserire i simboli nel nome della macro come per le lettere ed i numeri.In fondo il codice non può che essere solamente un inizio di pacchetto.
I codici a barre sono infatti disegnati con pgf che rispetto a pstricks offre un paio di indiscutibili vantaggi:
1 – gestione molto più efficiente delle immagini esterne;
2 – passaggio direttamente al formato pdf.Adesso quindi il codice di interfaccia è completo. Quello da proseguire è l’integrazione con il basic layer di PGF e la creazione di oggetti grafici barcode come ad esempio gli oggetti nodo.
Occorre quindi non solo imparare a costruire gli altri tipi di barcode, come i bidimensionali datamatrix e qrcode, ma sopratutto imparare a programmare PGF.
Potrebbe venirne fuori l’equivalente del pacchetto pst-barcode per TikZ.
Grazie.
Bye
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.