Está en la página 1de 31

#include <stdio.

h>

int main ()
{
int i, j, primo,l;
primo = 1;
printf("Introduzca un numero: \n");
scanf("%d", &l);

for (i = 2; i < l; i++)


{
for ( j = 2; j <= i/2; j++)
if ((i%j) == 0)
primo = 0;
if(primo)
printf("%d\n", i);
primo = 1;
}
system("pause");
return 0;
}

Aqui mi ejemplo de funcion, pero da error, me podrian decir en donde tengo el error(es)?

int primos(int c)
{
int a,j,p;
int num=0;
p=1;
for(a=2 ; a<num ; a++)
{
for(j=2 ; j<=a/2 ; j++)
if ((a%j) == 0)
p = 0;
if(p)
printf("%d\n", a);
p = 1;
return (num);}
}

void primos(int c){


int a,j,p;
int num=0;
p=1;
for(a=2 ; a<c ; a++){
for(j=2 ; j<=a/2 ; j++)
if ((a%j) == 0)
p = 0;
if(p)
printf("%d\n", a);
p = 1;
}
}
#include <stdio.h>

int mcd(int a,int b);

int mcm(int a,int b);

int main()

int a,b,c,d;

printf("Este programa calcula el maximo comun divisor de dos

numeros enteros\ny el minimo comun multiplo\n");


printf("Introduce el primer numero\n");

scanf("%d",&a);

printf("Introduce el segundo numero\n");

scanf("%d",&b);

c=mcd(a,b);

if(c<0) c*=-1;

printf("\n%d es el maximo comun divisor de %d y %d\n",c,a,b);

d=mcm(a,b);

if(d<0) d*=-1;

printf("\n%d es el minimo comun de %d y %d",d,a,b);

return 0;

int mcd(int a,int b)

return (b == 0)? a : mcd(b, a % b);

int mcm(int a,int b)


{

return (a*b)/mcd(a,b);

CARACTERES Y CADENAS EN C.

El tipo Carcter en C
El tipo Cadena en C
E/S de Caracteres y Cadenas - Problemas derivados del uso de un
tampn
Funciones de tratamiento de cadenas
Ejercicios propuestos

El tipo Carcter en C El nombre del tipo carcter en C es char. Este tipo


ocupa un byte (ocho bits) de extensin, y puede interpretarse con y sin signo.
La tabla de tipos de datos de carcter en C es como sigue:

Nombre Extensin Alcance


char 8 bits Cualquier cdigo ASCII
signed char 8 bits desde -128 hasta +127
unsigned char 8 bits desde 0 hasta 255

Vase a continuacin un ejemplo de utilizacin de variables de los tipos


anteriores:
#include<stdio.h>

char letra;
signed char letraconsigno;
unsigned char letrasinsigno;

int main(int argc, char * argv[])


{
letra = 'A';
printf("La letra es %c y su valor decimal es %d.\n\n",
letra,letra);

letraconsigno = -65;
printf("Letraconsigno es %d y su valor decimal es %d.\n\n",
letraconsigno,letraconsigno);

letrasinsigno = 165;
printf("Letrasinsigno es %u y su valor decimal es %d.\n\n",
letrasinsigno,letrasinsigno);
return 0;
}

Y el resultado de ejecutar este programa es:

La letra es A y su valor decimal es 65.

Letraconsigno es -65 y su valor decimal es -65.

Letrasinsigno es 165 y su valor decimal es 165.

Como puede apreciarse, el descriptor empleado para la lectura y escritur de


variables de tipo char es %c.

Nota.- La lectura de caracteres individuales plantea una insospechada


dificultad, debida a que C es literal, y cuando se le pide que lea un caracter,
obedece sin rechistar. Pero no hemos pulsado un carcter, sino dos, verdad?
Vase el siguiente

Ejemplo
#include<stdio.h>

/* Este programa muestra los peligros que acechan


al incauto lector de caracteres */

char unaletra, otraletra;

void main(void)
{
printf("Escriba una letra y pulse intro, por favor: ");
scanf("%c", &unaletra);

printf("La letra que ha pulsado era %c y su valor decimal


es %d\n", unaletra, unaletra);

printf("Ahora escriba otra letra, por favor: ");


scanf("%c", &otraletra);
printf("La letra que ha pulsado era %c y su valor decimal
es %d\n", otraletra, otraletra);

printf("\n\nTerminacin normal del programa.\n\n");


}
/*
El resultado de la ejecucin de este programa es:
Escriba una letra y pulse intro, por favor: a
La letra que ha pulsado era a y su valor decimal es 97
Ahora escriba otra letra, por favor: La letra que ha pulsado era
y su valor decimal es 10

Terminacin normal del programa.

Qu ha pasado?
*/

Existen varias posibilidades para descartar el carcter sobrante. Una de ellas


es emplear un descriptor que ignora el carcter siguiente al ledo: %c%*c en
lugar de %c. Tambin se puede recurrir a las funciones gets() y fgets(), que
ofrece stdio.h, y que sirven para leer cadenas. La primera, gets() lee del
teclado hasta que encuentra el retorno de carro; se retorno no se incluye en
la cadena proporcionada y gets() podra servir muy bien para vaciar el bfer si
no fuera peligrosa: es responsabilidad del usuario reservar espacio suficiente
para la cadena leda. Dado que no es posible anticipar con seguridad lo que
har el usuario, resulta ms prudente emplear fgets(). Esta funcin si permite
determinar el nmero mximo de caracteres ledos, y devuelve un puntero
nulo cuando el bfer est vaco. Una tercera solucin, finalmente, consiste en
invocar a la funcin fpurge(stdin) inmediatamente despus de leer el
carcter. De este modo se descarta directamente el contenido restante en el
bfer de teclado. Slo hay un problema: es propia de Unix, y los entornos que
no estn basados en este estndar suelen carecer de ella. El tipo Cadena en C
Una cadena es una sucesin de caracteres, cuyo final est marcado mediante
el carcter '\0', que se emplea como marcador de fin de cadena. Obsrvese
que se ha encerrado la expresin \0 entre comillas sencillas y no dobles. Esto
denota que se trata de un carcter; si se hubiera encerrado entre comillas
dobles se tratara de la cadena formada por este carcter... y tendra dos bytes
de longitud, siendo el ltimo, precisamente,'\0'. La adicin de este carcter
de finalizacin es imprescindible, toda vez que ser empleado por todas las
funciones de tratamiento de cadenas. Las cadenas de C se declaran como listas
de caracteres. El carcter de terminacin tambin cuenta, y ocupa un byte
igual que cualquier otro. Por tanto, una cadena para la cual se reserven 80
caracteres podr contener un mximo de 79 caracteres del usuario, ms el
carcter de terminacin. Esto no implica, desde luego, que sea obligatorio
emplear siempre todos los caracteres reservados... con el consiguiente
desperdicio de espacio en la mayora de las ocasiones. La
funcin strlen(),que pertenece a string.h, permite determinar el nmero
exacto de caracteres de la cadena utilizados realmente. El
operador sizeof() proporciona el nmero total de caracteres reservados para
la cadena. Consltense las pginas man. Las cadenas se declaran mediante
expresiones de la forma siguiente:
char cadena[numero_total_de_bytes_reservados];
o bien char cadena[] = "Algn valor"; o bien, incluso, char cadena[] =
{ 'U', 'n', 'o', 's', ' ',
'c', 'u', 'a', 'n', 't', 'o', 's', ' ',
'c', 'a', 'r', 'c', 't', 'e', 'r', 'e', 's',
'\0'}; Obsrvese que el compilador reserva, en los dos ltimos casos, el
espacio necesario para almacenar la cadena deseada. El compilador, en el caso
de dar valor inicial a la cadena, incluyen el marcador de fin de
cadena '\0' an cuando ste no se indique explcitamente. No sucede lo
mismo cuando se omite el carcter '\0' en la ltima declaracin. Vase el
siguiente ejemplo: #include<stdio.h> int main(int arcg, char* argv[])
{
char c1[8];
char c2[] = "Hola";
char c3[] = { 'U', 'n', 'o', 's', ' ',
'c', 'u', 'a', 'n', 't', 'o', 's', ' ',
'c', 'a', 'r', 'a', 'c', 't', 'e', 'r', 'e',
's', '\0'};
strcpy(c1,"hola");
printf("Esto es c1 %s\n", c1);
printf("Esto es c2 %s\n", c2);
printf("Esto es c3 %s\n", c3);
return 0;
} Obsrvese la necesidad de emplear la funcin strcpy() para dar valor a c1,
que inicialmente no haba recibido valor alguno. El compilador no admite el
operador de asignacin como mtodo para dar valor a esta cadena, porque
intentara interpretar esa expresin empleando la lgica de punteros. En
efecto: intente cambiar la expresin strcpy(c1, "Hola") por c1 = "Hola" y
compile el programa.
Obsrvese tambin que aparecen caracteres adicionales al imprimir si se
suprime el ltimo carcter (el'\0') al declarar c3. Esto se debe a
que printf() sigue imprimiendo caracteres en pantalla hasta llegar
(casualmente) a un byte de valor 0.

E/S de Caracteres y Cadenas - Problemas derivados del uso de la memoria


intermedia de teclado. Las cadenas pueden leerse y escribirse mediante el uso
de scanf() y printf() respectivamente. Es preciso tener en cuenta
que scanf() detiene la lectura de caracteres en cuanto encuentra un espacio
en blanco o tabulador. Vase un ejemplo Ejemplo
#include<stdio.h>

/* Este programa muestra la utilizacin de cadenas en C */


char cadena[8], resto[80];

void main(void)
{
printf("Escriba una cadena: ");
scanf("%s", cadena); /* Las cadenas NO llevan & */

printf("\n\nLa cadena leda era %s\n\n", cadena);

printf("Y el resto era");


gets(resto);
puts(resto);
printf("Terminacin normal del programa.\n\n");
}
Es interesante recordar que todo lo que "sobra", esto es, lo que est ms all
del primer espacio en blanco, queda almacenado y disponible para la siguiente
sentencia de lectura. La funcin gets() captura todo lo restante, y despus se
imprime mediante puts(). Hay que ser precavidos a la hora de "dejar" restos
en el tampn. Lo mejor es eliminar posibles restos antes de pasar a la lectura
siguiente, empleandofflush(stdin) o bien fpurge(stdin).

Funciones de tratamiento de cadenas

El archivo de encabezado string.h contiene numerosas funciones relacionadas


con el tratamiento de caracteres. Vase a continuacin una tabla de funciones
tiles:

/*
* Funciones de concatenacin
*/
Encabezado Descripcin
Esta funcin aade s2 a s1 y pone
un '\0' al final del resultado; se
supone que s1 contiene espacio
char *strcat (char *s1, const char
*s2); suficiente para el total de caracteres
(los de s1, los de s2 y el '\0').
Proporciona como resultado un puntero
de s1
Anloga a la anterior, pero aade
char *strncat (char *s1, const char a s1 un mximo den caracteres de s2.
*s2, size_t n); Proporciona como resultado un puntero
de s1
/*
* Funciones de comparacin
*/
Encabezado Descripcin
int memcmp (const void *s1, const
void *s2, size_t n); Compara byte por byte las dos cadenas
cuya direccin se proporciona,
suponiendo que ambas
tuvieran n bytes de longitud. Si ambas
series de bytes son iguales, la funcin
proporciona el valor 0. Si no son
iguales, la funcin devuelve la
diferencia entre los dos primeros bytes
distintos. La comparacin es numrica,
sin tener en cuenta el orden alfabtico
internacional, lo cual produce
resultados extraos cuando las
cadenas contienen signos diacrticos.
Esta funcin compara byte por byte las
cadenas de caracteres sealadas
por s1 y s2. El resultado es:
int strcmp (const char *s1, const
char *s2); negativo si s1 es menor que s2
nulo si s1 y s2 son iguales
positivo si s1 es mayor que s2

Esta funcin sirve para comparar dos


cadenas, y hace uso de la secuencia
int strcoll (const char *s1, const lexicogrfica (locale) definida en el
char *s2); momento de su ejecucin. Produce
valores numricos anlogos a los
de strcmp()
Esta funcin es una variante
int strncmp (const char *s1, const de strcmp() que compara nicamente
char *s2, size_t n); los n primeros caracteres de ambas
cadenas.
Almacena en s1 la traduccin de la
cadena s2 a la configuracin
de locale definida en el momento de la
size_t strxfrm (char *s1, const char ejecucin. Esta funcin puede no estar
*s2, size_t n); presente en todas las
implementaciones de la biblioteca de
C; consltense las pginas man de la
mquina utilizada.
/*
* Funciones de bsqueda
*/
Encabezado Descripcin
Determina la posicin de la primera
void *memchr (const void *s, int c, aparicin de c(que se interpreta como
size_t n); carcter sin signo) dentro de
los n primeros bytes de la cadena s.
Si c forma parte de s, se proporciona
como resultado un puntero de c.
Si c no forma parte de s, se
proporciona el puntero nulo.
Anloga a la anterior, salvo que se
explora toda la cadena, incluyendo el
char *strchr (const char *s, int c); marcador final '\0'. Por tanto, si se
busca '\0', se encontrar el marcador
de fin de cadena.
Esta funcin calcula la longitud del
segmento mximo de s1 que est
size_t strcspn (const char *s1, formado por caracteres queno estn
const char *s2); presentes en s2. Dicho en pocas
palabras, sirve para calcular la longitud
de la subcadena complementaria.
Esta funcin busca en s1 la primera
aparicin de cualquier carcter de los
contenidos en s2 y proporciona su
char * strpbrk (const char *s1,
const char *s2); direccin (mediante un puntero de
carcter). Si s1 no contiene ningn
carcter de s2, se proporciona el
puntero nulo.
Esta funcin busca un
carcter c dentro de la cadenas,
empezando por el final. Si lo
encuentra, proporciona su direccin
char *strrchr (const char *s, int
c); mediante un puntero. Si no lo
encuentra, proporciona el puntero
nulo. Dicho de otro
modo, strrchr() busca la ltima
aparicin de cen s.
Esta funcin calcula la longitud del
size_t strspn (const char *s1, const mximo segmento inicial de s1 que
char *s2); est formado completamente por
caracteres presentes en s2.
Esta funcin busca la primera aparicin
de s2 dentro de s1, sin tener en cuenta
el carcter de fin de cadena. Si s2 se
char *strstr (const char *s1, const encuentra en s1, la funcin proporciona
char *s2); un un puntero del primer byte
de s2dentro de s1. Si no se
encuentra s2 dentro de s1, se
proporciona el puntero nulo.
char *strtok (char *s1, const char Esta funcin extrae subcadenas
*s2); (tokens) de s1. Los separadores de
subcadenas son los caracteres que
contenga s2. La primera subcadena se
proporciona (mediante un puntero)
cuando se llama
a strtok()empleando s1 y s2 como
parmetros. La segunda subcadena (y
siguientes) se obtienen mediante
llamadas a strtok() con el puntero
nulo como primer argumento, y con la
cadena de separadores como segundo
argumento (sta se puede modificar en
las distintas llamadas). Cuando ya no
quedan ms subcadenas, la funcin
proporciona el puntero nulo. Obsrvese
la notable utilidad de esta funcin para
la lectura de archivos de texto
con formato delimitado. Obsrvese
tambin que, una vez invocada la
cadena por primera vez, se admiten
cambios en el delimitador especificado
(que es una cadena! Se pueden
emplear delimitadores "complejos",
formados por mltiples caracteres.)
/*
* Varios
*/
Encabezado Descripcin
Sirve para rellenar la cadena sealada
por s, copiando en sus bytes el valor
void *memset (void *s, int c, size_t
n); de c, interpretado como carcter sin
signo. Se escribe un mximo
de nbytes.
Esta funcin recibe como argumento
un nmero de error y proporciona
como resultado el mensaje de error
char *strerror (int errnum); correspondiente. Los nmeros y
mensajes de error dependen por
completo del compilador (y de la
plataforma).
Proporciona la longitud de la cadena
size_t strlen (const char *s);
sealada por s.
Un ejemplo
Construir un programa que muestre la forma de utilizar las principales
funciones de tratamiento de cadenas en C. El programa debe mostrar
procedimientos de lectura, escritura, comparacin, concatenacin y bsqueda
de fragmentos.
/*
* funciones.h
* cadenas
*
* Created by coti on 28/08/09.
* Copyright 2009 Tests by Coti. All rights reserved.
*
*/
#include <stdio.h>
/* aqu vive strlen() */
#include <string.h>

funciones.h /* CONSTANTES */
#define NUM_BYTES 128
#define LONGITUD_1 64
#define LONGITUD_2 64

void leer(char * p1, char * p2);


void mostrar(char * p1, char * p2);
void recorrer(char * p1, char * p2);
void comparar(char * p1, char * p2);
void concatenar(char * p1, char * p2, char * pc);
void buscar(char * p1, char * p2, char * pc);

/*
* funciones.c
* cadenas
*
* Created by coti on 28/08/09.
* Copyright 2009 Tests by Coti. All rights reserved.
*
*/

#include "funciones.h"

void leer(char * p1, char * p2)


funciones.c {
printf("\nEscriba la primera palabra: ");
fgets(p1, LONGITUD_1, stdin);
p1[strlen(p1)-1] = '\0';
printf("\nEscriba la segunda palabra: ");
fgets(p2, LONGITUD_2, stdin);
p2[strlen(p2)-1] = '\0';
printf("\n");
}
void mostrar(char * p1, char * p2)
{
printf("\nLa primera palabra es %s y la segunda es
%s\n\n", p1, p2);
}
void recorrer(char * p1, char * p2)
{
int i;
printf("\nLos caracteres de la palabra %s
son:\n\n",p1);
for (i=0; i<strlen(p1); i++) {
printf("%3d %c\n", (unsigned char)p1[i],
p1[i]);
}
printf("\nLos caracteres de la palabra %s
son:\n\n",p2);
for (i=0; i<strlen(p2); i++) {
printf("%3d %c\n", (unsigned char)p2[i],
p2[i]);
}
printf("\n");
}
void comparar(char * p1, char * p2)
{
int resultado = strcmp(p1, p2);
/* convertimos el resultado en un valor q es 1, 0 o -
1 */
resultado = resultado > 0 ? 1 : (resultado < 0 ? -1 :
0);
switch (resultado) {
case -1:
printf("\n%s es menor que
%s\n",p1,p2);
break;
case 0:
printf("\n%s es igual que
%s\n",p1,p2);
break;
case 1:
printf("\n%s es mayor que
%s\n",p1,p2);
break;
default:
break;
}
printf("\n");
}
void concatenar(char * p1, char * p2, char * pc)
{
strcpy(pc, "");
strcat(pc, p1);
strcat(pc, " ");
strcat(pc, p2);
printf("\nLa concatenacin de %s y %s es %s\n\n",p1,
p2, pc);
}
void buscar(char * p1, char * p2, char * pc)
{
char * resultado = NULL;
printf("\nEscriba la palabra que busca: ");
fgets(pc, NUM_BYTES, stdin);
pc[strlen(pc)-1] = '\0';
resultado = strstr(p1, pc);
if (NULL == resultado)
printf("\n%s no contiene a %s\n",p1,pc);
else {
printf("\n%s contiene a %s\n",p1,pc);
}
resultado = strstr(p2, pc);
if (NULL == resultado)
printf("\n%s no contiene a %s\n",p2,pc);
else {
printf("\n%s contiene a %s\n",p2,pc);
}
printf("\n");
}

#include <stdio.h>
/* malloc() vive aqu */
#include <stdlib.h>
/* toupper() vive aqu */
#include <ctype.h>
/* Las funciones viven aqu */
#include "funciones.h"

/*
Este programa muestra ejemplos de las operaciones
fundamentales con cadenas:

- declaracin (esttica)
- lectura
- escritura
- recorrido
- comparacin
- concatenacin
- bsqueda de fragmentos
main.c */

int main (int argc, const char * argv[]) {


/*
Las variables palabra_1 y palabra_2 son cadenas de
LONGITUD_1 y LONGITUD_2
bytes respectivamente, y se declaran estticamente.
*/
char palabra_1[LONGITUD_1], palabra_2[LONGITUD_2];
/*
La variable pcadena seala un bloque de memoria de
dimensiones
iguales a la suma de dimensiones de palabra_1 y
palabra_2.
*/
char * pcadena =
malloc((LONGITUD_1+LONGITUD_2)*sizeof(char));
/*
Este es el men q muestra la aplicacin
*/
char menu[] = "1)Leer 2)Mostrar 3)Recorrer
4)Comparar\n5)Concatenar 6)Buscar fragmento Q) Salir";
/*
Esta es la opcin q escribe el usuario
*/
char opcion;
/*
Esta es la condicin de finalizacin del programa
*/
int terminar = 0;
do {
printf("%s ", menu);
scanf("%c%*c",&opcion);
opcion = toupper(opcion);
switch (opcion) {
case '1':
printf("\nLectura de
cadenas\n");
leer(palabra_1, palabra_2);
break;
case '2':
printf("\nEscritura de
cadenas\n");
mostrar(palabra_1, palabra_2);
break;
case '3':
printf("\nRecorrido de
cadenas\n");
recorrer(palabra_1,
palabra_2);
break;
case '4':
printf("\nComparacin de
cadenas\n");
comparar(palabra_1,
palabra_2);
break;
case '5':
printf("\nConcatenacin de
cadenas\n");
concatenar(palabra_1,
palabra_2, pcadena);
break;
case '6':
printf("\nBuscar un
fragmento\n");
buscar(palabra_1, palabra_2,
pcadena);
break;
case 'Q':
printf("\nTerminacin del
programa\n");
terminar = 1;
break;
default:
break;
}
} while (!terminar);
return 0;
}

Comentarios
Este programa consta de dos archivos, y se puede compilar desde la lnea de
rdenes, o empleando cualquier IDE. Vanse las pginas
man
correspondientes a las distintas funciones.
La arquitectura de programa es muy bsica; si se aade una funcin ms ser
preciso modificar el programa principal. Sera posible emplear otra arquitectura
menos engorrosa?

Ejercicios resueltos y propuestos

1. Ejercicio 0103r01.-Un programa recibe un nombre y un apellido a


travs del teclado, en la forma:

Por favor, dgame el nombre : Jos


Por favor, dgame el apellido : Garca

Se pide construir y mostrar en pantalla una cadena de la forma:

Titular: Jos Garca.

Emplear las funciones de concatenacin descritas. Qu ocurre si la


cadena formada es ms larga que la cadena de nombre?
2.
3. Ejercicio 0103r02.-Repetir el ejercicio anterior impidiendo la formacin
de cadenas excesivamente largas. Si es necesario, se truncar la cadena
y se avisar al usuario.
4. #include<stdio.h>
5.
6. #define DIM_NOMBRE 12
7. #define DIM_APELLIDOS 10
8.
9. int main(int argc, char *argv[])
10. {
11. char nombre[DIM_NOMBRE], apellido[DIM_APELLIDOS];
12. printf("\n\nPor favor, dgame el nombre : ");
13. fgets(nombre,sizeof(nombre),stdin);
14. /* fgets() retiene el retorno de carro, lo
descartamos */
15. nombre[strlen(nombre)-1] = '\0';
16. /* Descartamos el resto si lo hay */
17. fpurge(stdin);
18. printf("\n\nPor favor,dgame el apellido : ");
19. fgets(apellido,sizeof(apellido), stdin);
20. /* fgets() retiene el retorno de carro, lo
descartamos */
21. apellido[strlen(apellido)-1] = '\0';
22. /* Si cabe en nombre el nombre, un espacio y el
apellido, lo almacenamos */
23. if (strlen(nombre) + strlen(" ") +
strlen(apellido) < sizeof(nombre) -1)
24. {
25. strcat(nombre, " ");
26. strcat(nombre, apellido);
27. }
28. else /* Si no cabe, intentamos aadir el blanco y
lo que quepa de apellido.
29. Hay que tener en cuenta que en
nombre sobran slamente
30. sizeof(nombre) -
strlen(nombre) - 1
31. caracteres. Por tanto,
limitamos a ste nmero
32. los caracteres aadidos (mediante
strncat).
33. */
34. {
35. strncat(nombre, " ", sizeof(nombre)
- strlen(nombre)-1);
36. strncat(nombre, apellido,
sizeof(nombre) - strlen(nombre)-1);
37. printf("Resultado demasiado largo,
se ha truncado a %d caracteres.\n",
38. sizeof(nombre)-1);
39. };
40. printf("\n\nTitular: %s\n", nombre);
41. printf("\n\nFin del programa.\n\n");
42. return 0;
43. }
44.Ejercicio 0103r03.-Construir un programa que muestre mediante
strerror() los mensajes asociados a diferentes cdigos de error.
45. #include<stdio.h>
46.
47. int main(int argc, char * argv[])
48. {
49. int i;
50. char * p;
51. for(i=0;i<sys_nerr;i++)
52. printf("%d.-%s\n", i, p);
53. return 0;
}

Este programa producir resultados distintos en diferentes plataformas;


adems, cada una de ellas proporciona un nmero diferente (sys_nerr)
de mensajes de error.
54.Ejercicio 0103r04.-Construir un programa que admita dos cadenas, las
compare e indique su relacin de orden: la primera es menor que la
segunda, son iguales o la primera es mayor que la segunda (strcmp()).
55. #include<stdio.h>
56.
57. #define DIM_primera 10
58. #define DIM_segunda 15
59.
60. int main(int argc, char *argv[])
61. {
62. char primera[DIM_primera], segunda[DIM_segunda];
63. int relacion, relacion2;
64.
65. printf("\n\nPor favor, escriba la primera cadena
: ");
66. fgets(primera,sizeof(primera),stdin);
67. /* fgets() retiene el retorno de carro, lo
descartamos */
68. primera[strlen(primera)-1] = '\0';
69. /* Descartamos el resto si lo hay */
70. fpurge(stdin);
71.
72. printf("\n\nPor favor,escriba la segunda cadena :
");
73. fgets(segunda,sizeof(segunda), stdin);
74. /* fgets() retiene el retorno de carro, lo
descartamos */
75. segunda[strlen(segunda)-1] = '\0';
76.
77. relacion = strcmp(primera, segunda);
78.
79. printf("\n\nRelacin: ");
80. if (relacion > 0)
81. printf("%s es mayor que %s\n",primera,
segunda);
82. else
83. if (relacion < 0)
84. printf("%s es menor que %s\n",
primera, segunda);
85. else
86. printf("%s es igual a %s\n",
primera, segunda);
87. /*
88. Pero probemos lo que sucede
89. si slo se comparan 6 caracteres
90. */
91. relacion2 = strncmp(primera, segunda, 6);
92.
93. printf("\n\nRelacin2: ");
94. if (relacion2 > 0)
95. printf("%s es mayor que %s\n",primera,
segunda);
96. else
97. if (relacion2 < 0)
98. printf("%s es menor que %s\n",
primera, segunda);
99. else
100. printf("%s es igual a %s\n",
primera, segunda);
101. printf("\n\nFin del programa\n\n");
102. return 0;
103. }
104.
105. /*
106. El resultado de la ejecucin es como sigue:
107.
108. Por favor, escriba la primera cadena : abcdefppp
109.
110.
111. Por favor,escriba la segunda cadena : abcdefzzz
112.
113.
114. Relacin: abcdefpp es menor que abcdefzzz
115.
116.
117. Relacin2: abcdefpp es igual a abcdefzzz
118.
119. */

Como puede observarse en el resultado de la ejecucin, la funcin


strncmp() permite limitar la comparacin al principio de las cadenas,
produciendo resultados aparentemente falsos, aunque realmente sean
exactos.

120. Ejercicio 0103r05.-Se dispone de una lista de nombres y


apellidos. Se pide construir un programa que procese la lista y muestre
todos los registros que contengan una cierta palabra, bien sea como
nombre, como primer apellido o como segundo apellido (strstr()).
121. #include<stdio.h>
122.
123. #define FILAS 5
124. #define LONGITUD_CADENA 20
125. int main(int argc, char * argv[])
126. {
127. char nombre[FILAS][LONGITUD_CADENA] = { "Juan",
"Martn", "Pedro", "Luis", "Alonso"};
128. char apellido_1[FILAS][LONGITUD_CADENA] =
{"Martin", "Perez", "Garcia", "Hernandez", "Lopez"};
129. char apellido_2[FILAS][LONGITUD_CADENA] =
{"Alonso", "Gonzalez", "Martin", "Luis", "Gomez"};
130. char palabra[LONGITUD_CADENA];
131. int i;
132. printf("\n\nBsqueda de registros\n\n");
133. printf("La lista de registros es:\n\n");
134. for(i=0;i<FILAS;i++)
135. printf("%d: %s %s %s\n",
136. i,
137. nombre[i],
138. apellido_1[i],
139. apellido_2[i]);
140. printf("\n\nEscriba una palabra: ");
141. scanf("%s", palabra);
142. printf("\n\nPalabra buscada: %s\n\n", palabra);
143. for(i=0;i<FILAS;i++)
144. {
145. if(
strstr(palabra,nombre[i])!=NULL ||
146.
strstr(palabra,apellido_1[i])!=NULL ||
147.
strstr(palabra,apellido_2[i])!=NULL)
148. printf("%s figura en el registro
%d: %s %s %s\n",
149. palabra,
150. i,
151. nombre[i],
152. apellido_1[i],
153. apellido_2[i]);
154. }
155. printf("\n\nFin del programa\n\n");
156. return 0;
157. }
158. Ejercicio 0103r06.-Se dispone de una lista de registros de
formato delimitado, esto es, cuyos campos estn separados por un
carcter que no puede formar parte del campo. Se pide construir una
funcin que admita esos registros y los separe en campos, mostrando
esos campos en pantalla una vez separados (strtok()).
159. #include<stdio.h>
160.
161. #define FILAS 5
162. #define COLUMNAS 40
163. int main(int argc, char * argv[])
164. {
165. char registro[FILAS][COLUMNAS] = {
"Ana*Perez*Lopez",
166. "Bernardo*Ga
167. "Carlos*Mart
168. "Damian*Garc
169. "Elena*Gonza
170. int i;
171. char * p;
172. for(i=0;i<FILAS;i++)
173. {
174. printf("\n\nLos campos del registro
%s son:\n\n", registro[i]);
175. puts(strtok(registro[i], "*"));
176. while (p = strtok(NULL,"*"))
177. puts(p);
178. }
179. printf("\n\nFin del programa\n\n");
180. return 0;
181. }
182.

El resultado de ejecutar este programa es precisamente el deseado:


/*
Los campos del registro Ana*Perez*Lopez son:

Ana
Perez
Lopez

Los campos del registro Bernardo*Garcia*Gonzalez son:

Bernardo

Introduccin

Vamos ahora a ver cmo manejar texto con C. Para empezar, es preciso decir que
existe un tipo string como en otros lenguajes, pero no existe un tipo de datos
especfico para almacenar texto, sino que se utilizan arrays de char. Funcionan
igual que los dems arrays con la diferencia de que ahora se manejan letras en
vez de nmeros. Se les llama cadenas, strings o tiras de caracteres y a partir de
ahora les llamaremos cadenas.

Para declarar una cadena se hace como en el caso de un array. Por ejemplo, si
queremos declarar una cadena de longitud 20 caracteres se hara:
char texto[20];

Al igual que en los arrays, no podemos entonces introducir ms de 20 elementos


en la cadena. Vamos a ver un ejemplo para mostrar el nombre del usuario en
pantalla:

#include <stdio.h>

main()
{
char nombre[20];

printf( "Introduzca su nombre (20 letras mximo): " );


scanf( "%s", nombre );
printf( "\nEl nombre que ha escrito es: %s\n", nombre );
}
Obsrvese que en la sentencia scanf no se usa el smbolo & delante de nombre. No
hace falta porque se trata de un array, de modo que escribir el nombre
delarray es equivalente a poner &nombre[0].

Tambin puede llamar la atencin sobre la forma de imprimir el array. Con slo
usar %s ya se imprime su totalidad. Ya veremos esto ms adelante.

Por si alguien est acostumbrado a programar en otro lenguaje es preciso hacer


notar que en C no se puede hacer esto:

#include <stdio.h>

main()
{
char texto[20];

texto = "Hola";
}

Es interesante saber cmo funciona una cadena por dentro, por eso vamos a ver
primero cmo se inicializa:

#include <stdio.h>

main()
{
char nombre[] = "Gandalf";

printf( "Texto: %s\n", nombre );


printf( "Tamao de la cadena: %i bytes\n", sizeof nombre );
}

Resultado al ejecutar:

Texto: Gandalf
Tamao de la cadena: 8 bytes

Curiosamente la respuesta nos dice que "Gandalf" ocupa 8 bytes. Como cada
elemento char ocupa un byte eso quiere decir que la cadena tiene 8 elementos, a
pesar de que "Gandalf" slo cuenta con 7 letras. La razn de esta aparente
paradoja estriba en que la cadena tiene como carcter final el smbolo '\0', cuyo
significado es "fin de cadena". De esta forma, cuando queremos escribir la
cadena basta con usar %s y el compilador sabe cuntos elementos debe escribir:
hasta que encuentre '\0'.

El programa anterior sera equivalente a:


#include <stdio.h>

main()
{
char nombre[] = { 'G', 'a', 'n', 'd', 'a', 'l', 'f', '\0' };

printf( "Texto: %s\n", nombre );


printf( "Tamao de la cadena: %i bytes\n", sizeof nombre );
}

Aqu ya se observa claramente que nombre tiene 8 elementos. Pero, qu pasara


si no pusiramos '\0' al final?

#include <stdio.h>

main()
{
char nombre[] = { 'G', 'a', 'n', 'd', 'a', 'l', 'f' };

printf( "Texto: %s\n", nombre );


printf( "Tamao de la cadena: %i bytes\n", sizeof nombre );
}

En mi ordenador se obtiene:

Texto: Gandalf-

Tamao de la cadena: 7 bytes

Pero en otro despus de "Gandalf" puede aparecer cualquier cosa. Lo que aqu
sucede es que printf no encuentra el smbolo '\0' y no sabe cundo dejar de
imprimir. Afortunadamente, cuando introducimos una cadena se hace de la
primera forma y el C se encarga de poner el smbolo al final.

Es importante no olvidar que la longitud de una cadena es la longitud del texto


ms el smbolo de fin de cadena. Por eso cuando definamos una cadena tenemos
que reservarle un espacio adicional. Por ejemplo:
char nombre[8] = "Gandalf";

Funciones de manejo de cadenas


Existen unas cuantas funciones el la biblioteca estndar de C para el manejo de
cadenas:

strlen
strcpy
strcat
sprintf
strcmp

Para usar estas funciones en nuestro programa hay que aadir la directiva:

#include <string.h>

strlen
size_t *strlen(const char *cadena);

Esta funcin devuelve el nmero de caracteres que tiene la cadena (sin contar
el '\0').

#include <stdio.h>
#include <string.h>

main()
{
char texto[]="Gandalf";
int longitud;
longitud = strlen(texto);
printf( "La cadena \"%s\" tiene %i caracteres.\n", texto,
longitud );
}

Como ejemplo, vamos a ver cmo se programara esta funcin si no


dispusiramos de ella. Hay ms informacin en Recorrido de cadenas con
punteros.

#include <stdio.h>
#include <string.h>

main()
{
char texto[]="Gandalf";
char *p;
int longitud=0;

p = texto;
while (*p != '\0') {
longitud++;
printf( "%c\n", *p ); /* Mostramos la letra actual */
p++; /* Vamos a la siguiente letra
*/
}
printf( "La cadena \"%s\" tiene %i caracteres.\n", texto,
longitud );
}

Para medir la longitud de la cadena usamos un puntero para recorrerla (el


puntero p). Hacemos que p apunte a texto. Luego entramos en un bucle while. La
condicin del bucle comprueba si se ha llegado al fin de cadena ('\0'). Si no es
as, suma 1 a longitud, muestra la letra por pantalla e incrementa el puntero en 1
(con lo que pasamos a la siguiente letra).

strcpy
char *strcpy(char *cadena1, const char *cadena2);

Copia el contenido de cadena2 en cadena1. cadena2 puede ser una variable o una
cadena directa (por ejemplo, "hola"). Debemos tener cuidado de que la cadena
destino (cadena1) tenga espacio suficiente para albergar a la cadena origen
(cadena2).

#include <stdio.h>
#include <string.h>

main()
{
char texto[] = "ste es un curso de C.";
char destino[50];

strcpy( destino, texto );


printf( "Valor final: %s\n", destino );
}

Vamos a ver otro ejemplo en el que la cadena destino es una cadena constante
("ste es un curso de C.") y no una variable. Adems, en este ejemplo vemos que
la cadena origen es sustituida por la cadena destino totalmente. Si la cadena
origen es ms larga que la destino, se eliminan las letras adicionales.

#include <stdio.h>
#include <string.h>

main()
{
char destino[50]="ste no es un curso de HTML, sino de C.";

printf( "%s\n", destino );


strcpy( destino, "ste es un curso de C." );
printf( "%s\n", destino );
}

strcat
char *strcat(char *cadena1, const char *cadena2);

Aade la cadena2 al final de la cadena1 (concatena).

#include <stdio.h>
#include <string.h>

main()
{
char nombre_completo[50];
char nombre[]="Gandalf";
char apellido[]="el Gris";

strcpy( nombre_completo, nombre );


strcat( nombre_completo, " " );
strcat( nombre_completo, apellido );
printf( "El nombre completo es: %s.\n", nombre_completo );
}

Como siempre, tenemos asegurar que la variable en la que aadimos las dems
cadenas tenga el tamao suficiente. Con la primera lnea de este programa
introducimos el nombre en nombre_completo. Usamos strcpy para asegurarnos de
que queda borrado cualquier dato anterior. Luego usamos un strcat para aadir
un espacio y, finalmente, introducimos el apellido.

sprintf
int sprintf(char *destino, const char *format, ...);

Funciona de manera similar a printf pero, en vez de mostrar el texto en la


pantalla, lo guarda en una variable (destino). El valor que devuelve (int) es el
nmero de caracteres guardados en la variable destino.

Con sprintf podemos repetir el ejemplo de strcat de manera ms sencilla:

#include <stdio.h>
#include <string.h>

main()
{
char nombre_completo[50];
char nombre[]="Gandalf";
char apellido[]="el Gris";

sprintf( nombre_completo, "%s %s", nombre, apellido );


printf( "El nombre completo es: %s.\n", nombre_completo );
}

Se puede aplicar a sprintf todo lo indicado para printf.

strcmp
int strcmp(const char *cadena1, const char *cadena2);

Compara cadena1 y cadena2. Si son iguales, devuelve 0. Un nmero negativo


si cadena1 "va" antes que cadena2, y un nmero positivo si es al contrario:

< 0 si cadena1 < cadena2


==0 si cadena1 == cadena2
> 0 si cadena1 > cadena2

#include <stdio.h>
#include <string.h>

main()
{
char nombre1[]="Gandalf";
char nombre2[]="Frodo";

printf( "Comparacin con strcmp: %i\n",


strcmp(nombre1,nombre2));
}

El resultado es:

Comparacin con strcmp : 1

Arrays de cadenas

Un array de cadenas puede servirnos para agrupar una serie de mensajes. Por
ejemplo, todos los mensajes de error de un programa. Luego, para acceder a cada
mensaje, basta con usar su nmero.
#include <stdio.h>
#include <string.h>

int error( int num_err )


{
char *errores[] = {
"No se ha producido ningn error",
"No hay suficiente memoria",
"No hay espacio en disco",
"Me he cansado de trabajar"
};

printf( "Error nmero %i: %s.\n", num_err, errores[num_err] );


exit( -1 );
}

main()
{
error( 2 );
}

El resultado ser:

Error nmero 2: No hay espacio en disco.

Un array de cadenas es en realidad un array de punteros a cadenas. El primer


elemento de la cadena ("No se ha producido ningn error") tiene un espacio
reservado en memoria y errores[0] apunta a ese espacio.

o Ordenacin de un array de cadenas

Vamos a ver un sencillo ejemplo de ordenacin de cadenas. En el ejemplo


siguiente tenemos que ordenar una serie de dichos populares:

#include <stdio.h>
#include <string.h>

#define ELEMENTOS 5

main()
{
char *dichos[ELEMENTOS] = {
"La avaricia rompe el saco",
"Ms vale pjaro en mano que ciento volando",
"No por mucho madrugar amanece ms temprano",
"Ao de nieves, ao de bienes",
"A caballo regalado no le mires el diente"
};
char *temp;
int i, j;
printf( "Lista desordenada:\n" );
for( i=0; i<ELEMENTOS; i++ )
printf( " %s.\n", dichos[i] );

for( i=0; i<ELEMENTOS-1; i++ )


for( j=i+1; j<ELEMENTOS; j++ )
if ( strcmp(dichos[i], dichos[j]) > 0 ) {
temp = dichos[i];
dichos[i] = dichos[j];
dichos[j] = temp;
}

printf( "Lista ordenada:\n" );


for( i=0; i<ELEMENTOS; i++ )
printf( " %s.\n", dichos[i] );
}

Cmo funciona el programa:

tomamos el primer elemento de la matriz. Lo comparamos con todos los


siguientes. Si alguno es anterior, los intercambiamos. Cuando acabe esta
primera vuelta tendremos "A caballo regalado no le mires el diente" en
primera posicin.
Tomamos el segundo elemento. Lo comparamos con el tercero y
siguientes. Si alguno es anterior, los intercambiamos. Al final de esta
vuelta quedar "A caballo regalado no le mires el diente" en segunda
posicin.

Para ver con mayor claridad el resultado a partir del desarrollo del proceso, se va
a sustituir cada cadena por su primera letra (menos la de "Ao de nieves..." que
se sustituir por A). As, el proceso queda:
0 1 2 3 3' 4 4' 5 6 6' 7 7' 8 8'
9 9' 10 10'
1 L L L L A A A
2 M M M M M M M M M L L A
3 N N N N N N N N N N N N N M
M L
4 A A A A L L L L L M M M M N
N N N M
5 A A A A A A A A A A A L L L
L M M N

Recorrido de cadenas con punteros


Las cadenas se pueden recorrer de igual forma que se hace con los arrays, usando
punteros. Vamos a ver un ejemplo: el siguiente sencillo programa cuenta los
espacios y las letras e (minsculas) que hay en una cadena.

#include <stdio.h>
#include <string.h>

main()
{
char cadena[]="El puerto paralelo del PC";
char *p;
int espacios = 0, letras_e = 0;

p = cadena;
while (*p != '\0') {
if (*p == ' ') espacios++;
if (*p == 'e') letras_e++;
p++;
}

printf( "En la cadena \"%s\" hay:\n", cadena );


printf( " %i espacios\n", espacios );
printf( " %i letras e\n", letras_e );
}

El resultado es:

En la cadena "El puerto paralelo del PC" hay:


4 espacios
3 letras e

Para recorrer la cadena necesitamos un puntero p que sea de tipo char. Debemos
hacer que p apunte a la cadena (p=cadena). As, p apunta a la direccin del primer
elemento de la misma. El valor de *p sera, por tanto, 'E'. Comenzamos el bucle.
La condicin comprueba que no se ha llegado al final de la cadena (*p != '\0').
Entonces se comprueba si en la direccin a la que apunta p hay un espacio o una
letra e. Si es as, se incrementan las variables correspondientes. Una vez
comprobado esto se pasa a la siguiente letra (p++).

En este otro ejemplo substituimos los espacios por guiones:

#include <stdio.h>
#include <string.h>

main()
{
char cadena[]="El puerto paralelo del PC";
char *p;

p = cadena;
while (*p != '\0') {
if (*p == ' ') *p = '-';
p++;
}

printf( "La cadena queda: \"%s\" \n", cadena );


}

y se obtiene:

También podría gustarte