Apuntes C++ Manejo Variables Char
Apuntes C++ Manejo Variables Char
Cuando se estudió los tipos de datos definidos en C, se pudo observar que el lenguaje
C sólo define datos de tipo entero y de punto flotante. Se puede apreciar que existe
un tipo de dato denominado char, sin embargo una variable definida de este tipo
alberga números enteros entre -128 y 127 y no caracteres como lo hacen otros
lenguajes como el Pascal.
También se pudo apreciar que un valor constante de tipo entero se puede expresar de
diferentes formas, por ejemplo como un número entre tradicional (123, 5, 796, 114567,
etc), como un número en base 8, anteponiendo un cero al número (0173, 05, 01434,
337607, etc.) o como números hexadecimales, anteponiéndoles 0x (0x7B, 0x5, 0x31C,
0x1BF87, etc.), pero también se puede expresar un número entero empleando una
notación de caracteres, es decir escribiendo un carácter entre apóstrofos simples
('A', '?', 'h' '%', etc.). Esto se da porque un programa en C/C++ (o en cualquier
otro lenguaje de programación) se redacta en un editor de palabras, por lo tanto todo
lo que se escribe en el editor son secuencias de caracteres. Es el compilador el que
interpreta estos caracteres y los almacena en la memoria como representaciones
binarias. Es lo mismo para el compilador haber escrito int a = 65; que escribir int a
= 'A'; o escribir int a = 0x41; en la dirección de memoria dada para la variable a se
almacena la misma representación binaria (0100 0001). Es por esta razón que una
expresión puede darse de esta manera a = 'A' + 32;, no es que se pretenda sumar el
valor de 32 a la letra A, si no que se esta sumando 32 al valor numérico que este
carácter representa.
En este sentido podemos definir una cadena de caracteres en C como un arreglo en el
que en cada elemento es de tipo char. Los caracteres de una cadena se colocarán uno a
continuación del otro en los elementos del arreglo, a partir del primero. Para poder
saber donde terminan los caracteres válidos en el arreglo, se debe colocar un valor
de terminación al final de la secuencia de caracteres, este valor es cero, que
representa al carácter cuyo código ASCII es cero. Este valor se le puede proporcionar
al arreglo simplemente como 0 ó mediante su representación como carácter: '\0'.
Esta forma de manipular las cadenas de caracteres trae muchas ventajas en comparación
de la forma en que lo hacen otros lenguajes de programación. Por ejemplo en Pascal,
la longitud de las cadenas de caracteres se almacena en la misma representación, al
inicio de la secuencia de caracteres. Como cada elemento de la cadena se almacena en
un byte, y la longitud no es una excepción, las cadenas en Pascal no pueden tener más
de 255 caracteres. Las cadenas en C, al no almacenar el tamaño, permite manejar
cadenas sin límite de tamaño.
DECLARACIÓN:
Una cadena de caracteres es un arreglo de tipo char, por lo tanto una cadena de
caraceres se declara de la siguiente manera:
char identificador [límite];
Por ejemplo:
char nombre[20];
donde "nombre" es una cadena de caracteres que puede albergar hasta 19
caracteres, no olvidar que se requiere un espacio para el delimitador de la
cadena (cero o '\0'). por eso no se pueden albergar en ella 20 caracteres.
INICIALIZACIÓN:
Como cualquier arreglo, una cadena de caracteres se puede ser inicilizada en el
momento de su declaración. Esta operación se realiza de la siguiente manera:
char nomb1[10] = { 72, 111, 108, 97, 0, 43, 9, 123, 10, 45}; ó
char nomb2[10] = {'H', 'o', 'l', 'a', '\0', '+', '\t', '{', '\n', 'A'};
En ambos casos se asigna a los elemntos del arreglo la misma información
(los números en nomb1 equivalen a los códigos ASCCI de los caracteres que
aparecen en nomb2).
Observe que, según lo expuesto anteriormente, sólo los primeros cuatro datos
corresponden a caracteres válidos en las cadenas, ya que el quinto elemento
es un 0 (cero) o un '\0', delimitadores de la cadena.
Otra opción que nos da el compilador para inicializar una cadena de caracteres es
haciendo uso de una secuencia de caracteres encerrados entre comillas ("..."), como
se muestra a continuación:
char nomb4[10] = "Hola";
La función scanf también se puede emplear con punteros, sin embargo se debe tener
especial cuidado en el sentido de asegurar antes que el puntero apunte a una
dirección válida. En ese sentido, observe las siguientes instrucciones:
char nombre[20];
char *c1, *c2;
scanf("%s", c1); // Esto es un error lógico, ya que c1 no apunta a
una dirección válida.
c2 = nombre;
scanf("%s", c2); // Esto es correcto.
Un aspecto que se debe tomar en cuenta, cuando se quiere leer una cadena de
caracteres empleando scanf es que, al igual con la lectura de números, la exploración
de un dato se realiza hasta encontrar un "espacio" (entiéndase por "espacio", un
carácter blanco, un carácter de tabulación o un carácter de cambio de línea). Es por
esta razón que empleando el especificador de acceso %s en la función scanf sólo se
podrán leer palabras sueltas y no frases completas.
También se puede negar un conjunto, de modo que se permita cualquier carácter menos
los contenidos en el conjunto. Esto se logra poniendo el carácter ^ al inicio del
conjunto.
Aquí un ejemplo:
La función printf permite, empleando el especificador de formato %s, la impresión del
contenido de un arreglo de tipo char, como caracteres en la consola. La función irá
tomando cada uno de los elementos del arreglo e irá mostrando en la pantalla cada uno
de los caracteres correspondientes, hasta encontrar el delimitador de la cadena (0 ó
'\0'). Si el delimitador no se encontrara presente en el arreglo, se seguirían
imprimiendo caracteres contenidos en los bytes contiguos hasta encontrar uno.
La función puts es equivalente a scanf con la diferencia que cuando puts termina de
imprimir los caracteres, envía a la pantalla un carácter de cambio de línea. La
función puts devuelve un valor entero positivo si la operación tiene éxito y un valor
negativo (por lo general EOF) si hubo un error de lectura.
Finalmente se pueden emplear los objetos cin y cout. El uso de ambos objetos tiene un
efecto igual al del %s en las funciones scanf y printf.
También existe un método asociado a cin que permite realizar una operación similar a
gets, este método se denomina getline. La manera cómo se utiliza se explica a
continuación:
Por ejemplo:
cin.getline(cad, n);
donde "cad" es una cadena de caracteres y n es la cantidad máxima de
caracteres menos uno, que se podrá leer desde el buffer de entrada. Al final
coloca el carácter de terminación.
ASIGNACIÓN DE VALORES
Asignar un valor a una variable en un programa quiere decir que colocaremos un valor
en la posición de memoria relacionada con la variable. Cuando se hacen operaciones de
asignación se emplean por lo general valores constantes, variables o expresiones.
Empleando tipos de datos numéricos,esto se realiza de la siguiente manera:
int a, b, c;
a = 234; // asignación de un valor constante.
b = a; // asignación de una variable.
c = a + b; // asignación de una expresión.
Por otro lado, un valor constante dado para una cadena de caracteres se representa
como una secuencia de caracteres encerrados entre comillas, por ejemplo: "Cadena",
"Juan Perez Castro". Cuando se pone un valor constante de este tipo en un programa,
el compilador coloca cada uno de los caracteres, incluso el carácter determinación,
en un espacio de memoria libre, luego el compilador reemplaza el valor constante por
la dirección de inicio del área asignada. Es por esta razón que no se permite tampoco
asignar a una cadena de caracteres un valor constante, por que se intentaría
modificar la dirección a la que apunta este arreglo.
char nombre[50];
nombre = "Paula Valentina"; // esto es un ERROR de compilación.
Por otro lado, tampoco se debe confundir con el manejo de punteros ya que:
char *nombre;
nombre = "Naomi Alexandra"; // esto SI es correcto.
esto se debe a que un puntero puede apuntar a cualquier área de datos, en particular
a la asignada al valor constante.
La pregunta ahora es ¿cómo hacer la asignación?. La respuesta a esto es sencilla
aunque no es tan inmediata como una asignación simple, habrá que elaborar un rutina
que permita asignar carácter a carácter los elementos de un arreglo al otro. Esta
rutina puede ser similar a la que se muestra a continuación:
#include <stdio.h>
void copiar (char [], char []);
Otra versión de esta misma rutina, que aprovecha más las propiedades del lenguaje C
en cuanto a punteros se trata, puede ser la siguiente:
#include <stdio.h>
void copiar (char *, char *);
Esta rutina, ahora más pequeña que la anterior, lo que hace es lo siguiente: Los
punteros destino y origen apuntan inicialmente al primer elemento del arreglo
respectivo. Como la condición del while tiene un = (asignación) y no un ==
(comparación), la orden *destino = *origen coloca el primer carácter de la cadena
origen en el primer carácter de la cadena destino. Luego se aplica el operador ++,
que está como sufijo, a destino y a origen (no se aplica a *destino ni a *origen por
la forma como se agrupa el operador), por lo que cada puntero termina apuntando al
siguiente carácter de la cadena. Finalmente el resultado de la asignación es el valor
que se emplea para verificar el final de while, si es un carácter cualquiera el que
se asignó, el ciclo continua, pero si se asignó el carácter de terminación, que es un
valor cero, el ciclo se detiene. Esto último quiere decir que no se necesita dar una
orden adicional para asignar el carácter de terminación a la cadena destino. Se debe
tener en cuenta que destino y origen son dos parámetros por valor, por lo que no
importa que se alteren los lugares a donde apuntan, esto no afecta a los punteros o
arreglos de la función que llamó a la rutina copiar.
COMPARACIÓN DE CADENAS
Para comparar dos cadenas de caracteres se debe tener las mismas consideraciones que
para la asignación de valores, esto es si nosotros pretendemos compara dos cadena de
la siguiente manera:
int cad1[30], cad2[30];
gets(cad1);
gets(cad2);
if (cad1 == cad2) printf("Iguales\n");
else printf("Diferentes");
Para comparar entonces dos cadenas de caracteres, debemos elaborar una rutina que sea
capaz de compara carácter a carácter dos cadenas y así poder determinar, si son
iguales, si una es mayor que otra o viceversa. La función que se muestra a
continuación realiza esta tarea, para lo cual, devuelve un valor menor que cero si la
primera cadena es menor que la segunda, devuelve cero si ambas cadenas son iguales, o
un valor mayor que cero si la primera cadena es mayor que la segunda.
#include <stdio.h>
int comparar (char [], char []);
gets(nomb1); gets(nomb2);
resultado = comparar (nomb1, nomb21);
if (resultado == 0) printf("Las cadenas son iguales\n");
else
if (resultado < 0) printf("La primera cadena es menor que la
segunda\n");
else printf("La primera cadena es mayor que la segunda\n");
···
}
Otra versión de esta misma rutina empleando punteros puede ser la siguiente:
#include <stdio.h>
int comparar (char *, char *);
strchr char *strchr(char *cad, char c); Busca la primera ocurrencia del
carácter contenido en la
variable "c".
Si lo encuentra devuelve un
puntero que apunta al carácter
encontrado en "cad", si no lo
encuentra devuelve NULL.
Ejemplo:
El siguiente ejemplo muestra cómo se manejan algunas de estas funciones:
#include<stdio.h>
#include<string.h>