Академический Документы
Профессиональный Документы
Культура Документы
Programacin en C/C++
Solai Jeyakumar
ndice
1. Bsicos de las computadoras
1.1. 1.2. 1.3. 1.4. 1.5. Que es una computadora? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programacin y estructura de la memoria
3
3 3 5 6 6
2. Introduccin a la programacin en C
2.1. 2.2. 2.3. 2.4. 2.5. 2.6. Un programa bsico en C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variables, Tipos de Datos y Printf
9
9 10 12 14 15 17
Char, Cadena en la memoria y Apuntador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Leyendo del teclado, scanf...... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . short, int, long, oat y double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . operadores numerical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
20 24 28 30
31 33
33 33 34
34 36 36
36 38 40 41 44 44
* Web
page:http://www.astro.ugto.mx/~sjk/course/programming/index.html
9. Strucut, Union 10.Lectura y escritura de archivos 11.Operaciones con Cadenas 12.Preprocesador & Macros 13.Cambiar de C a C++ 14.Programacin orientada a objetos: C++ 15.Conceptos avanzados en C++ 16.Librario de estndar templates (STL)
50 50 50 50 50 50 50 50
Disk
System Bus
Keyboard
Mouse CPU
Memory
Trabajo : Cmo hacer la cena? Instruccin A: Traiga el pan del edicio 1 al edicio 3. Instruccin B: Traiga el queso del edicio 2 al edicio 3. Instruccin C: Cocine el pan y el queso en el edicio 3. Instruccin D: Mueva el alimento cocido desde el edicio 3 al edicio 4. Instruccin E:
Instruccin F: Hable Buen provecho! Ahora referimos a los edicios por su direccin 1, 2, 3, etc. Los instrucciones como A, B, C, D, E, etc., Las instrucciones
ordenan, el contenido de los edicios que se cambiarn. Ahora organizaremos las instrucciones antedichas
Traiga *(edicio 1) al edicio 3. Traiga *(edicio 2) al edicio 3. Cocine el pan y el queso en el edicio 3. Mueva resultado al edicio 4.
Cuadro 1: Un programa del ejemplo que demuestra el concepto de programacin y su relacin a la estructura de la memoria
En el ejemplo antedicho el Edicio 1, 2, 3, etc., y los Instrucciones A, B, C, D, etc., son direcciones a las instrucciones o a los muebles. El contenido en esas direcciones es o
direcciones desde Edicio 1 hasta Instruccin-A tienen muebles o datos y desde de Instruccin-A tienen commandos.
Primero commado en el direccin Instruccin-A, dice traiga el contenido del direccin edicio-1 (expresado como *(edicio 1)) al edicio3.
Secundo commando en el direccin Instruccin-B, dice traiga el contendio del direccin edicio-2 (expresando como *(edicio 2) ) al edicio 3. Tercero commando en el direccin Instruccn-C, dice cocine el pan y el queso en el edicio 3. El pan y el queso se trean al edicio-3 usando commandos previos.
Como se ha explicado arriba, programacin es arreglar los commandos en sequencia para realizar un trabajo. Los commandos a un punto, dependen los resultados de los commandos que han realizado antes. Tambin un programa depende de los datos los cuales son descrito junto con los commandos. En las computadoras un programa se arregla en la memoria en una manera similar. Cada posicin de memoria tiene una direccin y un espacio para tener algn contenido. El contenido puede ser o datos o las instrucciones sobre cmo manipular los datos.
Memory
Figura 2: El CPU y un programa ejecutable
Un programa es un software que contiene instrucciones sobre cmo a hacer un trabajo unsando el CPU. El CPU empieza con la primera instruccin del programa y se ejecuta hasta el extremo. Un programa tiene instrucciones y datos. Se ejecutan las instrucciones usando el CPU y esas instrucciones manipulan los datos (demostrado en gura 2). La primera direccin de un programa llega al Registro del Apuntador de Instrucciones llamado EIP.
El registro ESP tiene la direccin del almacenamiento. El procesador ejecuta cada instruccin desde del punto de partida del programa hasta el extremo. El stack es una unidad del almacenamiento temporal en la memoria para almacenar valores durante la ejecucin del programa. Los clculos son hechos por los registros EAX, EBX, ECX, etc. Un programa de ejemplo se da en gura 3.
AND OR NOT DEC MOV PUSH POP ADD DIV CMP MUL
El nmero de instrucciones vara entre los procesadores. Hay cerca de 150 instrucciones y cerca de 32 instrucciones de salto condicionales.
La instruccin 4 en la posicin de memoria 0x0003 multiplica el contenido de la memoria 0x000B con el contenido del registro EAX. La instruccin 5 en la posicin de memoria 0x0004 mueve el resultado del regsiter EAX a la posicin de memoria 0x000C. La instruccin 6 dice terminar el programa.
Direccin
0x0000 0x0001 0x0002 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 0x000A 0x000B 0x000C 0x000D
Contenido
MOV, 5, 0x000A MOV, 3, 0x000B MOV, (0x000A), EAX MUL, (0x000B), EAX MOV,EAX, 0x000C END
Comentarios
Mueva 5 a la memoria 0x000A Mueva 3 a la memoria 0x000B Mueva el contenido de la memoria 0x000A al EAX Multiplica el contenido de la memoria 0x000B con EAX Mueva contenido de EAX a la memoria 0x000C Termino
Direccin
0x0000 0x0001 0x0002 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 0x000A 0x000B 0x000C 0x000D
Contenido
MOV, 5, EBX MOV, 1, EAX MUL, EBX, EAX DEC, EBX MUL, EBX, EAX DEC, EBX MUL, EBX, EAX DEC, EBX MUL, EBX, EAX DEC, EBX MUL, EBX, EAX MOV, EAX, 0x000D END
Comentarios
Mueva 5 al registro EBX Mueva 1 al registro Multiplica contenido de EBX con contendio de EAX Decremento EBX. (Ahora ECX es 4) Multiplica contenido de EBX con contendio de EAX Decremento EBX (Ahora ECX es 3) Multiplica contenido de EBX con contendio de EAX Decremento EBX (Ahora ECX es 2) Multiplica contenido de EBX con contendio de EAX Decremento EBX (Ahora ECX es 1) Multiplica contenido de EBX con contendio de EAX Mueva el resultado a la memoria 0x000D Termino Espacio para el resultado
Los lenguajes de alto nivel, tales como C y C++ simplican los clculos demostrados en los ejemplos antedichos. No tienen que escribir un programa en una manera tan complicada de multiplicar dos nmeros (como en el ejemplo 1). Por ejemplo programa de ejemplo 1 pude ser convertido a un lenguaje de alto nivel imaginario, como sigue: EMBIEZA Variable_de_numero_A = Variable_de_numbero_B = Variable_de_resultado TERMINO Si tenemos un 5 ; 3;
= Variable_de_numero_A
Variable_de_numero_B;
programa espacial para convertir el programa arriba a un programa de ensamblaje, podemos programa espacial se llama un compilador. Sin embargo, los lenguajes
escribir los programas facilmente mediante el lenguaje de alto nivel imaginario. Los lenguajes de alto nivel son similar al que se demuestra arriba. El de alto nivel tales como C y C++ tambin proporcionan el acceso a la memoria y la manipulacin de la memoria similar a la manera demostrada arriba.
2. Introduccin a la programacin en C
La computadora puede ejecutar solamente programas ejecutables. Para crear un programa ejecutable de una lenguaje de alto nivel, necesitamos un programa llamado compilador . El proceso de crear un programa ejecutable de lenguajes de alto nivel es como sigue: PROGRAMA ->COMPILER ->PROGRAMA EJECUTABLE Hemos aprendido sobre la estructura del programa ejecutable, cmo se ejecuta un programa y cmo se utilizan los comandos bsicos de la asamblea para crear programas simples. Sin embargo, es ms fcil para utilizar un lenguaje de alto nivel para escribir programas complicados. Cmo ayuda un lenguaje de alto nivel, a escribir un programa complicado?. Esto se alcanza usando las estructuras de alto nivel en un lenguaje para crear un programa ejecutable. Diversos lenguajes proporcionan diversas estructuras de alto nivel. Sin embargo hay algunas estructuras comunes entre lenguajes. Sin embargo, en C es tambin posible utilizar comandos bsicos de la ensamblaje y tambin otras estructuras para hacer las operaciones bsicas que son posibles con lenguaje ensamblador.
main()
int main().
ms adelante. Ahora las lneas entre los simbolos { y } describen el trabajo particular que deseamos hacer. En este ejemplo el programa imprime la lnea siguiente:
Hello World
Este trabajo particular es hecho por la lnea,
printf(Hello World\n);
Esta lnea pide a la computadora imprimir lo que est dentro de las comillas. Cada lnea o un sistema de lneas que terminan con el smbolo ; es una sentencia en C. En el ejemplo anterior tambin podramos escribir
printf(
);
Hello World\n
#include <stdio.h> int main() { /* Este es un comentario */ printf(Hello World\n); /* Este tambin es un comentario */ return 0; }
En este programa las palabras o lineas dentro los simbolos /* y */ se llaman comentarios. No se hace caso a estas lneas mientras se ejecuta el programa. Estas lneas son ignoradas por el compilador. Este programa tambin imprimir lo siguiente:
Hello World
En el ejemplo arriba hemos introducido los nuevos conceptos llamados para imprimir. Aqu la variable es i y el
La cadena del formato contiene muchos formatos y tambien cadenas tal como:
La tabla 3 muestra todos los tipos de datos y sus formatos. Hay otros tipos de formatos que se llaman formatos especiales, tales como \n , \t, \f y \r. Cul es el uso de estos formatos? Por ejemplo, en el programa siguente:
#include <stdio.h>
10
TIPO DE DATO void char signed char short unsigned short init unsigned int long unsigned long long long unsigned long long oat double long double (pointer)
TAMAO (BYTES) 0
%c %c %d %d, %u %d %d, %u %ld %lu %ld %lu %f, %e, %g %f, %e, %g %f, %e, %g %p
1 1 2 2 4 4 4 4 8 8 4 8 8 4
Cuadro 3: Una tabla de tipos de datos, cadena del formato y tamao de las variables
Palabra1,
en la miso lnea. La sentencia de printf que sigue imprimir desde la ubicacin del cursor. Despus de ejecutar el
Palabra1Palabra2
Usamos un formato especial \n para volver el cursor a una lnea nueva. Por ejemplo, el programa siguiente
Palabra1 Palabra2
El formato \f introducir una operacin, form-feed , o de otra manera, imprimir el texto que sigue el formato en un lnea nueva, pero empezar de la localizacin actual del cursor (no del principio de la lnea). El formato \r traer el cursor al principio de la misma lnea y sobreescribir los caracteres en lnea existente. La manera fcil de entender es que el formato \n es realmente \f \r.
11
#include <stdio.h> int main() { char str[12] = Hello World ; printf( %s\n, str); return 0; }
Cuando ejecuta, este programa se imprime siguiente:
Hello World
En el ejemplo arriba hemos introducido el nuevo tipo de dato se llama char.
str[12]
contiene 12 caracteres indivios. La gura 5 muestra cmo esta cadena reside en memora. En este ejemplo la cadena tiene 11 caracteres, pero hemos escrito como en el programa arriba como char str[12]. Es necesario un carcter ms para decir a la computatodra donde terminar la cadena. Este carcter ultimo es '\0' o entero cero. Cuando esta cadena se imprime, el ultimo carcter (\0) se ignora.
Direccin
0x0000 0x0001 0x0002 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 0x000A 0x000B 0x000C 0x000D W O R L D \0 H E L L O
Contenido
12
Los direcciones desde de 0x0000 hasta 0x000B contiene esta cadena. A la izquierda de la tabla se dan los nombres de las variables para referier a las direcciones. A la derecha de la tabla se dan los nombres de las variables para acceder cada unos de los caracteres (o contenido de las direcciones). Para imprimir solamente un carcter, por ejemplo segundo carcter e, usamos
&str[1] con un & en frente, se llama un apuntador. Un variable especial es, str, &str[0]. Aprendamos ms sobre este tipo de variable que contiene un carcter &. Toma un
#include <stdio.h> int main() { char Nom[6] = CO ; int NumLit ; char HayC ; int PesoMol ; int NumAtom ; NumAtom = 2 ; PesoMol = 28 ; HayC = S ; NumLit = 45 ; printf(Nombre: %s\n, Nom ); printf(Apuntador de la memoria de la variable Nom: %d\n, &Nom[0] ); printf(Numero_Atom %d\n, NumAtom); printf(Apuntador de la memoria de la variable NumAtom %d\n, &NumAtom); printf(Hay C? %c\n, HayC); printf(Nombre %s\n, Nom); } return 0;
La gura 6 muestra un ejemplo de estructura de la memoria que contiene de los datos del programa arriba.
En este programa, hemos introducido un variable HayC que tiene solomente un carcter. Asignamos un carcter a este variable como
HayC = S.
llamado el ASCII (American Standard Code for Information Interchange). Prcticamente nmero entero entre 0 y 127. Hay diferencia entre las asignaciones siguientes:
13
Direccin
0x0000 0x0001 2
Contenido
&PesoMol
0x0002 0x0003
28
PesoMol
&HayC &NumLit
S 45
HayC NumLit
&Nom[0] / Nom
C O
Nom[0]
&Nom[5]
0x000C 0x000D
\0
Nom[5]
VarCharA = 8 ; /* VarCharA contiene un codigo de ASCII, no es carcter 8) */ VarCharB = 8 ; /* VarCharB contiene un carcter 8 */ } return 0;
digamos que deseamos leer un valor dado del teclado, para el variable PesoMol. Cuando un nmero se presiona en el teclado, la funcin de la lectura (scanf ) copia ese valor a la posicin de memoria del PesoMol. Entonces el proceso de la lectura est: copiar la entrada del teclado al &PesoMol. As, es necesario proporcionar la direccin de la memoria de una variable, a la funcin de la lecturea. Similar a printf es tambin necesario dar el formato de los datos que deseamos leer. En el ejemplo antedicho l un nmero entero. Se escribe el programa de la lectura como sigue:
return 0;
Observe que proporcionamos el apuntador a la variable. Tambin, no se utiliza del formato especial \n. Ahora escribimos otro programa para leer dos variables, como sigue:
En este ejemplo, leemos primero un entero a un variable PesoMol, y segundo un carcter a un variable HayC. Supongamos que deseamos entrar un nmero 8 y un cracter N. Entonces necesitamos presionar lo siguiente en el teclado:
N 8
Observar el espacio entre 8 y el N. Esto se requiere, puesto que, dentro del formato arriba hay un espacio entre %d y %c. Supongamos que escribimos el scanf as:
En este ejemplo leemos un cadena desde teclado usando formato %s, y la direccin de la memora donde empieza la cadena str. Este ejemplo no puede leer una cadena con espacios. Aprenderemos ms sobre cmo leer un cadena con espacios adelante.
short, int y long son tipos que specican que los variables de este tipo puede contener un valor de nmero entero. float
y
double
son nmeros que contiene un punto decimal, por ejemplo 8.4, 123.8904,
Un variable de estos tipos tambin puede tomar valores negativos. Los formatos para imprimir las variables de estos tipos son dados en tabla 3. Los tipos short, int y long tienen tipos contrapartes llamado
unsigned int
unsigned long
unsigned short,
los cuales no pueden tomar valores nagtivos. Para imprimir los variables con es-
tos tipos usamos %u en lugar de %d o %i. Aqu hay un programa de ejemplo para imprimir los variables de este tipos.
short VarShort ; unsigned short VarUsShort; int VarInt ; unsigned int VarUsInt ; long VarLong ; unsigned long VarUsLong ; VarShort = printf("Es VarShort = printf("Es VarUsShort printf("Es VarUsShort printf("Es 11 ; un short positivo -10 ; un short negativo = 11 ; un unsigned short = -10 ; un unsigned short imprimado con % %d= %d\n", VarShort); imprimado con % %d= %d\n", VarShort); positivo imprimado con % %u= %u\n", VarUsShort); negativo imprimado con % %u= %u\n", VarUsShort);
printf("\n"); VarInt = 21 ; printf("Es un int positivo VarInt = -22 ; printf("Es un int negativo VarUsInt = 21 ; printf("Es un unsigned int VarUsInt = -22 ; printf("Es un unsigned int printf("\n"); VarLong = 31 ; printf("Es un long positivo VarLong = -32 ; printf("Es un long negativo VarUsLong = 31 ; printf("Es un unsigned long VarUsLong = -32 ; printf("Es un unsigned long return 0; }
La salida de este ejemplo es como sigue:
imprimado con % %d= %d\n", VarInt); imprimado con % %d= %d\n", VarInt); positivo imprimado con % %u= %u\n", VarUsInt); negativo imprimado con % %u= %u\n", VarUsInt);
imprimado con % %ld= %ld\n", VarLong); imprimado con % %ld= %ld\n", VarLong); positivo imprimado con % %lu= %lu\n", VarUsLong); negativo imprimado con % %lu= %lu\n", VarUsLong);
Es Es Es Es Es Es Es Es Es Es Es Es
un un un un un un un un un un un un
short positivo imprimado con %d= 11 short negativo imprimado con %d= -10 unsigned short positivo imprimado con %u= 11 unsigned short negativo imprimado con %u= 65526 int positivo imprimado con %d= 21 int negativo imprimado con %d= -22 unsigned int positivo imprimado con %u= 21 unsigned int negativo imprimado con %u= 4294967274 long positivo imprimado con %ld= 31 long negativo imprimado con %ld= -32 unsigned long positivo imprimado con %lu= 31 unsigned long negativo imprimado con %lu= 18446744073709551584
16
Como vemos, los variables, unsigned no pueden contenir un valor negativo. Para imprimir variables de tipos oat y double usamos los formatos %f (con un punto decimal), %e (notacin scientica), %g (para dejar la computadora tomar un decisin sobre %f o %e). En todos los formatos arriba podemos usar un tamao para dar la precision que queremos despus de punto decimal y tamao total. Por ejemplo un formato, %15.4f, signica que queremos 4 digitos despues de punto decimal. Tomamos el ejemplo siguiente, para imprimir los valores 1.5 y
1,5 1012
#include <stdio.h> int main() { float VarFloat ; double VarDouble ; VarFloat = 1.5; VarDouble = 1.5; printf("Es printf("Es printf("Es printf("Es un un un un float imprimido usando % %e = %e \n", VarFloat); float imprimido usando % %f = %f \n", VarFloat); double imprimido usando % %e = %e \n", VarDouble); double imprimido usando % %f = %f \n", VarDouble);
VarFloat = 1.5E-12; printf("Es printf("Es printf("Es printf("Es return 0; } un un un un float float float float imprimido imprimido imprimido imprimido usando % %e = %e \n", VarFloat); usando % %f = %f \n", VarFloat); usando % %16.13f = %16.13f \n", VarFloat); usando % %19.13e = %19.13e \n", VarFloat);
Es Es Es Es Es Es Es Es
un un un un un un un un
float imprimido usando %e = 1.500000e+00 float imprimido usando %f = 1.500000 double imprimido usando %e = 1.500000e+00 double imprimido usando %f = 1.500000 float imprimido usando %e = 1.500000e-12 float imprimido usando %f = 0.000000 float imprimido usando %16.13f = 0.0000000000015 float imprimido usando %19.13e = 1.4999999940063e-12
Cuando imprimimos el valor 1.5E-12 usando %f, este se imprime como 0.000000. Este no signica un error, sino dependcia de la precisin
/, para divisin. El operador, %, es llamado modulo operador, el cual da el resto de divisin de un entero por otro entero. Por ejemplo 5 %3 es igual a 2, y 5 %5 es igual a 0. Todos los operadors se dan en tabla 4
Por ejemplo, escribimos un programa para calcular la formula siguiente para un valor de x:
3x 2
17
Operador
Ejemplo Asignacin
Descripcin
A=B A+B A-B A*B A/B A %B *A A <B A >B A <= B A >= B A == B A != B A && B A || B ! A A += B A -= B A *= B A /= B A %= B A++ A
A se asignado con B?? Numerical A addicin B A menos B A multiplicado por B A por B Resto de A/B Valor que se apunta por A Condicional 1 si A<B; o 0 1 si A>B; o 0 1 si A<=B; o 0 1 si A>=B; o 0 1 si A igual a B; o 0 1 si A no igual a B; o 0 Logical 1 si A y B son ciertas; o 0 1 si A o B es cierta; o 0 1 si A es 0; o 0 Complex A = A + B A = A-B A = A*B A= A/B A = A %B incrementa A por 1 decrementa A por 1
Cuadro 4: Operadores
4*x + 3*x/2;
return 0 ; }
Valor f = %f \n, x, f );
Tambin podemos calcular la valor de, f, usando lineas multiples como sigue
18
f = (5+3*x) / (3+2*x); f = f
4*x ;
return 0 ; }
El operador
f=f4*x,
se pude escribir
f = 4*x.
es un operador complejo que signica que primero substraiga el valor derecho con la variable iz-
quierda, despes asigna el resultado a variable derecha. El mismo programa se puede escribir usando los operadores complejos como sigue:
4*x ;
return 0 ; }
#include <stdio.h> int main() { int vari ; int varj; vari = 5 ; varj = 7 ; printf( Valor vari= %d \n, vari); printf( Valor varj= %d \n, varj); return 0 ; }
Este programa comienza con int int
vari;
main(). Entonces el indicador de ujo apunta a la lnea siguiente la cual es varj;, entonces vari = 5; , entonces varj=7; De esta manera alcanza
19
el nal del programa que es }. Hay dos sentencias para imprimir los variables se queremos imprimir la variable utilizamos los sentencias de control del lenguaje-C.
vari y varj. Supongamos que no varj, cuando esta variable es menor que 100. Cmo alcanzaremos eso? Para esto
#include <stdio.h> int main() { int vari ; int varj; vari = 5 ; varj = 7 ; printf( Valor vari= %d \n, vari); if ( varj <100 ) { printf( Valor varj= %d \n, varj); } return 0 ; }
Hemos escrito la sentencia que imprime la variable varj dentro de los simboles { y }. Todas las lneas dentro de un conjunto de llaves se llama un bloque. En este case el bloque es como sigue:
{ }
La sentencia
if ( varj <100 )
varj
es menor que
100 ejecuta el bloque que sigue. El prototipo de sentencia de if es como sigue: if ( condicin ) { sentencias en C; } Puesto que el bloque sigue el condicin de if , llamamos como bloque-if. Un condicin tiene dos salidas posibles. Uno es condicin es
cierta , y otro es falso . Por ejemplo un condicin como Es varj menor que 100?
o falso dependiente de valor de varj. Para tomar tan desiciones usamos los operadores de condicional. Vea tabla 4 para una lista de los operadores. El bloque-if se ejecuta cuando esta condicn es ta lista. Por ejemplo para imprimir la variable vari cuando vari es menor o igual a 13 usamos un programa como sigue:
20
vari = 5 ; varj = 7 ; if ( vari <= 13 ) { printf( Valor vari= %d \n, vari); } if ( varj <100 ) { printf( Valor varj= %d \n, varj); } return 0 ; }
#include <stdio.h> int main() { char Varc; Varc = 'e'; if ( Varc == 'e' ) { printf( Varc= %c es un vocal\n, Varc); } return 0 ; }
En este programa inicializamos un variable
Varc como 'e'. Usamos un condicin, Varc == 'e' . Nota el operador, Varc == 'e'
no es cierta sino falsa. En
==, cual signica que Est Varc igual a 'e' ?. Cuando Varc est igual a 'e' el bloque-if se ejecuta. Qu pasa cuando Varc no est el vocal 'e' ?. Es decir, que pasa cuando la condicin usando else . Tomemos un ejemplo como sigue: este ejemplo arriba, el programa terminar. Pero es posible ejecutar otro bloque cuando un condicin est falso,
#include <stdio.h> int main() { char Varc; Varc = 'a'; if ( Varc == 'e' ) { printf( Varc= %c es un vocal\n, Varc); } else {
21
} return 0 ; }
no es 'e'
.
#include <stdio.h> int main() { char Varc; Varc = 'a'; if ( Varc == 'a' ) { printf( Varc= %c es un } else if ( Varc == 'e' ) { printf( Varc= %c es un } else if ( Varc == 'i' ) { printf( Varc= %c es un } else if ( Varc == 'o' ) { printf( Varc= %c es un } else if ( Varc == 'u' ) { printf( Varc= %c es un } else { printf( Varc= %c NO es } return 0 ; }
En este ejemplo cuando el condicin
vocal\n, Varc);
vocal\n, Varc);
vocal\n, Varc);
vocal\n, Varc);
vocal\n, Varc);
un vocal\n, Varc);
Varc == 'a'
terminar el programa. Pero cuando este condicin es falso, el indicador de ujo mover al bloque-else que sigue. Pero este bloque-else tiene ms otro condicin el bloque-else-if que sigue y terminar el programa. Cuando este condicin es falso el indicador de ujo mover a siguiente bloque-else-if que contiene un condicin
Varc == 'e'. Cuando este condicin es cierta el programa se ejecuta Varc == 'i',
y as sucesivamente.
22
IV. switch
El ejemplo arriba hace muchos condiciones de valor de un variable, como, es un variable (Varc), 'a', o, 'e', o, 'i', o 'u' ?. Para eso, usamos muchos condiciones de if, o if..else... o if...else if.... else if....... etc. Es posible hacer este tipo de condiciones multiples en un variable usando mecanisimo de switch. Por ejemplo, para vericar, si un variable de char est igual a el vocal 'a', o, 'e', o no, escribimos un programa come sigue:
#include <stdio.h> int main() { char Varc; Varc = 'a'; switch ( Varc ) {
case 'a': break ; case 'e': break ; default: break ;
printf( Varc es vocal 'a'\n); printf( Varc es vocal 'e'\n); printf( Varc NO es vocal 'a' o 'e'\n);
}
return 0; }
'a':
switch toma tres condiciones en un variable Varc. En caso que Varc es igual a 'a' los sentencias
y break; el que sigue imediatemente se ejecuta, y el indicador de ujo va afuera del bloque-
case 'e':
se ejecuta, y el indicador de ujo va afuera del bloque-switch. En caso que Varc no es igual a 'a' o 'e', pues los sentencias entre de default: y break; que sigue imediatemente, se ejecuta, y el indicador de ujo va afuera del bloque-switch. El prototipo de switch es como sigue:
switch( variable_tipo_int ) { case condicin1: sentencias en C; break; case condicin2: sentencias en C; break; case condicin3: sentencias en C; break; ........................................ ........................................ ........................................ ........................................ default: sentencias en C;
23
break;
En switch es necessario usar un variable de tipo int. Pero nosotros usamos un variable de tipo char. Es un error?. No, un variable de char tambin es un int. Aprendemos sobre esta cosa ms adelante. Tambin es possible usar un expresion en lugar de variable_tipo_int, pero el resultado de expresion tiene que un int. Es possible usar un groupo de condiciones. Por ejemplo, supponer que queremos encontrar todos los vocales en un grupo y todos los no-vocales en otro grupo. Escribimos un ejemplo como sigue:
#include <stdio.h> int main() { char Varc; Varc = 'a'; switch ( Varc ) {
case 'a': case 'e': case 'i': case 'o': case 'u': break ; default: break ;
}
return 0; }
En el ejemplo arriba, usamos solo un break; para todos los condiciones que precede. En este caso, cuando Varc est cualquier del vocal, el programa imprimir Varc es un vocal. En otra manera, todas las sentencias que preceden antes del primero break; se ejecutan.
I. while
El prototipo de while es como sigue:
Cunado el condicin es cierta, todas las sentencias entre llaves (bloque-while) se ejecuta. Cuando indicador de ujo a sentencia el indicador entcuentra la lnea
while (condicin), condicin se verica. Si este condicin es cierta, el indicador de ujo mover 1 en C;, despues sentencia 2 en C; etctera etctera, hasta el llave cerrar. En este momento, de ujo regresa a while (condicin) y verica este condicin otra vez. Si el condicin es cierta, el
processo repetir otra vez. En este manera todos los sentencias en el bloque-while se ejecuta indenidamente, hasta que el condicin es falso. Supponer que deseamos leer un carcter repetidamente hasta que la carcter presionada es 'q'. Escribimos un ejemplo como sigue:
#include <stdio.h> int main() { char varc ; varc = 'a' ; while ( varc != 'q' ) { printf(Dame un carcter\n); scanf( %c, &varc ); } printf ( Carcter 'q' est presionada \n ); return 0 ; }
En este ejemplo, inicializamos varc como 'a' antes de empezar la iteracin. Cuando el indicador de ujo alcanza while
imprimir Dame un carcter y espera para un presionar de llave de teclado. Cuando lee un carcter, regresa al condicin en while y vericar este condicin otra vez. Si el carcter presionada no es 'q' la iteracin continuar. Pero, cuando el carcter lo que se lee es 'q' , este ciclo terminar y la cadena Carcter se imprimir.
varc = 'a'.
Cuando este variable es 'q', la condicin es cierta y el programa no ejecuta el bloque-while. A veces es util ejecutar
25
}while ( varc != 'q' ); printf ( Carcter 'q' est presionada \n ); return 0 ; }
En este caso, es necesario introducir el carcter de terminacin ; en el ultimo de sentencia while. En este ejemplo el bloque-do-while ejecuta una vez. Si el carcter lo que leido es 'q', el condicin dentro de while terminar este bloque e imprimir Carcter regresa a sentencia do y ejecuta el bloque-do-while otra vez Tomemos ms otro ejemplo para usar
#include <stdio.h> int main() { int i; i=0 ; while ( i <10 ) { printf(Valor de i dentro de while = %d \n, i ); i++ ; } printf ( Ahora valor de i afuera de while = %d \n, i ); return 0 ; }
En este programa usamos un variable i como variable de control de iteracin. Inicializamos esta variable con una incrementamos este variable de control de iteracin por uno, usando i++; . La salida de este programa est como sigue: sentencia de inicializacin
i=0;
. Este bucle while se ejecuta hasta i mayor o igual a 10. Dentro del bloque-while
Valor Valor Valor Valor Valor Valor Valor Valor Valor Valor Ahora
de i dentro de while de i dentro de while de i dentro de while de i dentro de while de i dentro de while de i dentro de while de i dentro de while de i dentro de while de i dentro de while de i dentro de while valor de i afuera de
= 0 = 1 = 2 = 3 = 4 = 5 = 6 = 7 = 8 = 9 while = 10
while ( {
sentencias en C;
26
III. for
En el ejemplo arriba aprendimos sobre la iteracin usando
similar usando bucle-for. El prototipo de este bucle es como sigue: for ( inicializacin; { senenticas en C; }
condicin; control-de-interacin )
La sentencia de Initializacin se ejecuta slo una vez, cuando empieza este bucle. Los sentencias de condicin y control-de-iteracin son ejecutan cada uno de ciclos de iteraciones. Escribimos ejemplo arriba para imprimir de 0 hasta 9 usando for
return 0 ; }
Aqu la inicializacin es
i = 0;
condicin es
i <10;
control-de-iteracin es
i++;
Primera iteracin:
Cuando empieza este programa el valor de i es initializado a 0. Entonces la condicin i <10 se ejecuta. Ya que i es menor que 10 el programa se ejecuta todos los sentencias del bloque de for. As imprimir Valor de i= 0.
Secundo iteracin:
Cuando el ujo de programa regresa a for otra vez, la variable i est incrementado segun el control-de-iteracin. Ahora i tiene valor 1. Despues, sentencias de control se ejecuta. En este caso 1 es menor que 10, pues, el programa continua adentro del bloque del for. As imprimir Valor de i=1.
Tercera iteracin:
mismo como arriba ............................... ..............................
Ultimo iteracin:
Despues de imprimir Valor de i=9 el control de ujo de programa regresa a for otra vez. Entonces, incrementa el variable i a valor 10. Ahora la condicin i <10 no es satisfecho. Entonces el control del ujo de programa saltar a la sentencia printf
bucle = 10.
e imprimir Valor
de i afuera de
27
ultimo de iteracin. El programa para hacer los opciones mencionada es como sigue:
#include <stdio.h> int main() { int i ; int num1, num2 ; int option ; i=0; while( i <100 ) { printf( "\n\n"); printf( "Valor de i = %d\n", i ); printf( "Dame un entero (option): "); scanf ( " %d", &option ); if ( option == 0 ) continue ; if ( option == -1 ) break ; printf( "Dame dos nmeros enteros: "); scanf ( " %d %d", &num1, &num2 ); printf( "Multiplicacion de numeros: %d\n", num1*num2 );
( option == 0 ) continue ;
grama no ejecuta todos los lineas que sigue y el indicador de ujo regresa a
if ( option == -1 ) break ;
del bloque-while. Aqu hay un salida ejemplo de este programa cuando ejecutamos .
28
Valor de i = 0 Dame un entero (option): 1 Dame dos nmeros enteros: 4 5 Multiplicacion de numeros: 20 Valor de i = 1 Dame un entero (option): 9 Dame dos nmeros enteros: 4 5 Multiplicacion de numeros: 20 Valor de i = 2 Dame un entero (option): 0 Valor de i = 2 Dame un entero (option): 0 Valor de i = 2 Dame un entero (option): 5 Dame dos nmeros enteros: 1 7 Multiplicacion de numeros: 7 Valor de i = 3 Dame un entero (option): -1 Ahora valor de i = 3 Valor de option = -1
Cuando i = 2, entregamos 0 como option. Entonces el programa no nos pregunta para ms dos numeros y no
indicador de ujo salta al inicio del programa otra vez y imprime Valor
de i = 2,
imprime el resultado de multiplicacin. En lugar, el indicador de ujo salta al inico del programa y imprime Valor despues nos pregunta otra vez para dar un nmero. Entonces, entregamos otra vez 0 como option, y el
de i = 2,
vez para dar un nmero. Ahora entregamos 5 y todas las lneas en el bloque-while se ejecutan. Entonces imprime Valor de i = 3 y nos pregunta otra vez para dar un nmero. Ahora entregamos -1 y el indicador salta afuera del bloque-while. Nota que cuando damos el nmero de option como 0, el valor de i no es incrementado, porque esa sentencia ,
i++;
, no se ejecuta.
#include <stdio.h> int main() { int i ; int num1, num2 ; int option ; i=0; for (i=0; i <100; i++ ) { printf( "\n\n"); printf( "Valor de i = %d\n", i ); printf( "Dame un entero (option): "); scanf ( " %d", &option ); if ( option == 0 ) continue ;
29
if ( option == -1 ) break ; printf( "Dame dos nmeros enteros: "); scanf ( " %d %d", &num1, &num2 ); printf( "Multiplicacion de numeros: %d\n", num1*num2 ); } printf ( "Ahora valor de i = %d Valor de option = %d \n", i, option ); return 0 ; }
Aqu hay un salida ejemplo de este programa cuando ejecutamos. El comportamiento de los sentecias, if
== 0 ) continue ;
y if
ocurancia de la sentencia
( option ( option == -1 ) break ; son mismo al ejemplo usando while. Sin embargo, la i++; en el caso de bucle-for es diferente y cuando el indicador de ujo salta al inidicio
de bucle (cuando option = 0 ) incrementa el valor de i . Podemos ver en el salida siguiente para la misma entrada del programa, cmo incrementa el valor de i
Valor de i = 0 Dame un entero (option): 1 Dame dos nmeros enteros: 4 5 Multiplicacion de numeros: 20 Valor de i = 1 Dame un entero (option): 9 Dame dos nmeros enteros: 4 5 Multiplicacion de numeros: 20 Valor de i = 2 Dame un entero (option): 0 Valor de i = 3 Dame un entero (option): 0 Valor de i = 4 Dame un entero (option): 5 Dame dos nmeros enteros: 1 7 Multiplicacion de numeros: 7 Valor de i = 5 Dame un entero (option): -1 Ahora valor de i = 5 Valor de option = -1
3.4. goto
Hay otro modo para mover el indicador de ujo hacia una localizacin arbitraria, usando goto. El po de goto es como sigue:
30
#include <stdio.h> int main() { int option ; label1: printf( "Dame un entero (option): "); scanf ( " %d", &option ); printf( "Nmero leido es = %d\n", option ); if ( option != -1 ) goto label1; printf( "Afuera del bloque definido usando goto\n" ); return 0 ; }
Una salida de ejemplo de este programa es como sigue: Dame un entero (option): 0 Nmero leido es = 0 Dame un entero (option): 3 Nmero leido es = 3 Dame un entero (option): 4 Nmero leido es = 4 Dame un entero (option): 7 Nmero leido es = 7 Dame un entero (option): 3 Nmero leido es = 3 Dame un entero (option): 1 Nmero leido es = 1 Dame un entero (option): -1 Nmero leido es = -1 Afuera del bloque denido usando goto
se llama Byte. En los lenguajes como C, tipo de dato de un variable es un arreglo logico de bytes. Por ejemplo tipo de dato char es un byte, y oat es un arreglo de 4 bytes, o tamao de oat es 4 bytes. En la tabla 3 tamao de los tipos de datos se dan. Pero los tamaos dependen la implementacin en la compilador. Para saber el tamao
31
sizeof.
sizeof,
Tomemos un programa de ejemplo para imprimir tamao de tipo de datos come sigue:
char, int
long,
usando el operador
#include <stdio.h> int main() { printf( "Tamao de char es: %d bytes\n", sizeof(char) ); printf( "Tamao de int es: %d bytes\n", sizeof(int) ); printf( "Tamao de long es: %d bytes\n", sizeof(long) ); return 0 ; }
La salida de este prgograma pude ser
Tamao de char es: 1 bytes Tamao de int es: 4 bytes Tamao de long es: 8 bytes
De la salida arriba sabemos que el tamao del
char
es ms pequeo que
int
long.
Qu
sucede cuando intentamos almacenar un nmero LONG en una variable INT? Imagine el tamao de la tipo de dato, algo como la caja. Cuando intentamos caber una caja grande dentro de una caja pequea no cabr, as que podemos tener que cortar la caja en un tamao ms pequeo para caber. Asmismo si intentamos caber una caja pequea dentro grande hay muchas maneras de hacer. Por ejemplo podemos guardarla dentro del centro o a la una de las esquinas. De la misma forma, las variables se caben sobre uno otro. Ocasionalmente, es necesario convertir el valor de uno de la variable, a otro tipo. Para sa utilizamos el mtodo de conversin de tipo de variable. Por ejemplo convertimos un variable de tipo long como int como sigue:
return 0 ; }
Aqu el cadena
(int)
int.
de tipo char usando (int), (long), (oat) y (double) etc. como en el ejemplo que sigue:
#include <stdio.h> int main() { char Varc ; int VarInt ; float VarFloat ; long VarLong ;
32
double VarDouble ; Varc = 'a' ; VarInt = (int) Varc ; VarLong = (long) Varc ; VarFloat = (float) Varc ; VarDouble = (double) Varc ; printf("int de carcter ' %c' es : %d\n", Varc, VarInt ); printf("long de carcter ' %c' es : %ld\n", Varc, VarLong ); printf("float de carcter ' %c' es : %e\n", Varc, VarFloat ); printf("double de carcter ' %c' es: %e\n", Varc, VarDouble ); return 0 ; }
Salida de este programa es como sigue: int de carcter 'a' es : 97 long de carcter 'a' es : 97 oat de carcter 'a' es : 9.700000e+01 double de carcter 'a' es: 9.700000e+01
Tipo char short int unsigned short int int long int oat double
Bytes 1 2 2 4 8 4 8
Max
15 )
31 ) -2147483648 (-2
-9223372036854775808 (-2
63 )
16 - 1 ) 31 - 1 ) 2147483647 (2 63 - 1) 9223372036854775807 (2
15 )
12623
5.2. Flotantes
Usando notacin exponencial podemos expresar un nmero tal como321, como
0,321 103
3,21 102
3210 10
0,0321 10
. Cuando escribimos este nmero usando primero notacin donde el punto decimal
(o otante) precede un dgito no cero, se llama notacin punto otante. Es possible otar el punto decimal en este representacin, as pues este nombre. El parte 0.321 se llama signicando (m) y el parte 3 en otante es
(e) y 10 se llama base (b) y un valor para signo (s) (0 para positivo y 1 para negativo). El valor de un nmero
(1)s m be .
33
la representacin. Usualmente, solamente es posible usar el cantidad nito de dgitos para la precisin por razones prcticas. Este tipo de representacin introduce un error de tipo truncacin. Para aprender sobre esta tipo de error, tomemos un sistema de punto otante con precisin 3 as como un dgito para exponente y hagamos operaciones aritmticas. Un dgito para exponente signica que es possible usar de minimo es
0,100 109
y el valor maximo es
0,999 109 .
+
0,321 103
0,432 101 .
Ya que el segundo nmero no tiene miso exponente que el primero, es requiere alineacin (o des-normalizacin) como
(0,321+0,00432) 103 = 0,32532 103 . Pero, ya que es possible usar 3 3 solo 3 dgitos para signicando el resultado es 0,325 10 . Debido a la truncacin, tenemos un error de 0,00032 10
=
0,00432 103
0,24 103
por
0,12 108
el resultado es,
(0,240/0,120) 10
38
0,200 10
11
,100 109 .
Este tipo de error se llama underow. De la misma forma cuando queremos multiplicar
0,240 103
por
0,120 108
el resultado es,
(0,240 0,120) 10
3+8
0,288 10
10
,999 109 .
00000000
(0)
00000000000000000000000
sign (1 bit)
significand(23 bits)
Precision (Machine-Epsilon)
6. Arreglos
Un arreglo es un sequencia de variables (o valores) de mismo tipo de data. Un arreglo se declara como tipo_de_dato nomre[N], donde N signica cantidad de valores o elementos en este arreglo. Sunpongamos que queremos guardar 34
Byte4
Byte3
Byte2
Byte1
0.5
01111110
(1)
00000000000000000000000
1.25
01111111 (1)
01000000000000000000000
la propiedad como alto de cinco arboles en unas variables. Es posible declarar cinco variables como int altoarbo1, altoarbol2, ...... altoarbo5; y usar las variables en su programa. Ya que todos los variables contiene informacin de mismo propiedad y data de tipo, podemos usar un arreglo como altoarbol[5]. Este arreglo contiene un cinco elementos. Cada elemento se asocia a una variable. El variable de elemento 1 es altoarbol[0], elemento 2 es altoarbol[1], elemento 3 es altoarbol[2] elemento 4 es altoarbol[3] etc., Como vemos para acceder n-th elemento usamos la variable arr[n-1], donde n-1 es el ndice del elemento n. Escribimos un programa como sigue, para imprimir los valores de cada elementos en un arreglo:
#include <stdio.h> int main() { int i ; float altoarbol[5] ; altoarbol[0] altoarbol[1] altoarbol[2] altoarbol[3] altoarbol[4] = = = = = 1.1 ; 2.2; 3.3 ; 4.4 ; 5.5 ;
for (i =0 ; i <5; i++ ) { printf("Elemento %d de arreglo arbol es : %f\n", i+1, altoarbol[i] ); } return 0 ; }
Para cada tipo de dato es posible declarar un arreglo. Como vimos antes, en caso de tipo de data char usamos la palabra cadena en lugar de
35
7. Variable de Apuntador
Variable para acceder al direccin
&num1
Direccin
0x0000 0x0001 15 E 21 L 45
Contenido
&num2
0x0002 0x0003
* UnPtr
num2
&num3
0x0004 0x0005
num3
H W 0 0 0 2
8. Funciones
8.1. Bsicos de funciones
Una funcin es un sub-programa que realiza un trabajo especicado. Una funcin es un conjunto de declaraciones, deniciones, expresiones y sentencias como main. Tomemos el primer ejemplo que ya habamos aprendido que imprime una cadena como sigue:
36
#include <stdio.h> int mifuncion() { printf(Hello World\n); return 0 ; } int main() { mifuncion(); }
Hello
return 0; mifuncion().
Esta funcin imprimir la cadena
World.
funcin mifuncion no se ejecuta, cuando ejecutamos este programa. La salida de este programa tambin es,
Hello World
El prototipo de una funcin es como sigue:
main()
tambin es una funcin. Otra funciones que ya sabemos, son printf, scanf.
En este programa de ejemplo arriba, el tipo de dato de la funcin mifuncion es int el cual signica que esta funcin volver un dato de tipo int. As pues, usamos la sentencia return otro ejemplo como sigue:
0;
funcin no contiene ningn argumento. Cmo guardar o usar el dato que es devuelto de una funcin? Tomemos
#include <stdio.h> int mifuncion() { int out; int num1, num2 ; num1 = 5 ; num2 = 10 ; out = num1*num2 ; return out ;
37
} int main() { int val ; val = mifuncion(); printf ( Valor de val es = %d\n , val ); return 0; mifuncion()
para calcular multiplicacin de dos nmeros y devol-
vemos el resultado en la variable out de tipo int. En main llamamos esta funcin como
val
val = mifuncion();
es una variable del mismo tipo. Esta sentencia asigna la variable val con valor que se devuelve
Valor de val es = 50
Tome el ejemplo siguiente (solamente main) que intenta cambiar el valor de variable num2.
int main() { int val ; num2 = 40 ; val = mifuncion(); printf ( Valor de val es = %d\n , val ); return 0;
Cuando compilamos este programa, el compilador divulga un error que la variable num2 es indenida. Porque la variable num2 dentro de la funcin mifuncion() no est disponible en main.
#include <stdio.h> int mifuncion(int num1, int num2) { int out; out = num1*num2 ; } return out ;
38
numx = 5 ; numy = 40 ; val = mifuncion(numx, numy); printf ( Valor de val es = %d\n , val ); return 0; num1
y int
En este ejemplo, la funcin mifuncion toma dos argumentos de tipo int, los cuales son int mentos. Apenas para una claridad mejor llamemos estas variables como funcin desde main, usando una sentencia como
num2.
Aqu los argumentos son variables. Es necesario declarar el tipo de cada una de las variables en la lista de argu-
numx y numy como argumentos cuando llamamos esta funcin. Los variables son declarada en la funcin main como
variables pasan valores a variables-recibir. Cuando este programa se ejecuta, el valor de de
tipo int. Es necesario usar mismo tipo para los argumentos como declarado en una funcin, cuando llamamos esta funcin desde main. Apenas para una claridad mejor llamemos estas variables como
num1
y el valor de
el valor de
num2
numy
num2.
As pues, dentro de
numx
numy
num1
num2
#include <stdio.h> int mifuncion(int num1, int num2) { int out; printf ( Dentro mifuncion antes de cambiar las variables. num1 = %d ; num2 = %d \n, um1, num2 ); num1 = 6 ; num2 = 8 ; out = num1*num2 ; } return out ;
int main() { int val ; int numx, numy ; numx = 5 ; numy = 40 ; val = mifuncion(numx, numy); printf ( Valor de val es = %d\n , val ); printf ( Dentro main despus de llamar de mifuncion. numx = %d ; numy = %d \n , umx, numy ); return 0;
39
}
En este programa, dentro de main inicializamos las variables numx y numy como 5 y 40 respectivamente, antes de llamar mifuncion. Dentro de mifuncion imprimimos los valores de las variables-recibir correspondientes. Despus cambiamos los valores de las variables num1 y num2 como 6 y 8 respectivamente. Pues, dentro de main imprimimos el resultado de multiplicacin y los valores de las variables-pasar
numx
numy.
Dentro mifuncion antes de cambiar las variables. num1 = 5 ; num2 = 40 Valor de val es = 48 Dentro main despus de llamar de mifuncion. numx = 5 ; numy = 40
Los cambios de las variables-recibir dentro de la funcin mifuncion no se reeja en las variables-pasar. Este tipo de pasar los valores para los argumentos se llama El
#include <stdio.h> int mifuncion(int *num1, int *num2) { int out; printf ( Dentro mifuncion antes de cambiar las variables. num1 = %d ; num2 = %d \n, *num1, *num2 ); *num1 = 6 ; *num2 = 8 ; out = (*num1)*(*num2) ; } return out ;
int main() { int val ; int numx, numy ; numx = 5 ; numy = 40 ; val = mifuncion(&numx, &numy); printf ( Valor de val es = %d\n , val ); printf ( Dentro main despus de llamar de mifuncion. numx = %d ; numy = %d \n , umx, numy ); return 0;
40
Dentro mifuncion antes de cambiar las variables. num1 = 5 ; num2 = 40 Valor de val es = 48 Dentro main despus de llamar de mifuncion. numx = 6 ; numy = 8
Como vemos, ahora los valores de las variables numx y numy son diferentes dentro de main despus de llamar de mifuncion. Cmo alcanzamos este cambio? En este ejemplo, las variables-recibir en la funcin mifuncion son variables de punteros y pasamos las direcciones de las variables de numx y numy como las variables-pasar. Cuando ejecutamos este programa, los valores de punteros de las variables numx y numy se pasan a las variabes num1 y num2. Ahora es posible cambiar el contenido de las direcciones de las variables numx y numy desde la funcin mifuncion. En este modo tambin es posible devolver muchos valores desde una funcin que lo que se puede devolver mediante la sentencia return .
#include <stdio.h> int mifuncion(char *strp) { printf(La cadena es: %s\n, strp); return 0 ; } int main() { char str[12] = Hello World ; mifuncion(str); /* Nota aqu str es un puntero */ } return 0;
En este programa, la funcin mifuncion tiene un argumento de tipo char *, el cual es un puntero (de un carcter) del principio de la cadena o arreglo de 12 caracteres. Dentro de main llamamos esta funcin usando la variable str como argumento, el cual es el puntero del principio de la cadena. Dentro de la funcin es posible tener acceso a los punteros desde del inicio de la cadena hasta el ltimo. La salida de este programa es,
8.4.2.
Cuando queremos pasar un arreglo de int o oat etc., excepto la cadena, es necesario pasar el tamao o cantidad total de elementos. Este se requiere para saber el ltimo del arreglo dentro de una funcin. Tomemos un ejemplo como sigue, para manipular un arreglo de int (como vector) usando dos funciones. Dentro de main declaramos un arreglo de int (ivec[5]) y su tamao (Nivec). La funcin,
Ivecprint, imprime los elementos en el arreglo y la Ivecadd, agrega un nmero 3 a cada uno de los elementos. En este caso pasamos el puntero del inicio del arreglo (ivec) y tamao del arreglo (Nivec) a las funciones. Despus de llamar la funcin (Ivecadd) dentro de main, imprimimos otra vez los elementos de este arreglo usando la funcin, Ivecprint.
funcin,
41
#include <stdio.h> int Ivecprint( int *ivar, int Nivar) { int i ; i=0; printf(Elementos de vector son: ); while ( i <Nivar ) { printf( %d , ivar[i] ); i++ ; } printf(\n); } return 0 ;
int Ivecadd( int *ivar, int Nivar) { int i ; i=0; while ( i <Nivar ) { ivar[i] = ivar[i] + 3 ; i++ ; } } return 0 ;
int main() { int ivec[5] = { 3, 4, 5, 6, 7 }; int Nivec ; Nivec = 5 ; Ivecprint( ivec, Nivec ); Ivecadd( ivec, Nivec ); Ivecprint( ivec, Nivec ); } return 0;
La salida de este programa es dado abajo. Como vemos, los valores de los elementos despus de llamar la funcin han cambiado.
Este programa tambin muestra cmo devolvemos muchos valores (como un arreglo) desde una funcin, y cmo usamos una funcin para hacer un trabajo repetidamente. En las funciones arriba, en lugar de int *ivar, es possible usar int ivar[] . Es slo una declaracin alternativa, pero an el tamao del arreglo tiene que ser pasado por Nvar.
42
int Ivecadd( int ivar[], int Nivar) { int i ; i=0; while ( i <Nivar ) { ivar[i] = ivar[i] + 3 ; i++ ; } } return 0 ;
8.4.3.
Este tipo de declaracin es ms til cuando queremos utilizar arreglos de multi dimensionales. Tomemos un ejemplo donde pasamos un arreglo de oat de dos dimensiones como sigue. El arreglo en main es fvec[3][5]. La primera funcin recibe el arreglo usando una variable de puntero de oat como oat *fvar. Para acceder los valores de los elementos usamos el modo de acceder de los elementos que hemos visto en seccin 6. Cuando llamamos esta funcin es necesario pasar el puntero del inicio del arreglo, como &fvec[0][0]. La segunda funcin recibe los elementos del arreglo usando una variable de puntero de un arreglo de oat como oat fvar[][5] y pasamos fvec como argumento cuando llamos esta funcin.
#include <stdio.h> int Fmatrixprint1( float *fvar, int Ndim1, int Ndim2) { int i, j; printf("Method1: Elementos de arreglo son\n" ); j=0; while ( j <Ndim2 ) { i=0; while ( i <Ndim1 ) { printf(" %f ", *(fvar + j*Ndim1 + i) ); i++ ; } printf("\n"); j++ ; } printf("\n"); return 0 ;
int Fmatrixprint2( float fvar[][5], int Ndim1, int Ndim2) { int i, j; printf("Method2: Elementos de arreglo son\n" ); for (j=0; j<Ndim2; j++ )
43
} printf("\n"); return 0 ; } int main() { float fvec[3][5] = { { 3.1, 4.1, 5.1, 6.1, 7.1 }, { 3.2, 4.2, 5.2, 6.2, 7.2 }, { 3.3, 4.3, 5.3, 6.3, 7.3 } } ; int N1, N2 ; N1 = 5 ; N2 = 3 ; Fmatrixprint1( &fvec[0][0], N1, N2); Fmatrixprint2( fvec, N1, N2); return 0;
#include <stdio.h> int mifuncion( int, int); /* equivalente a int mifuncion(int x, int y); */ int main() { int i1, i2, res ; res = mifuncion(i1,i2); return 0 ; } int mifuncion(int x, int y) { return x*y ; }
En este ejemplo, la sentencia int mifuncion(int, int); declara el prototipo de la funcin mifuncion. Esta sentencia da information sobre el tipo de dato que devuelve de la funcin y cantidad de argumentos y los tipos de datos de los argumentos. Nota el simbol ; en el ltimo de la sentencia. Despus de main, escribimos la funcin real. Cuando una funcin se escribe arriba del main como sigue, no es necesario declarar el prototipo, porque la funcin real funciona da informacin sobre los tipos de datos y cantidad de los argumentos
44
#include <stdio.h> int mifuncion(int x, int y) { return x*y ; } int main() { int i1, i2, res ; res = mifuncion(i1,i2); return 0 ; }
8.6.1.
No es posible escribir una funcin dentro otra funcin. El programa se da abajo es incorecto, porque la funcin funcion2 se dene dentro la funcin main.
#include <stdio.h> int mifuncion(int x, int y) { return x*y ; } int main() { int i1, i2, res ; int funcion2(int x, int res) { return x*res*x ; } res = mifuncion(i1,i2); return 0 ;
Es posible llamar una funcin dentro de ontra funcin. Pero, es necesario denir la funcin o el prototipo de la funcin antes de llamar. En el ejemplo siguiente la funcin mifuncion llama la funcin funcprint.
#include <stdio.h> int funcprint(int x) { printf("Dentro funcprint: %d\n" , x); return 0 ; } int mifuncion(int x, int y) { funcprint (x); funcprint (y); return x*y ;
45
Cuando no queremos devolver ningun valor de una funcin usamos void como data de tipo, como en el ejemplo abajo.
8.6.2.
Las variables en una funcin existe slo cuando esta funcin se ejecuta. Cuando la ejecucin de una funcin se termine, todas las variables son destruido. Aunque es posible devolver a main el puntero de una variable local que pertenence a una funcin, cuando accedemos este puntero, el comportamiento es indenido. En el ejemplo abajo, devolvemos el puntero de una variable de tipo int, despus en main intentamos cambiar el contenido de este puntero. Este es un error, aunque el comportamiento depende del compilador. Hay otro modo para usar una variable local despus de terminar la ejecucin de una funcin, pero aprendemos ms adelante.
#include <stdio.h> int * func() { int i ; printf("El valor de i y &i en func: %d %d\n", i, &i); return &i ;
i = 20 ;
int main() { int *p ; p = func(); *p=10; printf("El valor de i y &i en main: %d %d\n", *p, p); return 0; }
8.6.3. El puntero de una funcin
Sabemos sobre puntero de una variable. De este modo, es posible denir y usar el puntero de una funcin tambin. En el ejemplo abajo escribimos una funcin como int myfunc1() que devuelve un int. El prototipo de esta funcin se da arriba de main. En main declaramos una variable de puntero para esta funcin como int (*funcptr1) () .
46
Comparemos esta declaracin con la declaracin del prototipo de la funcin. En lugar de myfunc1 en el prototipo usamos (*funcptr1) en el declaracin de la variable de puntero, y el tipo de dato int en este lnea signica el tipo de dato que devuleve de esta funcin. En main ahora funcptr1 es una variable de puntero de una funcin que devuelve un int. Por el mismo modo, funcptr2 es una variable de puntero de una funcin que devuelve un char. Ya sabimos que antes de usar una variable de puntero es necesario asignar esta variable con un valor de direccin a la memoria. La direccin de la funcin int myfunc1() es &myfunc1. As pues, asignamos funcptr1 = &myfunc1. El llamar esta funcin usando variable de puntero es my similar a llamar una funcin. Normalmente para llamar la funcin int myfunc1() usamos una sentencia como i = myfunc1(); asimismo aqu usamos i = (*funcptr1)(); . En este modo llamamos myfunc2 usando la variable de puntero funcptr2 despus de asignacin con myfunc2.
#include <stdio.h> int myfunc1(); /* prototipo de una funcin */ char myfunc2(); /* prototipo de una funcin */ int main() { int i ; char c; int (*funcptr1)(); /* es una declaracin de varaibale de puntero de una funcin */ char (*funcptr2)(); /* es una declaracin de varaibale de puntero de una funcin */ funcptr1 = &myfunc1 ; /* myfunc1 es el puntero de la funcin int myfunc1() */ i = (*funcptr1)(); printf("El valor de i en main: %d\n", i); funcptr2 = &myfunc2 ; c = (*funcptr2)(); printf("El valor de char en main: %c\n", c); } return 0;
int myfunc1() /* la funcin 1 */ { int i ; i = 20 ; printf("El valor de i en func: %d\n", i); } return i ;
char myfunc2() /* la funcin 2 */ { char c ; c = 'A' ; printf("El valor de char en func: %c\n", c); } return c ;
47
c = funcptr2();.
i = funcptr1()
8.6.4.
Algun ejemplos
1. Escribamos una funcin para evaluar la funcin f(x) = x + 3. En main imprimamos los valores de x y f(x), para x de 0 hasta 1.0 en el intervalo 0.1.
#include <stdio.h> float func(float x) { float res ; res = x*x + 3 ; return res ;
x = 0 ; dx = 0.1 ; while ( x <= 1.0 ) /* Este incluye el valor 1.0 */ { res = func(x); printf ( x= %f f(x)= %f \n, x, res ); x = x + dx ; /* Tambin podemos usar x += dx ; */ }
2. Escribamos una funcin para evaluar la funcin f(x) = x + log(x) + sin(x), y en otra funcin calculemos los valores de x y f(x) de 0 hasta 1.0 en el intervalo dx y guardemos los valores en los arreglos que son declarados en el main y pasado a la segunda funcin. El valor de dx tambin se pasa desde main. Ya que no es posible calcular log(x) cuando x no es positivo, imprimimos un error en este caso y suppongemos el valor de esta funcin es -1.
#include <stdio.h> /* Usamos la sentencia siguiente porque queremos usar las funcines log10(x) y sin(x) */ #include <math.h>
/* Esta funcin para evaluar la funcin que se declara arriba */
return res ;
/* Esta funcin para recibir los arreglos y dx, as como para guardar los resultados de la funcin */ /* en los arreglos */
int func2(float *xarr, float *farr, int Narr, float dx) { float res ; int i ; x = 0.0 ; while ( x <= 1.0 ) { res = func(x); arr[i] = res ; x = x + dx ; i++ ; } return 0;
int main() { float x[100], f[100], dx ; int Narr ; arr = 100 ; dx = 0.2 ; /* aqu inicializamos dx como 0.2 */ func2(x, f, Narr, dx); /* Aqu imprimimos los valores de los arreglos x y f */ for ( i=0; i <Narr ; i++ ) { printf ( x= %f f(x)= %f \n, x, f[i] ); }
49
Strucut, Union Lectura y escritura de archivos Operaciones con Cadenas Preprocesador & Macros Cambiar de C a C++ Programacin orientada a objetos: C++ Conceptos avanzados en C++ Librario de estndar templates (STL)
50