Saltar a contenido

Strings y punteros en C

Puesto que los strings en C son en realidad arrays es posible acceder a la direcci贸n de memoria de cada una de las celdas del array a trav茅s de un puntero del tipo char *. L贸gicamente las direcciones son siempre consecutivas ya que cada car谩cter se almacena exactamente en una celda (no ocurre igual con otros tipos de datos)
StringC
Dado que el manejo de Strings es una de las operaciones m谩s habituales en cualquier programa, la librer铆a est谩ndar C provee funciones para realizar cualquier cosa que se nos ocurra. Algunas funciones son las siguientes:

Funci贸n Descripci贸n
char *strcat(char *dest, const char *src) Concatena el string src string dest.
char *strncat(char *dest, const char *src, size_t n) Concatena el string src a dest con una longitud m谩xima n
int strcmp(const char *str1, const char *str2) Comparar strings
int strncmp(const char *str1, const char *str2, size_t n) Comparar n caracteres de dos strings
char *strcpy(char *dest, const char *src) Copia src a dest
char *strncpy(char *dest, const char *src, size_t n) Copia n caracteres de src a dest
size_t strlen(const char *str) Calcula el n煤mero de caracteres del string (sin el caracter especial \0)
char *strtok(char *str, const char *delim) Divide str en substrings separados por delim.

Para utilizar estas funciones es necesario incluir al principio del programa el archivo de cabecera string.h como en la l铆nea 28 del programa que se muestra a continuaci贸n. Este c贸digo es equivalente al mostrado en la versi贸n previa (v1) de StringC pero ahora los strings se manejan mediante punteros

StringCv2.c
  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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * StringC.c
 *
 *  Created on: 21/09/2015
 *      Author: santiago
 *
 * Soluci贸n utilizando las llamadas al sistema en string.h
 * 
 * gcc -Wall -Wextra -Werror -ansi -pedantic StringCv2.c -o bin/strc2
 */

/*
 * Definici贸n de ctes simb贸licas. Tarea para el preprocesador
 */
#define OK 0
#define MAX 50

/*
 * Gu铆as ultra-r谩pida:
 * https://www.tutorialspoint.com/c_standard_library/stdio_h.htm
 * https://www.tutorialspoint.com/c_standard_library/stdlib_h.htm
 * https://www.tutorialspoint.com/c_standard_library/string_h.htm
 * Man on-line:
 * http://man7.org/linux/man-pages/index.html
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * Copiar invocando strcpy()
 * Declaraci贸n y definici贸n
 */

void cpystr2 (void) {
    char str1[MAX+1], str2[MAX+1];

    printf("Teclear string1 (max %d caracteres): ", MAX);
    fgets(str1, MAX+1, stdin);

    /*
       Invocar funci贸n de librer铆a, m谩s simple imposible
       OJO a la cabecera de strcpy:
         char *stpcpy(char *restrict dst, const char *restrict src);
       La llamada presupone que la memoria se ha preasignado correctamente!!!
     */
    strcpy(str2,str1);

    printf("String resultante (str2): %s", str2);   /* OJO, aprovechamos el \n final en el array */
    printf("Longitud del string es (OJO!!) %d\n", (int) strlen(str2));  /* Idem */
    printf("脷ltimo car谩cter (\\n): 0x%02X\n", str2[strlen(str2)-1]);
    printf("脷ltimo car谩cter real (\\0): 0x%02X\n", (unsigned char) str2[strlen(str2)]);
}

/*
 * Concatenar str1 con str2 (OJO, ambos son arrays)
 * No leemos nada. Los strings son fijos
 * Invoca char *strcat(char *restrict dst, const char *restrict src);
 * En el c贸digo siguiente el resultado se almacena en str3
 * Para complicarlo un poco concatenamos seg煤n orden l茅xico-gr谩fico
 * Se muestra el uso de switch
 */

void catstr2 (void) {
    char str1[MAX], str2[MAX];
    int res = 0;

    /* 
       No leemos nada. Alternativa: leer strings desde el teclado
     */
    strcpy(str1, "Esta es la primera cadena");     /* 25 caracteres */
    strcpy(str2, "Esta es la segunda cadena; ");    /* 27 caracteres */

    /* 
       OJO, comparamos orden l茅xico-gr谩fico
       Se usa strcmp(). Ver https://www.man7.org/linux/man-pages/man3/strcmp.3.html
       Alternativa: implementar nuestro propio strcmp
     */
    res = strcmp(str1, str2);
    printf("strcmp devuelve %d\n", res);

    /* if motivado por el uso de switch: mofificar el valor devuelto conforme al switch */
    if (res < 0)
        res = -1;
    if (res > 0)
        res = 1;

    switch (res)   /* concatenar cadena mayor + cadena menor */
    {
        case 1:
            strcat (str1, str2);    /* el resultado queda en str1 (es mayor) */
            printf("String resultante (str1): %s\n", str1); /* OJO, no tenemos el \n final */
            printf("Longitud del string es %d", (int) strlen(str1));    /* Idem */
            break;
        case -1:
            strcat (str2, str1);    /* el resultado queda en str2 (es mayor) */
            printf("String resultante (str2): %s\n", str2); /* OJO, no tenemos el \n final */
            printf("Longitud del string es %d\n", (int) strlen(str2));  /* Idem */
            break;
        default:
            printf("Los strings son id茅nticos. No concatena\n");
    }

}

int main(void) {

    /*
     * Copiar invocando strcpy()
     */

    cpystr2();

    /*
     * Concatenar invocando strcat()
     * Por simplicidad, no leemos de la entrada
     * Concatenamos seg煤n orden l茅xico-gr谩fico
     */

    catstr2();

    exit(OK);
}


Ejercicio Autoevaluaci贸n

Escribir un tester para probar desde la l铆nea de orden cada una de las funciones en las dos versiones de StringC

  1. Reunir en un StringC.h todas las cabeceras (declaraciones) de las funciones en Stringv1.c y Stringv2.c
  2. Crear un test unitario para cada caso
  3. Compilar y ejecutar por separado