web-dev-qa-db-fra.com

Utiliser strtok en c

J'ai besoin d'utiliser strtok pour lire un nom et un prénom et les séparer. Comment puis-je stocker les noms où je peux les utiliser indépendamment dans deux tableaux de caractères distincts?

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="test string.";
  char * test;
  test = strtok (str," ");
  while (test != NULL)
  {
    printf ("%s\n",test);
    test= strtok (NULL, " ");
  }
  return 0;
}
14
shinjuo

Voici ma prise à un simple assistant tokenize qui

  • stocke les résultats dans un tableau en croissance dynamique
  • terminaison nulle du tableau
  • conserve la chaîne d'entrée en sécurité (strtok modifie la chaîne d'entrée, qui est comportement indéfini sur un caractère littéral [], du moins je pense en C99)

Pour rendre le code rentrant, utilisez le strtok_r non standard

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char** tokenize(const char* input)
{
    char* str = strdup(input);
    int count = 0;
    int capacity = 10;
    char** result = malloc(capacity*sizeof(*result));

    char* tok=strtok(str," "); 

    while(1)
    {
        if (count >= capacity)
            result = realloc(result, (capacity*=2)*sizeof(*result));

        result[count++] = tok? strdup(tok) : tok;

        if (!tok) break;

        tok=strtok(NULL," ");
    } 

    free(str);
    return result;
}

int main ()
{
    char** tokens = tokenize("test string.");

    char** it;
    for(it=tokens; it && *it; ++it)
    {
        printf("%s\n", *it);
        free(*it);
    }

    free(tokens);
    return 0;
}

Voici unestrtok- free réimplémentation de cela (utilise strpbrk à la place):

char** tokenize(const char* str)
{
    int count = 0;
    int capacity = 10;
    char** result = malloc(capacity*sizeof(*result));

    const char* e=str;

    if (e) do 
    {
        const char* s=e;
        e=strpbrk(s," ");

        if (count >= capacity)
            result = realloc(result, (capacity*=2)*sizeof(*result));

        result[count++] = e? strndup(s, e-s) : strdup(s);
    } while (e && *(++e));

    if (count >= capacity)
        result = realloc(result, (capacity+=1)*sizeof(*result));
    result[count++] = 0;

    return result;
}
19
sehe

Avez-vous besoin de les stocker séparément? Deux pointeurs dans un tableau de caractères modifié produiront deux chaînes distinctes parfaitement utilisables.

C'est ce que nous transformons ceci:

char str[] ="test string.";

Dans ceci:

char str[] ="test\0string.";
             ^     ^
             |     |
char *s1 -----     |
char *s2 -----------

.

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="test string.";
  char *firstname = strtok(str, " ");
  char *lastname = strtok(NULL, " ");
  if (!lastname)
    lastname = "";
  printf("%s, %s\n", lastname, firstname);
  return 0;
}
7
u0b34a0f6ae

Qu'en est-il d'utiliser strcpy:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_NAMES 2

int main ()
{
  char str[] ="test string.";
  char *names[MAX_NAMES] = { 0 };
  char *test;
  int i = 0;

  test = strtok (str," ");
  while (test != NULL && i < MAX_NAMES)
  {
    names[i] = malloc(strlen(test)+1);
    strcpy(names[i++], test);
    test = strtok (NULL, " ");
  }

  for(i=0; i<MAX_NAMES; ++i)
  {
    if(names[i])
    {
      puts(names[i]);
      free(names[i]);
      names[i] = 0;
    }
  }
  return 0;
}

Il contient beaucoup de fouillis pour maintenir un programme complet et nettoyer ses ressources, mais l’essentiel est d’utiliser strcpy pour copier chaque jeton dans sa propre chaîne.

4
Christian Rau
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


char** split(const char *str, const char *delimiter, size_t *len){
    char *text, *p, *first, **array;
    int c;
    char** ret;

    *len = 0;
    text=strdup(str);
    if(text==NULL) return NULL;
    for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
        if(c==0) first=p; //first token top

    ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
    if(ret==NULL){
        free(text);
        return NULL;
    }
    strcpy(text, str+(first-text));//skip until top token
    array=ret;

    for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
        *array++=p;
    }
    *array=NULL;
    *len=c;
    return ret;
}

void free4split(char** sa){
    char **array=sa;

    if(sa!=NULL){
        free(array[0]);//for text
        free(sa);      //for array
    }
}

int main(void){
    char str[] ="test string.";
    char **words;
    size_t len=0;
    int i;

    words = split(str, " \t\r\n,.", &len);

/*
    for(char **wk = words; *wk ;wk++){
        printf("%s\n", *wk);
    }
*/
    for(i = 0;i<len;++i){
        printf("%s\n", words[i]);
    }
    free4split(words);
    return 0;
}
/* result:
test
string
*/
2
BLUEPIXY

Copiez les résultats de strtok dans un nouveau tampon en utilisant une fonction telle que

/*
 * Returns a copy of s in freshly allocated memory.
 * Exits the process if memory allocation fails.
 */
char *xstrdup(char const *s)
{
    char *p = malloc(strlen(s) + 1);
    if (p == NULL) {
        perror("memory allocation failed");
        exit(1);
    }
    strcpy(p, s);
    return p;
}

N'oubliez pas de free les valeurs de retour lorsque vous avez terminé avec elles.

1
Fred Foo

OMI, vous n’avez pas besoin (et probablement pas voulu) d’utiliser strtok du tout (comme dans, "pour ceci, ou beaucoup d’autre chose"). Je pense que je voudrais utiliser du code quelque chose comme ça:

#include <string.h>
#include <stdlib.h>

static char *make_str(char const *begin, char const *end) { 
    size_t len = end-begin;
    char *ret = malloc(len+1);
    if (ret != NULL) {
        memcpy(ret, begin, len);
        ret[len]='\0';
    }
    return ret;
}

size_t tokenize(char *tokens[], size_t max, char const *input, char const *delims) { 
    int i;
    char const *start=input, *end=start;

    for (i=0; *start && i<max; i++) {
        for ( ;NULL!=strchr(delims, *start); ++start)
            ;
        for (end=start; *end && NULL==strchr(delims, *end); ++end)
            ;
        tokens[i] = make_str(start, end);
        start = end+1;
    }
    return i;
}

#ifdef TEST

#define MAX_TOKENS 10

int main() { 
    char *tokens[MAX_TOKENS];
    int i;
    size_t num = tokenize(tokens, MAX_TOKENS, "This is a longer input string ", " ");
    for (i=0; i<num; i++) {
        printf("|%s|\n", tokens[i]);
        free(tokens[i]);
    }
    return 0;
}

#endif
1
Jerry Coffin

U peut faire quelque chose comme ça aussi.

    int main ()
    {
    char str[] ="test string.";

    char * temp1;
    char * temp2; 

    temp1 = strtok (str," ");

    temp2 = strchr(str, ' '); 
    if (temp2 != NULL)
        temp2++;

    printf ("Splitted string :%s, %s\n" , temp1 , temp2);
    return 
    }
0
Thulasi