more on strtok

This commit is contained in:
tTh 2023-09-03 22:24:56 +02:00
parent 42ead5b695
commit c6fe2224bf
2 changed files with 66 additions and 7 deletions

View File

@ -479,9 +479,9 @@ avec les variables locales. Il est temps de passer à une gestion
explicite de celle-ci~: explicite de celle-ci~:
les fonctions \texttt{malloc} et \texttt{free} sont là pour ça. les fonctions \texttt{malloc} et \texttt{free} sont là pour ça.
La première demande au mc/p de nous préter une certaine quantité La première fonction demande au mc/p de nous préter une certaine quantité
de mémoire, que nous pourront utiliser à notre guise. de mémoire, que nous pourront utiliser à notre guise.
Et la seconde restitue la zone mémoire au système sous-jacent. Et la seconde restitue cette zone mémoire au système sous-jacent.
Un rapide synopsis minimal d'utilisation~: Un rapide synopsis minimal d'utilisation~:
@ -536,10 +536,72 @@ extern int optind, opterr, optopt;
La page de man de getopt(3) contient des explications détaillées La page de man de getopt(3) contient des explications détaillées
et un exemple simple d'utilisation. et un exemple simple d'utilisation.
% =========================================================
% Sun Sep 3 05:48:37 UTC 2023
%
%
\section{Analyser une ligne de texte} \index{parser}
Nous désirons implémenter une interface en ligne de commande
(aka CLI\index{CLI}) pour un enchainement simple d'intructions
assez semblables. On peut aussi voir ça comme la création
d'un \textsl{domain specific language} (aka DSL\index{DSL}).
Pour être cohérent avec le shell, nous allons utiliser la
même méthode de séparation des mots sur la ligne à
décomposer~:
utiliser une liste pré-définie de séparateur de champs,
comme le \$IFS du shell.
\subsection{la fonction \texttt{strtok}} \index{strtok}
Cette fonction nous permet de « découper » notre ligne de commande
en \textsl{tokens} par un ensemble de
caractères de séparation appelé \texttt{delim} dans cet extrait
du man\index{man}.
\begin{verbatim}
#include <string.h>
char *strtok(char *str, const char *delim);
The strtok() function breaks a string into a sequence of zero or more
nonempty tokens. On the first call to strtok(), the string to be
parsed should be specified in str. In each subsequent call that should
parse the same string, str must be NULL.
\end{verbatim}
Concrètement, nous allons utiliser deux séparateurs très classiques,
l'espace et la tabulation \texttt{ delim = "\symbol{92}t ";}.
on peut ensuite aller regarder dans la mémoire ce qui s'y passe~:
\begin{verbatim}
--- chaine d'origine
66 6f 6f 20 20 20 62 61 72 09 71 75 75 78 20 77 69 7a 00
f o o b a r q u u x w i z
--- 1er strtok
66 6f 6f 00 20 20 62 61 72 09 71 75 75 78 20 77 69 7a 00
f o o b a r q u u x w i z
got [foo]
\end{verbatim}
Déja on peut constater que la chaine de départ est modifiée, ce qui
risque de causer des soucis, mais on en parlera plus tard.
\subsection{Le programme complet}
\lstinputlisting[language=c]{code/C/demo-strtok.c}
% ========================================================= % =========================================================
\section{Erreurs classiques} \section{Erreurs classiques}
Le C est un langage parsemé de fosses, de chausse-trapes et de
pièges fourbes et sournois. Sans parler des UBs, hein\dots
\begin{itemize} \begin{itemize}
\item{Variables non initialisées.} \item{Variables non initialisées.}

View File

@ -5,8 +5,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
/*---------------------------------------------------------------------*/ /*-------------------------------------------------------*/
void dump_line(char *titre, char *ligne, int combien) void dump_line(char *titre, char *ligne, int combien)
{ {
int foo; int foo;
@ -23,8 +22,7 @@ for (foo=0; foo<combien; foo++) {
} }
puts(""); puts("");
} }
/*---------------------------------------------------------------------*/ /*-------------------------------------------------------*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char input[] = "foo bar\tquux wiz"; char input[] = "foo bar\tquux wiz";
@ -54,4 +52,3 @@ printf(" index = %d\n", foo);
printf(" and we have [%s]\n", input+foo); printf(" and we have [%s]\n", input+foo);
return 0; return 0;
} }
/*---------------------------------------------------------------------*/