Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have the following code, which was provided by the xstring author Christian Tellechea, thank you very much. The idea is to count the number of character inside a structure that do belong to a predefined list.

\documentclass{article}
\usepackage{xstring}
\usepackage{blindtext}
\makeatletter
\def\countoccurs#1#2{%
    \saveexpandmode\expandarg
    %\exploregroups
    \expandafter\def\expandafter\tmp@list\expandafter{\list,}%
    \let\nboccur\z@
    \loop
        \unless\ifx\empty\tmp@list
            \StrCut\tmp@list,\tmp@cs\tmp@list
            %\StrCount{\noexpand#2}\tmp@cs[\tmp@cs]%
            \StrCount{#2}\tmp@cs[\tmp@cs]%
            \edef\nboccur{\number\numexpr\nboccur+\tmp@cs}%
    \repeat
    \restoreexpandmode
}
%\def\list{12,a,bc,9} % list can also be defined as this
\def\list{%
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,Q,r,s,t,u,v,w,x,y,z,%
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,S,X,Y,Z,%
1,2,3,4,5,6,7,8,9,0,%
}
\def\countenv#1{#1\countoccurs\list{#1}}
\makeatother

\begin{document}
\countenv{\begin{tabular}{ll} a & b \\ a & c \end{tabular}}\par
I counted: \nboccur.

\noindent\hrulefill

\countenv{\textbf{D}2345}\par
I counted: \nboccur.

\noindent\hrulefill

\countenv{\blindtext}\par
I counted: \nboccur.

\noindent\hrulefill

%\countoccurs\list{12987d bc abcabc999}
\countenv{12987d bc abcabc999}\par
I counted: \nboccur.

\noindent\hrulefill
\end{document}

As you can see in the output, the first and last counts are correct, but the others don't. I tried to use the \exploregroups and \noexpand#2 but luck with all presented examples. For example, the \noexpand#2 corrects the second output, but badly influences the first and third. Is there a away that works for all?

share|improve this question
    
In my computer it compiles fine. –  cacamailg Apr 10 '13 at 23:10
    
sorry had an older xstring.tex masking the tL2012 one, fixed now. –  David Carlisle Apr 10 '13 at 23:20
    
Could you give an indication of why you want to do this (the macros are massively inefficient at this) to get a count for the whole document you can just use (say) latex followed by dvi2tty then wc (standard unix word count, which also counts characters) –  David Carlisle Apr 10 '13 at 23:22
    
I wanted this just to count the number of characters in particular parts of the document. I was not aware that this could be highly inefficient with TeX in general. In fact, with after @egreg's answer I realized that for large documents it would take a lot of time. –  cacamailg Apr 11 '13 at 0:06

1 Answer 1

\blindtext does not expand to some text, but executes many (unexpandable) commands before getting to a text.

You can try with kantlipsum, instead, which has the possibility of defining a macro expanding to one of its paragraphs.

\documentclass{article}
\usepackage{xstring}

\usepackage{kantlipsum}
\kantdef\mytext{1}

\makeatletter
\def\countoccurs#1#2{%
    \saveexpandmode\expandarg
    %\exploregroups
    \expandafter\def\expandafter\tmp@list\expandafter{\list,}%
    \let\nboccur\z@
    \loop
        \unless\ifx\empty\tmp@list
            \StrCut\tmp@list,\tmp@cs\tmp@list
            %\StrCount{\noexpand#2}\tmp@cs[\tmp@cs]%
            \StrCount{#2}\tmp@cs[\tmp@cs]%
            \edef\nboccur{\number\numexpr\nboccur+\tmp@cs}%
    \repeat
    \restoreexpandmode
}
%\def\list{12,a,bc,9} % list can also be defined as this
\def\list{%
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,Q,r,s,t,u,v,w,x,y,z,%
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,S,X,Y,Z,%
1,2,3,4,5,6,7,8,9,0,%
}
\def\countenv#1{#1\countoccurs\list{#1}}
\makeatother

\begin{document}
\countenv{\begin{tabular}{ll} a & b \\ a & c \end{tabular}}\par
I counted: \nboccur.

\noindent\hrulefill

\countenv{\textbf{D}2345}\par
I counted: \nboccur.

\noindent\hrulefill

\countenv{\mytext}\par
I counted: \nboccur.

\noindent\hrulefill

%\countoccurs\list{12987d bc abcabc999}
\countenv{12987d bc abcabc999}\par
I counted: \nboccur.

\noindent\hrulefill
\end{document}

After a long time (15 seconds on my machine, which is a very long processing time), you get this.

enter image description here

share|improve this answer
    
That does fix the third count, but not the second count. Any idea how to deal with macros like \textbf{} so that chars inside brackets are counted, but not the command itself? –  cacamailg Apr 10 '13 at 23:08
    
@cacamailg If you go with \exploregroups you'll get wrong results in the first, because also tabular will get counted. –  egreg Apr 10 '13 at 23:13
    
Yes. So no general solution is possible with TeX? –  cacamailg Apr 10 '13 at 23:18
5  
@cacamailg I'd answer with xii.tex –  egreg Apr 10 '13 at 23:22
    
very nice comment :) –  cacamailg Apr 11 '13 at 0:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.