Strings o cadenas de caracteres
Gonzalo Carvajal B.
gcarvajalb@gmail.com
Strings
z Strings, cadenas ó ristras
z “Hola Mundo”
z Secuencia de 0 o más caracteres terminada por un 0 o NULL
z No confundir 0 con ‘0’ (ASCII 0)
z NULL termina la cadena pero no forma parte de ella
z No es considerado en el largo de la cadena
z Pero si debe considerarse su espacio al declararse
z Secuencias literales
z Indicadas por comillas dobles“ ”
z Comillas simples indican constantes (ASCII) de caracter
Strings constantes
z
Strings pueden ocupar múltiples líneas usando el backslash \
char letras[] = “abcdefghijklmnopqr\
stuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”;
z
Strings adyacentes son unidos por el compilador
char letras[] = {“abcdefghijklmnopqr”
“stuvwxyzABCDEFGHIJKLMNOPQRSTUV”
“WXYZ”} ;
Funciones para strings
z
Declaradas en <string.h>
z
Funciones de
z Largo ilimitado
z Largo de la cadena dado por el terminador 0
z Largo limitado
z Largo de la cadena es argumento de la función
Largo de un string
z
Número de caracteres en el string
z No debe contarse el 0 o NULL
size_t strlen(const char *);
z Retorna un valor de tiposize_t
z Definido en <stddef.h> como unsigned integer
z Argumento es puntero a dato constante
z Función no puede modificar el string
Tip: paso de punteros a una función
z Caso 1: puntero no constante a datos no constantes void funcion(char *ptr)
z Se puede usar el puntero para moverse por los datos y modificar su valor
z Caso 2: puntero no constante a datos constantes void funcion(const char *ptr)
z El puntero puede modificarse para apuntar a cualquier dato del tipo adecuado, pero no puede modificar su valor
z Intentar modificar el valor apuntado es un error
Tip: paso de punteros a una función
z Caso 3: puntero constante a datos no constantes void funcion(char *const ptr)
z El puntero apunta siempre a la misma dirección de memoria
z Los datos apuntados pueden modificarse mediante el puntero
z Utilizado para acceder a arreglos mediante subindices
z Caso 4: puntero constante a datos constantes void funcion(const char *const)
z El puntero apunta siempre a la misma dirección
z Los datos apuntados no pueden ser modificados
z Utilizado para pasar un arreglo que consulta los datos mediante subíndices sin modificarlos
Operaciones con strlen()
if (strlen(x) >= 10) if (strlen(x) – 10 >= 0)
z
No son iguales!
z Resta de unsigned integers da un unsigned integer como resultado
z Segunda expresión es siempre positiva!
z Forzar resultado a tener signo
if ( (signed) strlen(x) – 10 >= 0)
strcpy()
char *strcpy(char *dst, const char *src)
z
Copia la cadena apuntada por *src (incluyendo NULL) a la dirección apuntada por *dst
z Retorna puntero a dst
z src es puntero a datos constantes
z dst debe ser un
z vector de caracteres
z puntero a un vector
z puntero a memoria dinámica
strcpy()
z
Cuándo termina la copia?
z Al encontrar un byte 0 en la cadena origen
z
Qué pasa si src y dst se traslapan?
z Comportamiento indefinido
z
Qué pasa si dst es menor que src?
z strcpy() sobreescribirá datos posteriores a dst
strcpy()
char mensaje[] = “Hola”;
char mensaje2[] = “Chao”;
strcpy(mensaje, “Adios”);
H o l a \0 C h a o \0
A d i o s \0 h a o \0
strcat()
char *strcat(char *dst, const char *src)
z
Concatena cadena apuntada por *src a continuación de la cadena apuntada por *dst
z Caracter inicial de src sobreescribe el caracter nulo al final de dst
z Retorna puntero a dst
z Si src y dst se traslapan, comportamiento indefinido
z Programador debe asegurarse de reservar suficiente espacio para ambas cadenas
strcat()
char mensaje[10] = “Hola”;
strcat(mensaje, “Chao”);
H o l a \0
H o l a C h a o \0
strcmp()
int strcmp(const char *s1, const char *s2)
z Compara la cadena apuntada por*s1 con la cadena apuntada por*s2
z Comparación caracter a caracter según código ASCII
z Resultado es 0 si s1 es igual a s2
z Resultado es negativo si s1 es menor que s2
z Resultado es positivo si s1 es mayor que s2
z Concepto de mayor y menor esta asociado a codificación ASCII de los caracteres (puede usarse para ordenar alfabéticamente)
strncpy()
char *strncpy(char *dst, const char *src, size_t len)
z
Copia hasta n caracteres de la cadena apuntada por *src a la cadena *dst
z Caracteres posteriores al caracter nulo no se copian
z Si las cadenas se superponen, comportamiento indefinido
z Si la cadenasrc es más corta que n caracteres, se completa con caracteres nulos
Ejemplo: strncpy
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char destino[]="Lenguaje de Programacion";
char source[]= "XXXXX";
char *c;
int i;
printf("Original: %s\n", destino);
printf("A copiar: %s\n", source);
c=strncpy(destino, source,5);
printf("Resultado: ");
for(i=0; i<=24;i++)
printf("%c",*(c+i));
printf("\n\n ");
printf("El largo de destino es: %i\n\n", strlen(destino));
system("pause");}
strncat()
char *strncat(char *dst, char const *src, size_t len)
z
Concatena no más de n caracteres de la cadena apuntada por *s1 a la cadena *s2
z Los caracteres después de NULL no son añadidos
z El caracter inicial de src sobreescribe el caracter final de dst
z El caracter NULL siempre se añade al resultado
z Si los objetos se superponen => comportamiento indefinido
strncmp()
int strncmp(char const *s1, char const *s2, size_t len)
z
Compara hasta n caracteres de la cadena apuntada por *s1 y de la cadena *s2
z Caracteres posteriores a NULL no se consideran
z Si los primeros len caracteres de ambas cadenas son iguales, función retorna 0
z Similarmente a strcmp(), puede retornar número negativo o positivo
strchr()
char *strchr(char *s, int c)
z
Revisa la cadena s de izquierda a derecha buscando el caracter c
z Retorna un puntero a la primera ocurrencia del caracter
z RetornaNULL si el caracter no está presente char *strrchr(char const *s, int c)
z Lo mismo, pero revisa de derecha a izquierda
strpbrk()
char *strpbrk(const char *s, const char
*grp)
z
Revisa la cadena s de izquierda a derecha buscando cualquier caracter del grupo grp
char s[20] = “Hola a todos”;
char *p;
p = strpbrk(s, “aeiou”);
z Retorna un puntero a la primera ‘o’
strstr()
char *strstr(char const *s1, char const *s2)
z
Revisa la cadena s1 de izquierda a derecha buscando la cadena s2 (excluyendo NULL)
z Retorna un puntero al comienzo de s2 en s1
z Sis2 no aparece en s1, retorna NULL
z Sis2 está vacío, retorna s1
strcspn(), strspn()
size_t strcspn(const char *s, const char *grp)
z
Determina la longitud de la parte inicial de la cadena s que no contiene ningún caracter de grp
len = strspn(cadena, “o”);
z len cuenta cuántos caracteres hay en cadena hasta la primera ‘o’.
z strspn() es el complemento de strcspn()
z Cuenta cuantos caracteres de grp hay al comienzo de s
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char source[]="Lenguaje de Programacion";
char *c;
int a,b;
a=strcspn(source,"o");
b=strspn(source,"o");
printf(" \"strcspn\" nos muestra que hay %i caracteres antes de la primera \'o\'\n",a);
printf(" \"strspn\" nos muestra que hay %i \'o\' al inicio de la cadena\n\n\n",b);
system("pause");
}
Ejemplo: strcspn y strspn strtok()
char *strtok(char *str, const char *sep)
z
Rompe la cadena str en segmentos o tokens tokens, separados por alguno de los
delimitadores de la cadena sep
z La primera llamada determina la cadena a romper, y retorna un puntero al comienzo del primer token
z Si se repite llamada con *str igual a NULL, sigue buscando más tokens en la cadena original
z Si no encuentra más delimitadores, se devuelve NULL
strtok()
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char s1[] = "En este caso los tokens seran los espacios";
char s2[] = " ";
char *ptr;
printf( "s1=%s\n", s1 );
ptr = strtok( s1, s2 ); // Primera llamada => Primer token printf( "%s\n", ptr );
while( (ptr = strtok( NULL, s2 )) != NULL ) // Nuevas llamadas printf( "%s\n", ptr );
system("pause");
return 0;}
Conversión de cadenas
z Declaraciones en <stdlib.h>
z Funciones convierten cadenas de caracteres en valores numéricos enteros
z Funciones para base 10
int atoi(char const *s);
long int atol(char const *s);
z Funciones retornan un valor numérico
z Ignora sufijos no numéricos
z atoi(“123abc”) entrega 123
z Si la cadena s no puede ser representada (ej: caracteres no numéricos), la función devuelve 0.
Conversión de cadenas
z
También existen versiones para conversión a números flotantes
z
Declaración en <math.h>
double atof(char const *s);
Ejemplo: atoi y atof
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
char cadena1[] ="10.345% se recibe";
char cadena2[] ="Se recibe 10.345%";
printf( "\"%s\" en entero es %i\n",cadena1,atoi(cadena1));
printf( "\"%s\" en flotante es %f\n", cadena1, atof(cadena1));
printf( "\"%s\" en entero es %i\n", cadena2, atoi(cadena2));
printf( "\"%s\" en flotante es %f\n", cadena2, atof(cadena2));
system("pause");
return 0;
}
Conversión de cadenas
z Hay generalizaciones para convertir a una base dada
z Declaraciones en <stdlib.h>
long strtol(const char *s, char **resto, int base)
z Convierte la cadenas a long, asigna a resto la parte no convertida de la cadena. El tercer argumento indica la base que se encuentra el dato a convertir en s.
z Base puede estar entre 2 y 36, también puede ser 0.
z Existen criterios para determinar si los datos en s corresponden o no a símbolos definidos en la base.
z Ejercicio: Revisar uso de estas funciones
Clasificación de caracteres
z
Declaraciones en <ctype.h>
z
Funciones reciben un entero conteniendo un caracter
z Exceptoisprint() que recibe un char
z
Funciones retornan un valor entero para verdadero o falso
int isdigit(int c)
z Equivalente a expresión (‘0’ <= c && c >= ‘9’)
Clasificación de caracteres
z iscntrl(): Verdadero si argumento es caracter de control
z Caracteres ASCII entre 0 y 31, y el 127
z isspace(): Verdadero si argumento es caracter blanco (‘ ‘, ‘\f’, ‘\n’, ‘\t’, ‘\v’, ‘\r’)
z isdigit(): Verdadero si argumento es dígito entre 0 y 9
z isxdigit(): Verdadero si argumento es dígito entre 0 y 9, a y f, o A y F
Clasificación de caracteres
z islower(): Verdadero si argumento es caracter entrea y z
z isupper(): Verdadero si argumento es caracter entreA y Z
z isalpha(): Verdadero si argumento es caracter entrea y z, o A y Z
z isalnum(): Verdadero si argumento es caracter entrea y z, o A y Z, o 0 y 9
Clasificación de caracteres
z ispunct(): Verdadero si argumento es caracter de puntuación
z isprint(char c): Verdadero si argumento es caracter imprimible (alfanumérico, puntuación, gráfico, espacio)
z Es lo contrario de iscntrl()
z isgraph(): Verdadero si argumento es caracter gráfico
z Lo mismo queisprint() excepto por el espacio
Funciones de clasificación
Ejemplo: determinar si una cadena es un nombre de variable válido
#include <ctype.h>
#define TRUE 1
#define FALSE 0
int is_valid(const char *s) { char ch=*s;
if (ch == '\0') return FALSE;
if (!(isalpha(ch) || ch == '_')) return FALSE;
while(ch != '\0') {
if (!(isalnum(ch) || ch == '_')) return FALSE;
ch= *(s++); } return TRUE;}
Ejercicio: verifique mas condiciones y compruebe
Conversión de caracteres
z int tolower(int c): retorna su argumento como minúsculas
z int toupper(int c): retorna su argumento como mayúsculas
z Si argumento no es transformable, se retorna sin cambios
Operaciones con memoria
z
Strings terminan en byte de valor 0
z
Cómo operar con áreas de memoria que pueden contener un 0?
z Funciones de strings no sirven!
z Usar funciones de manejo de memoria
z
Similares a funciones strnxxx()
z No terminan al encontrar un NULL
z Mas generales, utilizan punteros genéricos
z Declaradas en <string.h>
memcpy()
char *memcpy(void *dst, const void *src, size_t length)
z
Copia length bytes del área apuntada por
*src al área apuntada por *dst
z Qué pasa si áreas se traslapan?
z Comportamiento indefinido
int area1[numDatos], area2[numDatos];
memcpy(area2, area1, sizeof(area1));
memmove()
char *memmove(void *dst, const void *src, size_t length)
z
Copia length bytes del área apuntada por *src al área apuntada por *dst
z Qué pasa si áreas se traslapan?
z Comportamiento correcto!
z Realiza copia temporal intermedia
z Copia la cadena src a variable temporal y luego la copia a la posicion de dst
z memmove() más lento que memcpy()
memcmp()
int memcmp(const void *a, const void *b, size_t length)
z
Compara length bytes del área apuntada por
*a con bytes del área apuntada por *a
z Comparación se hace como unsigned char
z Retorna 0 si secuencias son iguales, negativo si a < b, positivo si a > b
memchr(), memrchr()
void *memchr(void const *s, int c, size_t length)
z
Revisa length bytes del área apuntada por
*s de izquierda a derecha buscando el caracter c
z Retorna puntero a la primera ocurrencia del caracter
z RetornaNULL si el caracter no está presente
z
*memrchr() hace lo mismo, pero revisa de derecha a izquierda
memset()
void *memset(void *s, int c, size_t length)
z
Inicializa length bytes del área apuntada por
*s al caracter c
z Retorna un puntero al área inicializada