Está en la página 1de 16

Cadena de Caracters 8

08.01 Caracteres
Un caracter es una letra minúscula, mayúscula; un número: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9; un signo de puntuación: ¡, !, ¿, ?, .. otros caracteres
como, <, >, %, $ _, @, etc. Para representar el evento de presionar la tecla <enter> ¿podemos usar un caracter?: SÍ; pero no tiene
representación gráfica y es invisible. Hay muchos caracteres invisibles.

En un bit de memoria se guarda 2 estados: 0 y 1; un byte: grupo de 8 bits, puede ser interpretado como número, en bases: 2, 4, 8, 16
(las más usadas)…, también puede ser interpretado como caracter, utilizando la tabla ascii:
Tabla ascii (Un carácter se guarda en un byte = 8 bits)
Número Caracter Se escribe
0 carácter nulo '\0' en un programa; pero cuando se ejecuta, el monitor no muestra nada

10 <enter> // caracter invisible '\n' en un programa; pero cuando se ejecuta, el monitor no muestra nada

32 Espacio en blanco ' ' en un programa
...
65 A 'A'
66 B 'B'
...
97 a 'a'
98 b 'b'
99 c 'c'
..
255 nbsp
Esta tabla tiene 256 números que son interpretados como 256 caracteres
En un programa, todos los caracteres se pueden escribir como si fueran enteros:
char car = 65; // Equivalente: char car = 'A';
Los visibles se pueden escribir como entero o carácter entre comillas simples:
char car1 = 65, car2 = 'A'; // ambos car1 y car2 tienen como valor la letra ‘A’
otros ejemplos de valores: 'a', '1', '&', '+', ' ' (carácter blanco), etc.
Algunos invisibles se pueden escribir como caracter con escape (/), ejemplo: '/n' representa a <Enter>; también se usa LF (Line Feed, en
inglés).
Los caracteres invisibles no se ven en el monitor, la impresora ni en el teclado, pues no tienen imagen, a veces se ven manchas o signos
raros.

Definición y asignación de valores


char dato1= 'a', dato2, dato3; // Tipo char

Formato de lectura/escritura (formato %d):


printf("Ingrese un carácter: ");
scanf("%c", &dato2); // tipee b<enter> // <enter> permanece en el buffer
dato3 = dato2+1; // Se toma el siguiente carácter de la tabla
printf("Datos: %c, %c, %c\n", dato1, dato2, dato3);
Salida:
Datos: a, b, c

Lectura/escritura de caracteres con scanf()/printf()


01 // 08_01a.c: Leer/escribir varios caracteres
02 #include<iostream>
03 int main(){
04 char cc, dd, ee;
05 printf("Ingrese 2 caracteres: ");
06 scanf("%c", &cc); // Tipee ab<enter> cc = 'a' // lee todos los caracteres del buffer
07 scanf("%c", &dd); // dd = 'b'
08 scanf("%c", &ee); // ee = <enter>
09 printf("\n%c", cc);
10 printf("\n%c", dd);
11 printf("\n%d\n", ee); // atento al formato %d para que escriba el código: cout << (int)ee
12 }

PÁGINA: 1
Salida:
Ingrese 2 caracteres: ab<enter>
a
b
10 // <enter> (carácter invisible) tiene código ascii 10
Explicación: Durante la ejecución, ocurre lo siguiente:
En la línea 06: El computador se detiene y espera el ingreso de: ab<enter>, guarda todo en el buffer, y lee 'a' en cc.
En la línea 07: lee del buffer el carácter 'b' en dd.
En la línea 08: lee del buffer el carácter <enter> en ee.

Lectura/ecritura de caracteres con cin/cout


01 // 08_01b.c: Leer/escribir varios caracteres
02 #include<iostream>
03 int main(){
04 char cc, dd;
05 cout <<"Ingrese 2 caracteres: "; // ingrese ab<enter>
06 cin >> cc >> dd; // equivalente: cin >> cc; (cc = 'a' ) cin >> dd; (dd = 'b' )
07 cout << cc << dd << endl; // equivalente: cout << cc; cout << dd << endl;
08 }
Salida:
Ingrese 2 caracteres: ab<enter>
ab
La lectura/escritura con cin/cout se comporta en modo diferente:
Lectura: lee el primer carácter visible, descarta todos los caracteres invisibles, blancos y <enter>.
cin >> cc; // tipeo: a<enter> => descarta todos los caracteres blancos iniciales, lee 'a' y descarta <enter>

Escritura: escribe un carácter, si es invisible no se ve, no escribe con formato numérico.


cout << '\n'; // no escribe a <enter>
printf("%c", '\n') // no escribe a <enter>
printf("%d", '\n') // escribe: 10
cout << (int)'\n' // escribe: 10

08.02 Aritmética Limitada de Caracteres


Los caracteres se convierten (via auto-casting) a su código numérico ascii y viciversa al caracter, dependiendo del contexto de
operación; ejemplo: Suma o resta de números y caracteres:
'a' + 1 ≡ 'b' : 'a' se convierte a 97 + 1 = 98, el cual se convierte a carácter = 'b'.
Ejemplo:
char dato = 'a';
printf("Número = %d; Caracter = %c\n", dato, dato); // con formato "%d" se imprime número, con "%c" caracter
printf("Número = %d; Caracter = %c\n", dato + 1, dato + 1); // se suma 1
Salida:
Número = 97; Caracter = a
Número = 98; Caracter = b

Restar dos caracteres: 'b' - 'a' = 1;


Suma de caracteres: Si lo hace; pero no tiene sentido sumar caracteres.

Ejercicio: Escriba un programa que lea una letra minúscula (la valide como tal) y la convierta en mayúscula (réstele 32).

// 08_02.c: Comparar dos caracteres


using namespace std;
int main(){
char dato1 = 'a', dato2 = 'b';
if(dato1 > dato2) cout << dato1 << " es mayor que " << dato2 << endl;
else if(dato1 == dato2) cout << dato1 << " es igual a " << dato2 << endl;
else cout << dato1 << " es menor que " << dato2 << endl;
}
Salida:
a es menor que b

Ejemplo: Escriba un programa que pregunte:


Te gusta cantar (s/n): // responda s ó n
Te gusta bailar (s/n) : // responda s ó n
PÁGINA: 2
Responda:
Chévere, llévame contigo // si respondió s s
Bueno, te enseñare a bailar // si respondió s n
Bueno, te enseñare a cantar // si respondió n s
Fuera de acá aburrido // si respondió n n
//08_03.c: Dialogo con la computadora
Usando cin y cout Usando printf() y scanf()
#include<iostream> #include<iostream>
using namespace std;
int main(){ int main(){
char cantar, bailar; char cantar, bailar;
cout << "Te gusta cantar (s/n): "; printf("Te gusta cantar (s/n): ");
cin >> cantar; // tipee s<enter> scanf("%c", &cantar); // tipee s<enter>, lee 's', deja <enter>
while(getchar() != 10); // Vacía el buffer: l
cout << "Te gusta bailar (s/n): "; printf("Te gusta bailar (s/n): ");
cin >> bailar; // tipee s<enter> scanf("%c", &bailar); // tipee s<enter>
// no es necesario vaciar el buffer, no se leerá más
if (cantar=='s')
if (bailar=='s') printf("Chévere, llévame contigo\n");
else printf("Bueno, te enseñare a bailar\n");
else if (bailar=='s') printf("Bueno, te enseñare a cantar\n");
else printf("Fuera de acá aburrido\n");
}
Salida:
Te gusta cantar (s/n): s
Te gusta bailar (s/n): s
Chévere, llévame contigo

08. 03 Arreglo y Cadena de Caracteres


Un arreglo de caracteres es un conjunto que contiene caracteres, por ejemplo:
char arr[3] = {'a', 'b', 'c'};
Se define, asigna valores, opera y funciona, como a cualquier otro arreglo.

Una cadena de caracteres es un arreglo de caracteres de una dimensión, que contiene al menos una vez el carácter: '\0' (código ascii =
0, NULL), ejemplo:
char arr[5] = {'a', 'b', '\0','d', '\0' };
arr
a b \0 d \0
Posiciones 0 1 2 3 4
La cadena Inicia en la posición 0, en este ejemplo, con el carácter 'a' y termina cuando encuentra el primer '\0', en este ejemplo, en la
posición 2.
La cadena esta compuesta por: 'a', 'b' y '\0'. Después de esta posición, no se consideran los elementos, en este caso se desperdician:
'd' y '\0'.
Longitud del arreglo arr = 5.
Longitud de la cadena arr: strlen(arr) ≡ 2; el primer carácter '\0' indica el fin de la cadena.
Si asignamos: arr[2] = 'c';
Longitud de la cadena arr cambiará a 4.

Definición y asignación de valores


char arr = "hola"; ≡ arr[ ] = {'h', 'o', 'l', 'a', '\0'} ≡ char arr[10] "hola"; desperdicia espacios de la derecha.

char arr1[10] = "hola", arr2[ ] = {'h', 'o', 'l', 'a', '\0'}, arr3[ ]= "Hola";
arr1: es un arreglo de 10 elementos y contiene la cadena “hola” + '\0', longitud de cadena = 4.
arr2: es un arreglo de 5 elementos y contiene la cadena “hola” + '\0', longitud de cadena = 4.
arr3: es un arreglo de 5 elementos y contiene la cadena “Hola” + '\0', longitud de cadena = 4.

Advertencia: Si se omite '\0' como fin de cadena, es un error de lógica SEVERO: el programa compila (no controla el valor de las
variables); pero en tiempo de ejecución se pueden producir errores de resultados o "violación de segmento"; es responsabilidad del
desarrollador garantizar que el arreglo contenga '\0' en algún lugar.

PÁGINA: 3
Leer y escribir cadenas con el formato %s
char arr[20],
scanf("%s", arr); // arr sin & adelante (&arr) porque arr es arreglo y entrega su dirección de inicio.
// descarta los primeros caracteres en blanco, toma solo caracteres distintos de blanco hasta hallar otro blanco:
// ingrese: abc def<enter>
// arr = “abc" incluye '\0', def<enter> queda en el buffer
printf("%s", arr); // escribe toda la cadena, aunque tenga espacios en medio.
Ejemplo:
char arr1[40], arr2[40];
printf("Ingrese dos string: ");
scanf("%s", arr1); // ingrese: aaa bbb ccc<enter> // queda en el buffer: bbb ccc<enter>
scanf("%s", arr2); // lee bbb, queda en el buffer: ccc<enter>
printf("%s %s\n", arr1, arr2);
Salida: aaa bbb

Leer y escribir cadenas con cin y cout


char arr1[40], arr2[40];
cout << "Ingrese dos string: ";
cin >> arr1 >> arr2; // equivalente: cin >> arr1; cin >> arr2;
// ingrese: aaa bbb ccc<enter> // queda en el buffer: ccc<enter>
cout << arr1 << " " << arr2;
Salida: aaa bbb

De acá en adelante manejaremos a los caracteres con visión cuadruple:


Visión Definición Notas
Caracter char cc = 'a'; Caracteres simples
Arreglo char cc[3] = {'a', 'b', 'c'}; Arreglo de caracteres
longitud = 3, no es una cadena.
Cadena de char cc[ ] = "ab"; // equivalente: char cc[ ] = {'a', 'b', \0''} Se usa funciones para: leer, imprimir,
caracteres Agrega '/0' automáticamente al final de los caracteres; cc es un arreglo de asignar, copiar, buscar subcadenas,
longitud 3, y también es cadena de longitud 2 conversión de tipo, escritura, etc.
Apuntador char cc[ ] = "ab", *pcc = cc;
Se recorre arreglos o cadenas.
pcc apunta a cc como arreglo o como cadena (si contiene '\0')

// 08_04.c: Comparación de arreglo y cadena de caracteres


#include<iostream>
#include<cstring> // librería para funciones de cadena
using namespace std;
int main(){
int i;
char arr[5] = {'a', 'b', '\0','c', '\0' };
cout << "Arreglo : ";
for(i=0; i<5; i++) cout << arr[i]; // imprime arreglo
cout << "\nLongitud de arreglo: " << sizeof(arr) << " elementos" << endl;
cout << "Cadena : " << arr << endl; // imprime cadena
cout << "Longitud de cadena : " << strlen(arr) << " caracteres\n"; // strlen(arr) = longitud de cadena
}
Salida:
Arreglo : abc // se imprime los 5 elementos, pero no se ven dos '\0' porque son invisibles
Longitud de arreglo : 5 elementos // longitud del arreglo: 5
Cadena : ab // se imprime solo los 2 elementos de la cadena, se pierde la cola
Longitud de cadena: 2 caracteres // longitud de la cadena: 2

Es responsabilidad del programador no exceder los límites derecho o izquierdo de arreglos y cadenas y el caracter de fin de cadena;
el compilador no reporta error; pero en tiempo de ejecución se producen resultados errados o errores de memoria (violación de
segmento); por ejemplo:
char arr[5] = {'a', 'b', '\0','c', '\0' };
Printf("\n arr[0] = %c arr[1] = %c", arr[0], arr[1]);// Salida: arr[0] = a, arr[1] = b
arr[0] = 'x'; // Asigna 'x' al elemento 0 y se tiene: {'x', 'b', '\0','c', '\0' };
arr[2] = 'z'; // Asigna 'z' al elemento 2 y se tiene: {'x', 'b', 'z','c', '\0' };
arr[4] = 'd'; // Asigna 'd' al elemento 4, arr ya no es cadena sino arreglo que contiene: xbzcd.
PÁGINA: 4
arr[7] = 'z'; // compila, pero en tiempo de ejecución se esta saliendo del arreglo.
arr[-1] = 'r'; // compila, pero en tiempo de ejecución se esta saliendo del arreglo.

Entendiendo a la función scanf()


Sintaxis : int scanf("format", &v1, &v2, ...);
Entradas:
format: formato que controla el modo de lectura para v1, v2, …
&v1, &v2, ... : lista de direcciones de variables, que se aparean con format
Proceso: Lee datos del teclado (almacenandolos en un buffer) y los asigna a las memorias de &v1, &v2, ...
retorna : número de datos leídos.

Ejemplo: Leer valores de tipo caracter para c1 y c2, según el formato "%c %c" (el primer %c se aparea con c1, el segundo con c2):
#include<iostream>
int main(){
int n;
char c1, c2;
n = scanf("%c %c", &c1, &c2); // teclee: a b n = número de variables leídas
printf("%d: %c %c\n", n, c1, c2);
}
Salida:
2: a b

Cuando lee con scanf( ), sucede lo siguiente:


1) Se suspende la ejecución del programa, mientras se escribe en el teclado, los caracteres aparecen en el monitor, y se van
guardando en un área temporal llamada buffer.
2) Cuando se presiona <enter> se reinicia la ejecución del programa y se lee del buffer:
Si lee un dato numérico, por ejemplo:
scanf("%d", &n);
El operador puede ingresar:
12<enter> // lee bien y vacía el buffer
12 <enter> // lee bien y vacía el buffer; aunque hayan espacios en blanco antes y después del número
doce<enter> // lee y vacía el buffer; no muestra error; pero n toma un valor desconocido.

Si lee caracteres: se leen uno por uno del buffer, por ejemplo para:
scanf("%c", &c1);
El operador puede ingresar:
a<enter> // lee 'a', en el buffer permanece <enter>
a<enter> // lee ' ' (un espacio en blanco), en el buffer permanece a<enter> para ser leido por el siguiente scanf()
Por este motivo, después de leer caracteres, se debe vaciar el buffer con:
while(getchar()!=10); // getchar( ) lee un carácter, 10 es el código ascii de <enter>

Entendiendo a la función printf()


Sintaxis : int printf("format", exp1, exp2, ...);
Entrada:
format: formato que controla el modo de impresión de los valores de exp1, exp2, … .
exp1, exp2, ... : lista de expresiones cuyos valores se imprimen, se aparean con formatos del format
Proceso: Imprime en el monitor los valores de exp1, exp2, … según format.
Retorno: Número de caracteres escritos.

Ejemplo:
int n;
n = printf("La vida es bella"); // imprime La vida es bella y asigna a n el número de caracteres escritos: 16
printf("\n%d\n", n);
Salida: La vida es bella
16

printf(": tiene %d caracteres\n", printf("La vida es bella")); // imprime el print ineterno: "La vida es bella" y luego el externo
16 caracteres
Salida: La vida es bella: tiene 16 caracteres

PÁGINA: 5
08.04 Apuntador a Cadena de Caracteres
char cc[] = "abc", *pc = cc;
pc cc
0x…0 a b c \0
0x…0
printf("%s\n", cc); // Salida: abc
printf("%s\n", pc); // Salida: abc
printf("%s\n", pc+1); // Salida: bc

Peligro: Detección de errores de lógica SEVEROS, ejemplo:


char a1[] = "abc", *p1 = a1; // compila y ejecuta bien.
char *p2 = "1234"; // no debiera compilar por que un apuntador no guarda datos, solo apunta
cout << p2 << endl; // sin embargo compila con warning (advertencia); pero ejecuta bien.
cout << "Ingrese una cadena: ";
cin >> p2; // p2 no aloja datos, p2 apunta a una dirección
cout << p2; // violación de sengmento: p3 no tiene espacio para alojar datos
EL DESARROLLADOR ES RESPONSABLE de:
• Asignar valores a todas las variables: sinples (int, float, chr, etc), arreglos y apuntadores antes de usarlos.
• No exceder los límites de las dimensiones de los arreglos
• La existencia del carácter de fin de cadena
• Controlar que los apuntadores apunten a direcciones válidas.
Los procedimientos para detectar y disminuir estos errores de lógica son: verificar resultados con la matriz de casos de prue-
ba y/o escribir trazas: escribir, en líneas clave, los valores de las variables importantes.

Valores de pcc:
char *pcc= "abc"; // Warning: esta asignación será discontinuada
printf("%p\n", pcc); // Dirección de pcc : 0xf….0
printf("%s\n", pcc); // Cadena apuntada: abc
printf("%s\n", pcc+1); // Cadena apuntada: bc
printf("%c\n",*pcc); // Primer carácter : a

Novena aplicación: Apuntadores como variables de iteración de una cadena de caracteres


// Diferentes modos de escribir: Hola mundo
#include<iostream>
#include<cstring>
char cc[] = "Hola mundo", *pcc = cc;
int i=0, ncc = strlen(cc);
Usando la cadena cc Usando el apuntador pcc
for(i=0; i<ncc; i++) printf("%c", cc[i]); for(i=0; i<ncc; i++) printf("%c", pcc[i]);
for(i=0; i<ncc; i++) printf("%c", *(cc+i)); for(i=0; i<ncc; i++) printf("%c", *(pcc+i));
while(cc[i]) printf("%c", cc[i++]); while(*pcc) printf("%c", *pcc++); // pcc apunta al final de la cadena: '\0'

// 08_05.c: Escribir un arreglo de cadenas que contenga el inicio del poema 15 de Neruda
Matriz de caracteres Apuntador a filas de caracteres
#include <iostream>
int main(){
int m=4, n = 60, i=0;
char poema[4][60] =
{"Me gusta cuando callas porque estás como ausente",
"y me oyes desde lejos, Y mi voz no te toca",
"Parece que los ojos se te hubieran volado",
"y parece que un beso te cerrara la boca"};
char *p = poema[0];
for(; i<m; i++) printf("%s\n", poema[i]); for(; i<m; i++, p += n) printf("%s\n", p);
}
Salida:
Me gusta cuando callas porque estás como ausente
y me oyes desde lejos, Y mi voz no te toca
PÁGINA: 6
Parece que los ojos se te hubieran volado
y parece que un beso te cerrara la boca

08.05 Paso de Argumentos de Tipo Caracter a Funciones


Se pasan caracteres, arreglos o apuntadores de caracteres del mismo modo que se pasan argumentos numéricos, lo cual ya fue
estudiado.
Aplicación: Hasta ahora, al describir la función printf( ), hemos utilizado una sintaxis simplificada <incompleta>:
printf(“format”, ... ); // “format” es una cadena constante (no puede cambiar).
Ahora ya tenemos las herramientas para utilizar la sintaxis formal, que nos permite utilizar un formato variable:
char format[ ]= “...”;
printf(format, ... ); // la cadena format puede contener cualquier formato válido
Sintaxis simplificada <incompleta> Sintaxis formal <completa> utilizada por la API de C++
printf("format", ex1, ex2, …) int printf(const char *format, tipo1 ex1, tipo2 ex2, ...);

Entradas: Entradas:
format: cadena de caracteres format: apuntador constante a una cadena de caracteres
ex1, ex2, ... : lista de expresiones a imprimir según format ex1, ex2, ... : lista de expresiones cuyo valor será impreso
según format
Retorno: número de caracteres impresos en el monitor
Ejemplo:
float f = 2.5;
// formato fijo // format dinámico
char format1[ ]= "%.f\n", format2[ ]= "%.2f\n", *pf=format1;
printf(“%f\n”, f); printf(pf, f); // equivalente: printf(format1, f);
pf = format2;
printf(pf, f); // equivalente: printf(format2, f);
Salida:
2.500000 2.500000 2.50

08.06 Funciones de Entrada de Datos desde el Teclado


requiere incluir la librería iostream
Descripción Sintaxis Ejemplos
Leer un carácter int getchar(void) int cc;
desde el teclado proceso: lee un carácter del teclado. printf("Ingrese un carácter: ");
retorno: código ascii leido, lee cualquier cc = getchar(); // tipee <enter>
carácter, por ejemplo: <enter>. printf("%d\n", cc); // Salida: 10
Leer una lista de int scanf(const char *format, &v1, int m, n;
variables desde el &v2, ...) char a, b, c[6], d[6], *p = d;
teclado Entradas:
format: formato para variables v1, v2, … scanf("%d", &m);
v1, v2, ... : lista de variables a leer. char *format = “%d”; // equivalente
Proceso: Lee del teclado valores para: scanf(format, &m);
v1, v2, … de acuerdo a format.
Al tipear: el final de un dato de tipo Tipeos válidos:
numérico o carácter es indicado por uno o 3<enter>
más espacios en blanco o por <enter>. 3 <enter> // espacios antes y después
Atento: Tipeo no válido: tres<enter>
1) El formato %c, para leer caracteres,
requiere leer el carácter <enter>. scanf("%d %d", &m, &n);
2) El formato %s, para leer una cadena Tipeos válidos:
v1, considera que la cadena tipeada 3 4<enter>
termina con un espacio en blanco o 3 <enter> 4 <enter> // espacios antes y después
<enter>. Agrega '\0' al final de v1. No Tipeo no válido: 3 tres <enter>
controla la longitud de la cadena tipeada.
Retorno: número de variables leídas. scanf("%c", &a);
Tipeos válidos:
<enter> // a toma el valor '\n' y vacía el buffer
PÁGINA: 7
x<enter> // a toma el valor 'x', en el buffer queda '\n'
Tipeo no válido: no hay

scanf("%c%c", &a, &b);


Tipeos válidos:
xy<enter> // a ←'x', b ←'y', en el buffer queda '\n'
x<enter> // a ←'x', b ←'\n'
<enter> // a ←'\n', espera la entrada de b.
Tipeo no válido: no hay

scanf("%s", c); // agrega '\0' al final de la cadena


Tipeos válidos:
Hola mundo<enter> // c ←"Hola"; acepta una sola palabra
Tipeo no válido:
Hola1234567<enter> // c ←Error: sobrepasa la dimensión

scanf("%s %s", c, d);


Tipeos válidos:
Hola mundo<enter> // c ←"Hola" d ←"mundo"
Tipeo no válido:
Hola1234567<enter> // c ←Error: sobrepasa la dimensión

scanf("%s %s", c, p);


Tipeo válido:
Hola mundo<enter> // c ←"Hola" p ←"mundo"
Leer una cadena de char *fgets(char *cad, int n, File char arr[20], *p;
caracteres desde *stream) printf("Ingrese una cadena: ");
un archivo Entradas: // leer máximo 19 caracteres en arr desde el teclado: stdin
cad: cadena que contendrá el valor leído. p = fgets(arr, 20, stdin);
n: número de caracteres (menos 1) a leer if (p) printf("%s\n", arr);
o hasta fin de stream (enter). else printf("No leyó datos\n");
stream: nombre de un archivo de entrada
Proceso: Lee del buffer n-1 caracteres o
hasta encontrar <enter> y agrega '\0' al
final.
Retorno: puntero a var en caso de éxito;
si no se lee ningún carácter y se llega a
fin de stream, no se altera var y retorna
null.
Leer una cadena Int readString(char *var, int n) int readString(char *cc, int n){
con longitud Entradas: int c, m=0;
controlada. var: var, contendrá el valor leído. n--;
Esta función no es n: número de caracteres (menos 1) a for(;(c=getchar())!=10 && m<n; m++) *cc++= c;
nativa de C++ leer o hasta llegar a <enter>. *cc = '\0';
Proceso: Lee caracteres del buffer y los return m;
va guardando en var hasta encontrar }
<enter> ó se completen n-1 caracteres, int main(){
agrega '\0' al final de var y desecha la char arr[6];
cola del buffer. readString(arr, 6);
Retorno: número da caracteres leídos. printf("%s\n", arr);
}
Si tipea: a b<enter> arr ← "a b\0" y limpia el buffer.
Si tipea: ab cde<enter> arr contiene "ab cd\0" y limpia el buffer..
Si tipea: ab cdefg<enter> arr contiene "ab cd\0" y limpia el buffer.

PÁGINA: 8
08.07 Funciones de Salida de Información hacia el Monitor
requiere incluir la librería iostream
Descripción Sintaxis Ejemplo
Imprimir un carácter int putchar(int cc) char cc = 'a';
(sin formato) Entrada: cc: carácter a imprimir. putchar(cc);
Proceso: imprime cc en el monitor. Salida: a
Salida: 1 exitoso, 0 error .
Imprimir,con formato, int printf(const char *format, ex1, ex2, ...) char arr[6] = "ab c";
valores de expresiones Entradas: printf("arr = %s\n", arr);
format: formato para imprimir ex1, ex2, … Salida:
ex1, ex2, ... : lista de expresiones a imprimir. arr = ab c
Proceso: Imprime en el monitor con formato format.
Retorno: Número de caracteres impresos.
Imprimir, sin formato, una int puts(const char *var) char arr[6] = "ab c";
cadena Entrada: var: cadena a imprimir. puts(arr);
Proceso: Imprime var en el monitor. puts("Todo se entendió bien");
Retorno: El número de caracteres impesos + 1. Salida:
ab c
Todo se entendió bien
Imprimir una cadena en un int fputs(const char *cad, FILE *file) char arr[4] = "abc";
archivo de destino Entrada: // imprime en el monitor:
cad: cadena a imprimir. // stdout
file: archivo de salida. fputs(arr, stdout);
Proceso: Escribe var en file. Salida:
Retorno: número de caracteres escritos. abc

Ejemplos
#include<iostream>
int main(){
char datos[6];
printf("Ingrese una cadena de caracteres: ");
scanf("%s", datos); // Ingrese en el teclado: abc
printf("Usted ingresó: %s\n", datos);
}
Salida:
Ingrese una cadena de caracteres: abc
Usted ingresó: abc

Nota: Si en lugar de ingresar "abc" hubiera ingresado " a bc".


Salida: Usted ingreso: a
Esto se debe a que, scanf("%s", datos) desecha los blancos del inicio y finaliza con un blanco o <enter>
Para resolver este problema se utiliza:
readString(datos, 6); // Ingrese en el teclado: a bc
Salida: Usted ingreso: a bc

08.08 Funciones para Cadenas


Notas:
1) Usaremos un nuevo tipo de dato: size_t, parecido a long unsigned, su formato de lectura/escritura es lu, ejemplo:
size_t n = 4;
printf("\nn = %lu\n",n);
Salida: n = 4
2) Para utilizar estas funciones requiere incluir:
#include<cstring>

PÁGINA: 9
Descripción Sintaxis Ejemplo
Longitud de cadena size_t strlen(char *cad) char arr[ ] = "abc";
Entrada: cad: cadena a operar. printf("%lu\n",strlen(arr));
Proceso: calcula la longitud de cad. Salida: 3
Retorno: longitud de cad sin contar '\0'.
Comparar dos cadenas int strcmp(const char *cad1, const char *cad2) char arr1[ ] = "abcd", arr2[ ] = "xyz";
Entradas: printf("%d\n", strcmp(arr1, arr2));
cad1: cadena a comparar. Salida: < 0
cad2: cadena a comparar.
Proceso: Compara cad1 contra cad2.
Retorno:
< 0 Si cad1 es menor que cad2.
0 Si cad1 es igual a cad2.
> 0 Si cad1 es mayor que cad2.
Buscar un caracter char *strchr(const char *cad, int c) #include<iostream>
dentro de una cadena Entradas: #include<cstring>
cad: cadena en la que se busca. int main(){
c: carácter a buscar. char cad[20] = "Hola amigo", c = 'a', *p;
Proceso: busca a c dentro de *cad. p = strchr(cad, c);
Retorno: apuntador (en la RAM) a la posición de c. if(p) printf("%lu\n", p-cad+1);
La posición de c dentro de cad es: p – arr+1. else printf("No está contenido\n"); // p == NULL
}
Salida: 4
Buscar una cadena char *strstr(const char *cad, const char *cadBus) #include<iostream>
dentro de otra cadena Entradas: #include<cstring>
cad: cadena en la que se busca. int main(){
cadBus: cadena a buscar. char cad[20] = "Hola amigo", bus[] = "la", *p;
Proceso: busca * cadBus dentro de *cad . p = strstr(cad, bus);
Retorno: if(!p) printf("No está contenido\n"); // p == NULL
Si no encuentra la cadena: NULL else printf("%lu\n", p-cad+1);
Si encuentra la cadena: apuntador a la posición de }
inicio de arrBus dentro de cad. La posición de Salida: 3
cadBus dentro de arr es: p – arr+1.

Copiar una cadena de char *strcpy(char *destino, const char *origen) char origen[ ] = "123", destino[ ] = "abcde", *p;
origen sobre otra de Entradas: p = strcpy(destino, origen);
destino destino: cadena de destino. printf("%s %s\n", destino, p);
origen: cadena de origen. Salida: 123 123
Proceso: copia origen en destino.
Retorno: apuntador a la posición de destino.
Copiar n caracteres de char *strncpy(char *destino, const char *origen, char origen[ ] = "123", destino[ ] = "abcde", *p;
origen sobre destino size_t n) p = strncpy(destino, origen, 2);
Entrada: printf("%s %s\n", destino, p);
n = número de caracteres a copiar. Salida: 12cde 12cde
Proceso: copia n caracteres de origen en destino.
Retorno: apuntador a la posición de destino.
Copiar n caracteres a int substring(char *destino, const char *origen, int #include<iostream>
partir de inicio, en inicio, int n) #include<cstring>
origen, sobre destino Entradas: void substring(char *destino, const char *origen, int
origen: cadena de origen. inicio, int n) {
destino: cadena de destino. int i;
inicio = posición de inicio en origen. for(i=0; i<n && inicio+i<strlen(origen); i++)
n = número de caracteres a copiar. destino[i] = origen[inicio+i];
Proceso: copia n caracteres de origen en destino. destino[i] = '\0';
Retorno: longitud de destino, resultado en destino. }
int main(){
char cadena[] = "01/06/98";
char subcadena[3];
substring(subcadena, cadena, 3, 2);
printf("%s\n", subcadena);
}
Salida: 06
Concatenar cad1 con char *strcat(char *cad1, const char *cad2) char arr1[ ] = "abc", arr2[ ] = "1234", *p;
PÁGINA: 10
cad2, el resultado se Entradas: p = strcat(arr1, arr2);
guarda en cad1 cad1: cadena a concatenar. printf("%s %s\n", p, arr1);
cad2: cadena a concatenar. Salida: abc1234 abc1234
Proceso: concatena cad1 con cad2.
Retorno: apuntador a cad1; resultado en cad1.
Concatenar cad1 con char *strncat(char *cad1, const char *cad2, size_t char arr1[ ] = "abc", arr2[ ] = "123", *p;
los n primeros n); p = strncat(arr1, arr2, 2);
caracteres de cad2, el Entradas: printf("%s %s\n", p, arr1);
resultado se guarda en n = número de caracteres, en cad2, a concatenar. Salida: abc12 abc12
cad1 Proceso: concatena cad1 con n caracteres de cad2
Retorno: apuntador a cad1; resultado en cad1.

Caracteres especiales frecuentes


Nombre Descripción Valor ascii Caracter Uso frecuente
NULL Fin de cadena de carácter 0 '\0' Al leer caracteres:
char c = '\0';
if(c==NULL) printf("c es nulo\n");
else printf("%c\n", c);
Equivalente:
if(!c) printf("c es nulo\n");
else printf("%c\n", c);
Puntero Nulo int *p;
if(p==NULL) printf("p es nulo\n");
else printf("%p\n", p);
Equivalente:
if(p) printf("%p\n", p);
else printf("p es nulo\n");
LF Line feed (cambio de línea) 10 '\n' Al leer caracteres

No es un carácter:
EOF End Of File (fin de archivo) -1 (No ascii) No tiene Al leer contenido de archivos
o de stream

Ejemplo de uso de arreglo de apuntadores y apuntador a apuntador con cadena de caracteres


Las cadenas de caracteres y párrafos son usados frecuentemente, las herramientas más apropiadas, suelen ser arreglo de apuntadores
y apuntador a apuntador; veamos un ejemplo:
// 08_06.c: Escriba un programa que:
defina un conjunto de palabras cp = {"juan","pedro","maria","rosa"},
lea la cadena cad que contiene: “juan busca a rosa y tambien a maria “
Busque las palabras de cp contenidas en cad.
Salida:
Ingrese una cadena cad= “juan busca a rosa y tambien a maria “
encontré a juan
encontré a rosa
encontré a maria
#include <iostream>
#include <cstring>
void buscar(int n, char **pcp, char *cad){
for(int i=0; i<n; i++, pcp++) if(strstr(cad, *pcp)) printf(" encontré a %s\n", *pcp);
}
int main(){
char cp[4][10] = {"juan", "pedro", "maria", "rosa"}, cad[81], *pcp[4];
for(int i=0; i<4; i++) pcp[i] = cp[i];
printf("Ingresar la cadena: ");
fgets(cad, 80, stdin); // ingrese: juan busca a rosa y tambien a maria
buscar(4, pcp, cad);
}

PÁGINA: 11
Problema de manejo de caracteres: Desarrolle un programa en C++ que muestre en pantalla un mensaje con un comportamiento
similar a un letrero de luces de neón, donde las letras en una ventana de m=19 caracteres, se desplazan de izquierda a derecha. El
mensaje será: "El sol de mi tierra" cuya longitud es de n= 19 caracteres. Una vista en un instante de tiempo podría ser:

Ventana: E l S o l d
1 2 3 4 5 6 7 8 9 10
Generar 3 rotaciones.
Indicaciones:
• Cada vez que se imprime una vista de ventana, se debe “dormir” a la computadora por 200 milisegundos para sincronizar su
velocidad con el ojo humano, para ello incluya la librería unistd.h a fin de usar el comando:
usleep(200000);
• Para limpiar la pantalla, incluya la librería cstdlib a fin de usar el comando:
system("clear");
Sugerencia:
1) Alargue la cadena del mensaje para incluir: el amanecer, el día, el atardecer y la noche:

2) Para producir el efecto desplazamiento: imprima n=19 caracteres, avance una posición, imprima m=19 caracteres, avance una
posición …. hasta el final.
// 08_07.c Salida y Puesta del sol
#include <iostream>
#include <cstdlib> // Para ejecutar comandos del terminal como system("clear"), la cual limpia la pantalla
#include <unistd.h> // Para la funcion: usleep(200000), la cual "durme" a la computadora por 200 milisegundos
int main(){
int n = 19, i, j, jmax= n+n+n/2, k;
char mensa[] = " El sol de mi tierra ";
system("clear");
for(i=0; i<3; i++) // Genera 3 rotaciones
for(j=0; j<jmax; j++){
for(k=0; k<n; k++) printf("%c", mensa[j+k]); // ordena imprimir m caracteres al buffer de salida
printf("\n");
usleep(200000);
system("clear");
}
}

Ejemplo: Leer una lista de nombres, crear un arreglo de apuntadores a los nombres, ordenar los apuntadores ascendentemente según
el orden de la lista, ejemplo:
Antes de ordenar los apuntadores Después de ordenar los apuntadores
lista plista (índice) Lista plista (índice)
José Pérez 0xf….00 José Pérez 0xf….20
Carlos Bazán 0xf….20 Carlos Bazán 0xf….00

Imprimir lista en modo secuencial (lista en su estado original, sin ordenar):
José Pérez
Carlos Bazán
Imprimir los valores apuntados por plista, recorrer plista en modo secuencial (lista ordenada):
Carlos Bazán
José Pérez

Salida en pantalla:
Pulsa Enter para finalizar...
Nombre y apellidos: José Pérez
Nombre y apellidos: Carlos Bazán
Nombre y apellidos:

PÁGINA: 12
Matriz sin ordenar:
Nombre y Apellidos: José Pérez
Nombre y Apellidos: Carlos Bazán

Matriz ordenada:
Nombre y Apellidos: Carlos Bazán
Nombre y Apellidos: José Pérez
// 08_08.c: ordenar apuntadores a una matriz
#include<iostream>
#include<cstring>
#define MAX 10
#define LONGE 60
int readString(char cc[ ], int n);
int main(){
char lista [MAX][LONGE], *plista[MAX], *pmin; // matriz de datos y arreglo de apuntadores
int n=0, i, j, imin;
// leer
puts("Pulsa Enter para finalizar...");
printf ("Nombre y apellidos: ");
while (readString(lista[n], LONGE) && n<MAX){
plista[n] = lista[n]; // apunta a la fila leída
printf ("Nombre y apellidos: ");
n++;
}
// ordenar el arreglo de apuntadores, método del mínimo
for(i=0; i<n-1; i++){
imin = i; // Hallar elemento mínimo
for(j=i+1; j<n; j++) if(strcmp(lista[i],lista[j]) > 0) imin = j;
if(i<imin){ // poner el mínimo al inicio
pmin = plista[imin];
plista[imin] = plista[i];
plista[i] = pmin;
}
}
// imprimir
printf (" \nMatriz sin ordenar:");
for (i=0;i<n;i++) printf ("\n Nombre y Apellidos: %s", lista[i]);
printf ("\n");
printf ("n\nMatriz ordenada:");
for (i=0;i<n;i++) printf ("\n Nombre y Apellidos: %s", plista[i]);
printf ("\n");
}
int readString(char *cc, int n){
int c, m=0;
n--;
for(;(c=getchar())!=10 && m<n; m++) *cc++= c;
*cc = '\0';
return m;
}

Ejercicio: Modifique el programa anterior utilice funciones para ordenar filas de datos.

PÁGINA: 13
08.09 Funciones para Caracteres
Para utilizar estas funciones requiere incluir:
#include<ctype.h> // biblioteca estándar, contiene macros (una forma de programar funciones) y funciones para validar caracteres:
función Descripción: Valida caracteres
isalnum(char) (A - Z o a – z ) (0 - 9)
isalpha(char) (A - Z o a - z)
isascii(char) 0 - 127 (0x00-0x7F)
iscntrl(char) (0x7F o 0x00-0x1F)
isdigit(char) (0 - 9)
isgraph(char) Imprimibles menos ' '
islower(char) (a - z)
isprint(char) Imprimibles, incluido ' ' // espacio en blanco
ispunct(char) Signos de puntuación
isspace(char) espacio, tab, retorno de línea, cambio de línea, tab vertical, salto de página (0x09 a 0x0D, 0x20).
isupper(char) (A-Z)
isxdigit(char) (0 - 9, A - F, a – f).
tolower(char) Convierte carácter a minúscula
toupper(char) Convierte carácter a mayúscula

Ejemplo: isalpha('c'), retorna número distinto de 0 (verdad).


// 08_09.c Escribir en mayúscula a una cadena de caracteres
#include<iostream>
#include<ctype.h>
int main(){
char arr[] = "Hola", *p = arr;
while(*p) printf("%c", toupper(*p++));
printf("\n");
}
Salida: HOLA

08.10 Funciones para Convertir Cadenas de Caracteres a Otras Formas de Datos


#include <cstdlib>:
Función Descripción
atoi(char *) Convierte cadena de caracteres a int
//Convierte cadena de caracteres a float
#include <iostream>
#include <cstdlib>
atof(char *) int main(){
printf("%f\n",atof("1.2"));
}
Salida: 1.2000
Funciona como printf( ); pero la salida se guarda en un arreglo y no va al monitor
int m = 16;
float x = 2.1;
sprint(char *,
char cc[20]; // acá se guarda la salida
formato)
sprintf(cc, "m = %d, x = %.2f", m, x);
printf("%s\n", cc);
Salida: m = 16, x = 2.10

PÁGINA: 14
Ejemplo: Parámetros y salida de la función int main()
Para llamar a una función miFun() se pasan argumentos (valores):
n = miFun(4, 3.1);
Al definir a miFun() se definien el tipo de retorno y los parámetros (variables) que reciben los argumentos:
int miFun(int m, float n){ … }

Hasta ahora hemos utilizado la función main( ) sin parámetros de entrada ni salida:
int main(){ … }
Esta es una excepción a la regla; pero podemos cumplirla de ser necesario:

La función int main() tiene la sintaxis general:


int main(int argc, char *argv[ ])
donde:
argc significa: argument counter (contador de argumentos) = número de elementos (filas) del arrreglo *argv.
argv significa: argument values (valores de los argumentos); es un arreglo de apuntadores a caracteres (arrglo de cadenas).
// 08_10.c: Imprimir los parámetros de int main()
#include <iostream>
#include<cstdlib>
int main(int argc, char *argv[ ]){
int i;
printf("argc : %d\n", argc); // número de argumentos
for(i=0; i<argc; i++) printf("argv[%d]: %s\n", i, argv[i]); // impresión de argumentos
printf("Número: %d\n", atoi(argv[3])); // atoi() convierte una cadena a número: atoi("31") → 31
return 1; // retorno de tipo entero.
}
Para ejecutar tipee: ./a.out 1 dos 31
Salida:
argc : 4 // 4 = Número de elementos de argv
argv[0] : ./a.out // nombre de programa ejecutado
argv[1] : 1 // primer argumento (como cadena de caracteres, un solo caracter)
argv[2] : dos // segundo argumento (como cadena de caracteres)
argv[3] : 31 // Tercer argumento (como cadena de caracteres, un solo caracter)
Número: 31 // Convierte el carácter '31' al número 31.

De acá en adelante utilizaremos la sintaxis formal para describir cualquier tema.


¡Que bárbaros!!! ¿Cuanto hemos avanzado?. Nos faltan pocos conocimientos y PRACTICAR mucho.

08.11 Preguntas de Teoría


1) Indique los códigos ascii de los caracteres:
‘A’ → ‘Z’
‘a’ → ‘z’
‘0’ → ‘9’
Espacio en blanco: ‘ ’
<enter>: ‘\n’
nulo: ‘\0’

2) Indique los caracteres resultantes:


‘A’ + 32
‘a’ - 32
‘B’ + 32
‘b’ - 32’

3) El programa:
01 #include<iostream>
02 #include<iostream>
03 using namespace std;
04 int main(){
05 char a = 'a';
06 cout << 'a'; // printf("%c", 'a');
07 cout << a; // printf("%c", a);
08
09 cin >> a; // scanf("%c", &a);
PÁGINA: 15
10 scanf("%c", &a); // cin >> a;
11 scanf("%c", a); // cin >> a;
12 }
Funciona bien desde las líneas 01 a la 09
La línea 10 parece que ejecuta: cin >> a; pero no es así ¿por qué?
La línea 11 daría warning de compilación, ¿por qué?

4) ¿Cuáles son la diferencias entre una cadena, un arreglo de caracteres y un apuntador de caracteres? De un ejemplo usando
printf( )

5) Dado el código:
char saludo[]="Hola", *p=saludo;
while(*p) printf("%s\n", p++);
Explique la segunda línea, ¿cuál es la salida?

6) Dado el código:
char saludo[]={'H', 'o', '\0', 'l','a', '\0'}, *p=saludo;
for(int i=0; i<6; i++) printf("%s\n", p++);
¿Cuál es la salida, por qué?

7) Explique, de dos ejemplos e indique el #include< … > necesario para para usar los siguientes grupos de funciones:
• Entrada de datos desde el teclado
• Salida de información hacia el monitor
• Operación de caracteres
• Operación de cadenas de caracteres
• Para convertir cadenas de caracteres a otras formas de datos

08.12 Ejercicios de Programación


Resuelva los ejercicios e imprima los resultados:
1) Lea del stdin (teclado) la cadena "hola mundo" e imprímala; repita la operación anterior, pero utilice otra función de lectura.
2) Lea del stdin la cadena "hola mundo", conviértala a "HOLA MUNDO" y muéstrela.
3) Lea del stdin dos cadenas: saludo y nombre (por ejemplo: "Hola" y "juan"), forme una sola: "HOLA Juan" e imprímala.
4) Una cadena es palíndroma si las letras de izquierda a derecha y al revés son las mismas, Ejemplo: "ana" es palíndroma.
Lea una cadena y averigue si es, o no, palíndroma.
5) Lea una cadena, por ejemplo; "Hola mundo" ordene los caracteres ascendentemente para que quede: " Hadlmnoou"
Sugerencia: utilice un algoritmo para ordenar números.
6) Dadas 3 cadenas: cad1, cad2 y cad3 de caracteres, imprímalas de menor a mayor.
7) Leer una lista de estudiantes con nombre y apellido (en una sola variable), guardarlos en las filas de una matriz, ordenar ascenen-
temente las filas e imprimir la matriz, utilice punteros y funciones. Sugerencia: Modifique un programa anterior similar.
int main(){
char lista [MAX][LONGE], *plista[MAX];
int n = leer (lista, plista); // lee datos a lista y prepara el apuntador.
ordenar (plista, n);
imprimir (plista, n);
}

8) Escriba un función que ordene un arreglo numérico y un arreglo de cadenas de caracteres. Utilice apuntadores a funciones.
9) En la teoría del capítulo de Estructuras de repetición vimos el ejemplo de dos amigos A y B que prevenían el alzeimer, para ello
habían escrito un programa que repetía el conteo de 1, 2 y 3, en modo alternativo por los dos amigos:
A B
1
2
3
1
2
3
Ahora desarrollaremos el mismo programa; pero lo haremos más vívido, agregaremos sonidos.
Los archivos de sonido, están incluidos en la carpeta. Para tocarlos se debe instalar los drivers de mp3 en ubuntu: Dentro del programa
fuente están las instrucciones.
Atento: Ver instrucciones del programador

PÁGINA: 16

También podría gustarte