Teoría:
Historia de C:
El
lenguaje de programación C fue creado por Dennis Ritchie
entre 1969 y 1973 cuando trabajaba en Bell Laboratories
de AT&T junto con Ken Thompson en el diseño del sistema operativo UNIX. C fue
creado para poder escribir dicho sistema operativo en un lenguaje de alto
nivel, independiente del hardware donde se ejecutara.
Contar
con un lenguaje de alto nivel permitió el avance de los sistemas operativos, ya
que el mismo código podía ser utilizado en las distintas plataformas,
propiciando la reutilización de código y reduciendo los tiempos de desarrollo.
Así es que los sistemas operativos basados en UNIX, el sistema BSD, el sistema
GNU/Linux y muchos otros fueron desarrollados en C.
Además,
con el paso del tiempo se han desarrollado cientos de bibliotecas que permiten
a los programadores de C utilizar el código desarrollado por otros para la
realización de tareas comunes. Esto, a su vez, ha propiciado el desarrollo de
aplicaciones en lenguaje C.
Actualmente
es imposible contar la cantidad de aplicaciones y herramientas desarrolladas en
C.
Cadenas
de caracteres:
Las
cadenas de caracteres (también llamadas cadenas o strings)
son un tipo particular de vectores, son de hecho vectores de char, con la particularidad que tienen una marca de fin (el
caracter '\0'), además el lenguaje nos permite
escribirlas como texto dentro de comillas dobles. Veamos unos ejemplos de su
declaración:
char
cadena_hola[]="Hola";
char
otro_hola[]={'H','o','l','a','\0'};
// Igual al anterior
char
vector[]={'H','o','l','a'}; /* Un vector de 4
elementos,
con
los elementos 'H','o','l' y 'a' */
char
espacio_cadena[1024]="Una cadena en C";
char
cadena_vacia[]="";
Cómo
vimos anteriormente al declarar un vector se define la cantidad de elementos
que puede contener, en el caso de las cadenas se debe tener en cuenta el
espacio adicional necesario para el \0. Viendo el ejemplo, tanto cadena_hola y otro_hola tienen un
largo 5 y cadena_vacia tiene un largo de 1.
También
vimos anteriormente que al usar vectores debemos tener en cuenta su largo, y
así es que el largo o cantidad de elemento lo necesitamos en todas las
funciones que definimos usando vectores y lo recibimos como un parámetro más en
estas, en el caso de las cadenas al tener una marca de fin podemos prescindir
del largo y procesar una cadenas hasta llegar a la marca de fin.
Por
ejemplo, la siguiente función calcula el largo de una cadena:
/*
devuelve la cantidad de caracteres en cadena sin
contar el '\0' */
int largo_cadena(char cadena[])
{
int
largo=0
while
(cadena[largo]!='\0') largo++;
return
largo;
}
Se
debe tener en cuenta que el largo de una cadena y el largo del vector con la que
se representa son distintos, tanto por como largo_cadena() cuenta el largo de
la cadena, como por espacio_cadena del ejemplo
anterior.
Algo
bastante usual es necesitar unir dos cadenas, veamos un ejemplo:
bool unir_cadenas(char destino[], char origen[], int largo)
{
int
largo_origen = largo_cadena(origen);
int
largo_destino = largo_cadena(destino);
if
( largo_origen+largo_destino+1 > largo ) {
return
false;
}
for (int i=0; i<largo_origen;i++) {
destino[largo_destino+i] = origen[i];
}
destino[largo_destino+largo_origen]='\0';
return
true;
}
...
if
( unir_cadenas(espacio_cadena,"
que puede crecer hasta 1023 caracteres",1024) ) {
...
Estos
dos ejemplos son versiones simplificadas de funciones provistas por la
biblioteca estándar de C a través del encabezado string.h.
Nuestro largo_cadena() es similar al strlen() de la
biblioteca estándar, y unir_cadenas() se asemeja al strncat(). Si bien ver estas versiones nos sirven para
entender las cadenas en C, en general será preferible usar las funciones
provistas por la biblioteca estándar, ya que podemos estar seguros que van a
estar programadas de la mejor manera posible.
Entre
las funcione que provee la biblioteca estándar de C, las más importantes son:
largo = strlen(cadena)
// Para obtener el largo de una cadena
strcpy(destino, origen) // Copia el contenido
de origen en destino
// destino
debe ser lo suficientemente grande
strcat(destino, origen) // Agrega el
contenido de origen al final de destino
// destino
debe ser lo suficientemente grander
resultado = strcmp(cadena1,
cadena2) // Compara dos cadenas
// devuelve
un valor menor, igual o mayor que 0 según si cadena1 es menor,
// igual o
mayor que cadena2, respectivamente.
posicion = strchr(cadena,
caracter) // Devuelve la posición en memoria de la
primer
// aparición
de caracter dentro de cadena
posicion = strstr(cadena,subcadena) // Devuelve la posición en memoria de la
primer
// aparición
de subcadena dentro de cadena
Veamos
algunos ejemplos usando <string.h>:
#include <stdio.h>
#include <string.h>
...
char
color[] = "rojo";
char
grosor[] = "grueso";
...
char
descripcion[1024];
strcpy(descripcion, "Lapiz color ");
strncat(descripcion, color, 1024);
strncat(descripcion, " de trazo
", 1024);
strncat(descripcion, grosor, 1024);
// descripcion contiene "Lapiz
color rojo de trazo grueso"
...
void intercambiar(char
vector[], int pos1, int
pos2);
void invierte_cadena(char cadena[])
{
int largo = strlen(cadena);
for (int i=0; i
< (largo/2); i++) {
intercambiar(cadena, i, (largo-1)-i);
}
}
void intercambiar(char
vector[], int pos1, int
pos2)
{
char
aux=vector[pos1];
vector[pos1]=vector[pos2];
vector[pos2]=aux;
}