Vous pouvez être faire cela un peu plus difficile qu'il doit être. Oui, vous pouvez marquer une chaîne par des appels répétés à sscanf
ou avec des lectures répétées avec scanf
, mais la bibliothèque C fournit un outil pour marquer les mots d'une ligne de texte. Assez bien nommé strtok
.
Vous déclarez simplement une chaîne constante contenant les délimiteurs sur lesquels vous souhaitez interrompre les mots (par exemple delims = " \t";
pour casser les mots sur l'espace ou la tabulation, puis appelez strtok (str, delims)
pour retourner le premier jeton (mot), puis bouclez appelle strtok (NULL, delims)
pour analyser les mots restants (ou jusqu'à ce que vous atteigniez votre maximum de 3 mots).
(note le premier appel à strtok
utilise str
comme premier paramètre, alors que tous les appels utilisent NULL
)
Ceci est une manière beaucoup plus souple pour gérer un nombre inconnu de jetons dans une chaîne.
Au lieu d'utiliser a[]
, b[]
, c[]
, etc .. envisager d'utiliser un seul buf[]
à lire la ligne d'entrée dans, puis un tableau de chaînes pour maintenir les paramètres (qui vous permet d'utiliser un indice variable au cours de vos boucles sur strtok
pour affecter et copier la chaîne correcte à l'index associé). N'utilisez pas void
comme retour dans des circonstances comme celle-ci.
Pourquoi ne pas utiliser un retour significatif (comme le nombre de paramètres dans la ligne de texte). De cette façon, vous savez combien ont été lus (ou tokenisés) dans votre fonction de division. Donnez-lui un retour qui peut fournir des informations utiles, par ex.
size_t divide (char *buf, char (*params)[MAXC+1]);
qui retourne maintenant un type size_t
contenant le nombre de paramètres qui résultent de chaque appel à diviser.
Mettre complètement (et en utilisant fgets
pour lire toute la ligne d'entrée), vous pouvez faire quelque chose comme ce qui suit:
#include <stdio.h>
#include <string.h>
enum { MAXP = 3, MAXC = 50 }; /* max parameters & chars */
size_t divide (char *buf, char (*params)[MAXC+1]);
int main (void) {
char buf[MAXC * 4 + 1] = "";
char params[MAXP][MAXC + 1]; /* array to hold 3 parameters */
size_t i, len, nparams = 0;
/* use fgets for line-oriented user input */
printf ("\nenter commands: ");
if (!fgets (buf, sizeof buf, stdin)) {
fprintf (stderr, "error: insufficient input.\n");
return 1;
}
len = strlen (buf); /* get length */
if (buf[len - 1] == '\n') /* validate last char is '\n' */
buf[--len] = 0; /* overwrite with nul-terminating char */
else { /* short read -- handle error */
fprintf (stderr, "error: incomplete input read.\n");
return 1;
}
nparams = divide (buf, params);
for (i = 0; i < nparams; i++)
printf ("parameter[%zu] : %s\n", i, params[i]);
return 0;
}
/* divide using strtok */
size_t divide (char *buf, char (*params)[MAXC+1])
{
char *delims = " \t", /* delimiters for strtok */
*p = buf; /* pointer to buf */
size_t n = 0; /* var to return number of params */
p = strtok (buf, delims); /* tokenize fist paramter */
while (p) { /* now loop until all words exhausted or limit reached */
strncpy (params[n++], p, MAXC); /* copy token to params array */
if (n == MAXP) /* check if limit reached */
break;
p = strtok (NULL, delims); /* get next token */
}
return n; /* return the number of parameters found */
}
Exemple d'utilisation/sortie
$ /bin/splitparams
enter commands: create /dir/bar
parameter[0] : create
parameter[1] : /dir/bar
$ ./bin/splitparams
enter commands: write /foo/bar "test"
parameter[0] : write
parameter[1] : /foo/bar
parameter[2] : "test"
Ou fournir un tas de mots supplémentaires (pour valider le traitement de seulement 3)
$ ./bin/splitparams
enter commands: write /foo/bar "test" and some more stuff
parameter[0] : write
parameter[1] : /foo/bar
parameter[2] : "test"
1) 'scanf ("% s \ n ", a);' -> 'scanf ("% 50 [^ \ n] ", a);' – BLUEPIXY
'pour (i = 0; b [i]! = '\ 0'; je ++) '?? – BLUEPIXY
2) 'pour (j = 0; a [i]! = '\ 0'; i ++, j ++)' -> 'pour (j = 0; a [i]! = ESPACE; i ++, j ++)' – BLUEPIXY