Publi

Separar palabras de una cadena de caracteres en un array [ C ]

Si conocéis PHP, habréis visto la función explode(). Tiene una utilidad curiosa, separa cadenas de caracteres en elementos de un array. Es como hacer un corte a la cadena cada vez que encontremos un carácter delimitador. Por ejemplo:

“Bienvenido al blog Poesía Binaria”, si usamos como delimitador ” ” (un espacio), los elementos del array quedarían así:

[0] = “Bienvenido”
[1] = “al”
[2] =”blog”
[3] =”Poesía”
[4] = “Binaria”

Pero en C, no encontramos ninguna función que haga esto, tenemos que currar un poco; aunque tenemos una función de string.h que hace algo que se parece en cierto modo: strtok(), esta función, va a separar una cadena en fragmentos modificando la propia cadena, es decir, introduciremos caracteres terminadores al final de cada palabra.

La solución intuitiva, sería hacer una copia en una variable de la original, y utilizar la copia para strtok() aunque el acceso a cada palabra no es tan flexible, es decir, strtok() nos devolverá un puntero a donde empieza la palabra, pero en cuanto queramos conocer la siguiente palabra que encontremos no podremos volver fácilmente a la anterior.

Por ello, planteo la siguiente solución:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#define MAX_CADENA 100

/**
 ******************************************************************
 * @brief Extrae palabras de una cadena y las coloca en un array
 *
 * @param orig     Cadena inicial
 * @param delim    Las palabras vendrán delimitadas por uno de los
 *                 caracteres de esta cadena            
 * @param args     Array donde separaremos cada palabra
 * @param max_args Número de palabras como máximo a extraer (tamaño
 *                 del array)
 *
 * @return Número de palabras extraídas. (max_args+1) si en la
 *         cadena hay más de max_args palabras.
 *
 ******************************************************************/

int extrae_argumentos(char *orig, char *delim, char args[][MAX_CADENA], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = malloc(strlen(orig)+1);
  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      strcpy(args[num], tmp);   /* Copiamos la palabra actual en el array */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num;
}

Con esta función ejecutaremos strtok para extraer palabras de una cadena, como máximo (max_args+1) veces. El objetivo es rellenar el Array, debido a las limitaciones de los Arrays tenemos que decir el número máximo de elementos que vamos a extraer, la cadena podrá tener 1000 palabras, pero si nuestro array sólo tiene capacidad para 10 no podremos extraer todo; y la función debe estar preparada para eso; por tanto cuando no hayamos podido extraer todo, devolveremos max_args+1, si todo va bien, devolveremos el número de palabras extraídas.

Lo curioso es que cambiando sólo una línea podemos hacer que admita en lugar de un array de cadenas de caracteres (char args[][MAX_CADENA]) un array de punteros de cadenas de caracteres (char *args[]) por lo que en cierto modo, depende del uso que vayamos a darle es algo más flexible, en este caso repartiremos en el array anterior los valores de las posiciones de memoria donde empieza cada palabra en la cadena copiada de la original:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int extrae_argumentos_d(char *orig, char *delim, char *args[], int max_args)
{
  char *tmp;
  int num=0;
  /* Reservamos memoria para copiar la candena ... pero la memoria justa */
  char *str = malloc(strlen(orig)+1);
  strcpy(str, orig);

  /* Extraemos la primera palabra */
  tmp=strtok(str, delim);
  do
    {
      if (num==max_args)
    return max_args+1;  /* Si hemos extraído más cadenas que palabras devolvemos */
                /* El número de palabras máximo y salimos */

      args[num]=tmp;            /* Copiamos la dirección de memoria tmp en args[num] */
      num++;

      /* Extraemos la siguiente palabra */
      tmp=strtok(NULL, delim);
    } while (tmp!=NULL);

  return num;
}

Ahora acompaño un programa para probar esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_ARGS 90
#define MAX_CADENA 100

// Aquí copiamos extrae_argumentos o extrae_argumentos_d
int main()
{
  char cadena[]="Una ristra de palabras separadas por espacios";

  char args[MAX_ARGS][MAX_CADENA]; // Para extrae_argumentos
//  char *args2[MAX_ARGS];                  // Para extrae_argumentos_d

  int nargs = extrae_argumentos(cadena, " ", args, MAX_ARGS);
  int i;

  if (nargs>MAX_ARGS)
    {
      printf ("Se han devuelto más palabras del máximo\n");
      nargs=MAX_ARGS;
    }

  printf("CADENA: %s\n", cadena);
  for (i=0; i<nargs; i++)
    printf("Palabra %d: "%s"\n", i, args[i]);

  return 0;
}

También podría interesarte...

There are 4 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. Pingback: BlogESfera.com /

  3. Pingback: Poesía binaria » Separar palabras de una cadena en C [ método dinámico con puntero triple ] /

  4. Pingback: Enlazado dinámico en C++ (dynamic linking) IV: Permitir plug-ins en nuestra aplicación » Poesía Binaria /

Leave a Reply