Matriz de cadenas en C

Matriz de cadenas en C

¿Qué es una matriz de cadenas? #

Una cadena es una matriz de caracteres en 1D, por lo que una matriz de cadenas es una matriz de caracteres en 2D. Al igual que podemos crear una matriz 2-D de int , float etc; también podemos crear una matriz 2-D de caracteres o una matriz de cadenas. Así es como podemos declarar una matriz de caracteres en 2-D.

1
2
3
4
5
char ch_arr[3][10] = {
                         {'s', 'p', 'i', 'k', 'e', '\0'},
                         {'t', 'o', 'm','\0'},
                         {'j', 'e', 'r', 'r', 'y','\0'}
                     };

Es importante terminar cada matriz 1-D con el carácter nulo, de lo contrario, será solo una matriz de caracteres. No podemos usarlos como cadenas.

Declarar una matriz de cadenas de esta manera es bastante tedioso, por eso C proporciona una sintaxis alternativa para lograr lo mismo. Esta inicialización anterior es equivalente a:

1
2
3
4
5
char ch_arr[3][10] = {
                         "spike",
                         "tom",
                         "jerry"
                     };

El primer subíndice de la matriz, es decir, 3 indica el número de cadenas en la matriz y el segundo subíndice indica la longitud máxima de la cadena. Recuerda que en C, cada carácter ocupa 1 byte de datos, por lo que cuando el compilador ve la declaración anterior, asigna 30 bytes (3*10 ) de la memoria.

Ya sabemos que el nombre de una matriz es un puntero al elemento 0 de la matriz. ¿Puedes adivinar el tipo de ch_arr ?

El ch_arr es un puntero a una matriz de 10 caracteres o int(*)[10] .

Por lo tanto, si ch_arr apunta a la dirección 1000 entonces ch_arr + 1 apuntará a la dirección 1010 .

De esto, podemos concluir que:

ch_arr + 0 apunta a la 0.ª cadena o 0.ª matriz 1-D.
ch_arr + 1 apunta a la primera cadena o la primera matriz 1-D.
ch_arr + 2 apunta a la segunda cadena o la segunda matriz 1-D.

En general, ch_arr + i apunta a la i-ésima cadena o la i-ésima matriz 1-D.

Sabemos que cuando eliminamos la referencia de un puntero a una matriz, obtenemos la dirección base de la matriz. Entonces, al desreferenciar ch_arr + i obtenemos la dirección base de la matriz 0th 1-D.

De esto podemos concluir que:

*(ch_arr + 0) + 0 apunta al carácter 0 de la matriz 1-D 0 (es decir, s )
*(ch_arr + 0) + 1 apunta al primer carácter de la matriz 0th 1-D (es decir, p )
*(ch_arr + 1) + 2 apunta al segundo carácter de la primera matriz 1-D (es decir, m )

En general, podemos decir que:*(ch_arr + i) + j apunta al j-ésimo carácter de la i-ésima matriz 1-D.

Tenga en cuenta que el tipo base de *(ch_arr + i) + j es un puntero a char o (char*) , mientras que el tipo base de ch_arr + i es una matriz de 10 caracteres o int(*)[10] .

Para obtener el elemento en la j-ésima posición de la i-ésima matriz 1-D, simplemente elimine la referencia a toda la expresión*(ch_arr + i) + j .

*(*(ch_arr + i) + j)

Hemos aprendido en el capítulo Punteros y arreglos 2-D que en un arreglo 2-D la notación de puntero es equivalente a la notación de subíndice. Entonces, la expresión anterior se puede escribir de la siguiente manera:

ch_arr[i][j]

El siguiente programa demuestra cómo imprimir una matriz de cadenas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<stdio.h>

int main()
{
    int i;

    char ch_arr[3][10] = {
                             "spike",
                             "tom",
                             "jerry"
                         };

    printf("1st way \n\n");

    for(i = 0; i < 3; i++)
    {
        printf("string = %s \t address = %u\n", ch_arr + i, ch_arr + i);
    }

    // signal to operating system program ran fine
    return 0;
}

Resultado esperado:

1
2
3
string = spike address = 2686736
string = tom address = 2686746
string = jerry address = 2686756

Alguna operación no válida en una matriz de cadena #

1
2
3
4
5
char ch_arr[3][10] = {
                         {'s', 'p', 'i', 'k', 'e', '\0'},
                         {'t', 'o', 'm','\0'},
                         {'j', 'e', 'r', 'r', 'y','\0'}
                     };

Asigna 30 bytes de memoria. El compilador hará lo mismo incluso si no inicializamos los elementos de la matriz en el momento de la declaración.

Ya sabemos que el nombre de una matriz es un puntero constante, por lo que las siguientes operaciones no son válidas.

1
2
ch_arr[0] = "tyke";   // invalid
ch_arr[1] = "dragon"; // invalid

Aquí estamos tratando de asignar un literal de cadena (un puntero) a un puntero constante que obviamente no es posible.

Para asignar una nueva cadena a ch_arr usa los siguientes métodos.

1
2
strcpy(ch_arr[0], "type"); // valid
scanf(ch_arr[0], "type");  // valid

Concluyamos este capítulo creando otro programa simple.

Este programa le pide al usuario que ingrese un nombre de usuario. Si el nombre de usuario ingresado es uno de los nombres en la lista maestra, entonces el usuario puede calcular el factorial de un número. De lo contrario, se muestra un mensaje de error.

 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include<stdio.h>
#include<string.h>
int factorial(int );

int main()
{
    int i, found = 0, n;

    char master_list[5][20] = {
                                  "admin",
                                  "tom",
                                  "bob",
                                  "tim",
                                  "jim"
                              }, name[10];

    printf("Enter username: ");
    gets(name);

    for(i = 0; i < 5; i++)
    {
        if(strcmp(name, master_list[i]) == 0 )
        {
            found = 1;
            break;
        }
    }

    if(found==1)
    {
        printf("\nWelcome %s !\n", name);
        printf("\nEnter a number to calculate the factorial: ");
        scanf("%d", &n);
        printf("Factorial of %d is %d", n, factorial(n));
    }

    else
    {
        printf("Error: You are not allowed to run this program.", name);
    }

    // signal to operating system program ran fine
    return 0;
}

int factorial(int n)
{
    if(n == 0)
    {
        return 1;
    }

    else
    {
        return n * factorial(n-1);
    }
}

Resultado esperado: 1ra ejecución:

1
2
3
4
5
6
Enter username: admin

Welcome admin !

Enter a number to calculate the factorial: 4
Factorial of 4 is 24

2da ejecución:

1
2
Enter username: jack
Error: You are not allowed to run this program.

Cómo funciona:

El programa le pide al usuario que ingrese un nombre. Después de ingresar el nombre, compara el nombre ingresado con los nombres en el master_list matriz usando strcmp() función. Si se encuentra una coincidencia, entonces strcmp() devuelve 0 y la condición if strcmp(name, master_list[i]) == 0 condición se vuelve verdadera. A la variable encontrada se le asigna un valor de 1 , lo que significa que el usuario puede acceder al programa. El programa le pide al usuario que ingrese un número y muestra el factorial de un número.

Si el nombre ingresado no es uno de los nombres en el master_list matriz, el programa sale mostrando un mensaje de error.