Strings en C
![Author](https://blog.pleets.org/img/authors/fermius.jpg)
En un artículo anterior hemos hablado de los Arrays en C, y vimos que una cadena de caracteres está realmente representada como un array de elementos de tipo char. En este post, veremos más a fondo todo lo que tiene q ver con los strings en C.
Declaración e inicialización
A diferencia de otros lenguajes de programación C no soporta un tipo de dato primitivo de cadena. Esto significa que las cadenas son formadas a partir de otros tipos básicos, en este caso el tipo char
. Para definir el valor de una cadena utilizamos comillas dobles.
char saludo[5] = "Hola";
Internamente se almacena cada caracter en una posición del array comenzando desde la posición cero y se agrega una última posición para el caracter nulo ('/0'
). Es por esta razón que se reservan cinco espacios para la palabra "Hola" y no cuatro. También hubieramos podido definir este array de la siguiente manera:
char saludo[5] = {'H', 'o', 'l', 'a', '/0'};
También podemos hacer uso de las capacidades del compilador y definir un array sin tamaño así.
char saludo[] = "Hola";
Aunque decimos "sin tamaño" realmente es el compilador quien asigna el tamaño por nosotros. No es posible determinar el tamaño de un array en tiempo de ejecución.
Algo que podría parecer correcto sería definir primero el array de tipo char y después asignarle una cadena así:
Incorrecto
char saludo[5];
saludo = "HOLA";
Sin embargo obtendrás un error del compilador ya que como sabemos el nombre de la variable array en realidad es un puntero, y no podemos asignar la construcción "HOLA" a un array más que en su declaración. De lo contrario, parecería que estamos intentando asignar algo a la dirección de memoria del primer elemento del array.
Strings en funciones
Ya que los strings realmente son un conjunto de elementos de tipo char, y el nombre de un array realmente representa un puntero a la dirección del primer elemento del array, tiene sentido que devolvamos un string como un puntero de elementos de tipo char. Veamos esto más claro con la siguiente función que devuelve un string.
#include <stdio.h>
char* str_hello()
{
return "hello world!";
}
int main()
{
printf("%s\n", str_hello());
return 0;
}
En el anterior ejemplo la función printf
también está diseñada para aceptar un puntero a string tal y como hemos visto. También podemos aceptar cadenas de caracteres en los parámetros de una función. Veamos el siguiente ejemplo en donde agregamos relleno a una palabra enviando la cadena de destino, la cadena original y el valor del relleno en una función.
#include <stdio.h>
#include <string.h>
void str_pad(char* destination, char* string, char* pad)
{
int i;
strcpy(destination, pad);
strcat(destination, string);
strcat(destination, pad);
}
int main()
{
char word[10], result[14];
printf("Please type a word: ");
scanf("%s", word);
str_pad(result, word, "--");
printf("%s\n", result);
return 0;
}
Veamos la ejecución de este programa con una palabra dentro de los rangos especificados.
user@server$ ./main
Please type a word: hello
--hello--
Captura de strings en consola
Ya que los strings son realmente conjuntos de elementos de tipo char, tiene sentido obtener cada caracter por separado mediante el ingreso de una cadena completa por consola. Veamos el siguiente ejemplo en donde obtenemos una cadena por consola obteniendo cada caracter.
#include <stdio.h>
void get_chars(char* string);
int main()
{
char name[25];
printf("Please fill your name: ");
get_chars(name);
printf("Your name is %s\n", name);
return 0;
}
void get_chars(char* string)
{
char input;
int k = 0, is_new_line = 0;
do {
scanf("%c", &input);
is_new_line = (input == '\n');
string[k++] = !is_new_line ? input : '\0';
} while (!is_new_line);
}
La función get_chars
acepta un puntero al tipo char, que en esencia puede ser el nombre de un array, y solicita mediante un bucle que se digite caracter a caracter el string y va asignando los valores en el array. Al ejecutar este programa obtendrás una salida similar a la siguiente:
user@server$ ./program
Please fill your name: Steve
Your name is Steve
Nota que la función permitirá que digites caracteres hasta que detecte un salto de línea (\n
) y en ese caso agregará el caracter nulo (\0
) al final del array para representar la cadena. Porsupuesto, C ya trae incorporada en la función scanf
una forma de obtener una cadena de caracteres, podemos fácilmente reemplazar nuestra función para obtener caracteres con la siguiente instrucción:
scanf("%s", name);
Nuestro programa será muy similar con la leve diferencia que scanf
lee la cadena hasta un espacio en blanco y salto de línea, veamos que pasa cuando digitamos dos palabras.
user@server$ ./program
Please fill your name: Steve Jobs
Your name is Steve
En este caso nuestra función parace ser un poco mejor en este aspecto. Sin embargo, C provee otra función para obtener una cantidad de caracteres sin omitir el espacio en blanco. Podemos cambiar la instrucción de scanf por
fgets(name, sizeof(name), stdin);
Esta función acepta tres parámetros. El primero es el array en sí, que como sabemos el nombre es el puntero a la dirección del primer elemento; el segundo que es la cantidad de caracteres que se van a leer; y el tercero la entrada desde donde se tomará la información que será la entrada estándar (consola). Sin embargo, nuevamente hay una leve diferencia, y es que la función fgets
agregará el salto de línea como contenido en el string.