Programación en Borland C++ Ejemplo 1: Programa que imprime 'Hola' en la pantalla #include <stdio.h>
librerías a usar
void main(void) { printf("Hola"); }
tipo_de_salida nombre_función(parámetros)
Ejemplo 2: Programa que lee un valor ingresado por teclado y luego lo imprime. #include <stdio.h> void main(void) { int x; declaración de variable local scanf("%d",&x); printf("El valor ingresado es %d",x); }
Ejercicios: 1) Hacer un programa que calcule la siguiente función: y = ¾ x + 3,14 . Donde x es un valor ingresado por teclado. #include <stdio.h> #define PI 3.14; void main(void) { float y,x; scanf("%f", &x);
declaración de una constante
declaración de una variable local (tipo float) se lee una tecla (el "%F" se llama Cadena de Control y se utiliza para indicar el tipo de valor que se va a leer, en este caso float (%F). Para int sería "%d" y para char "%c). El "and" delante del nombre de la variable sirve para que el valor de esa variable se guarde en el lugar correspondiente en memoria. Al no colocarla es posible que se generen errores.
y=(3 / 4) * x + PI; printf("El resultado es = \"%f\"",y);
se imprime el valor. Para imprimir una cadena de texto con una variable, se tiene que colocar la Cadena de Control en el lugar donde iría la variable que queremos colocar, luego se cierran comillas, se coloca "," y luego se pone el nombre de la variable a imprimir, en este caso "y" que es de tipo float (%f).
} 2) Realice un programa que permita ingresar por teclado tres valores y que imprima el mayor de ellos. #include <stdio.h> #include #include void main(void)
Favaro Santiago 2° 2° E
1
{ int A,B,C,Aux1,Aux2; declaración de variables locales clrscr(); limpia la pantalla gotoxy(5,10); printf("Ingrese tres valores uno a continuación del otro\n"); Cuando se imprime una cadena de texto, éste puede llevar ciertos modificadores, en este caso el modificador "\n" sirve para bajar un renglón. (Ver tabla de modificadores más adelante). gotoxy(15,11);scanf("%d",&A); gotoxy(15,12);scanf("%d",&B); gotoxy(15,13);scanf("%d",&C); if (A > B) {Aux1=A;} else {Aux1=B;} if (Aux1 > C) {Aux2=Aux1;} else {Aux2=C;} gotoxy(5,14); textcolor(RED); cprintf("El número mayor que ingresó es el %d",Aux2);
La función cprintf, imprime texto pero con el color y tipo de fuente actual, a diferencia de printf que solo imprime el texto sin características especiales.
getch(); // Hace una pausa }
Tipos de Variables: A continuación se detallan los tipo de variables con sus respectivos rangos. Tipo Char Unsigned char Short Unsigned short Long Unsigned long Int Unsigned int Float Double Class Struct Void
Bytes 1 1 2 2 4 4 4 4 4 8 * * 0
Signo Con signo Sin signo Con signo Sin signo Con signo Sin signo Con signo Sin signo Con signo Con signo
Ninguno
Rango de Valores -128 a 127 0 a 255 -32768 a 32767 0 a 65535 -2147483648 a 2147483647 0 a 4294967295 Bajo Win32 igual que long Bajo win32 igual que unsigned long ± 1.4E-45 a ±3.4E38 ±4.9E-324 a ±1.7E308 Varía según la definición Varía según la definición Indica que no hay tipo
Estructura del IF if (cond) { instrucciones; } else { instrucciones; }
Favaro Santiago 2° 2° E
2
Modificadores para escribir texto Los modificadores de texto son utilizado en las funciones printf y cprintf. Éstos sirven para, por ejemplo, poder insertar un retorno de carro o para escribir un carácter especial como puede ser las comillas. Modificador \n \*
\a \b \f \r \t \v \\ \? \" \x \' \o
Acción Inserta una nueva linea. Ej: printf("Primera linea.\nSegunda linea"); Donde "*" es cualquier carácter. Inserta el mismo carácter que se puso luego de la barra. Ej: printf("Ahora voy a insertar unas comillas \""); Carácter de alarma (campana) Retroceso Avance de hoja Regreso de carro Tabulador horizontal Tabulador Vertical Diagonal ("\" ? " Numero hexadecimal ' Numero octal
Favaro Santiago 2° 2° E
3
Funciones para lectura de caracteres Una de las maneras es la siguiente: char a; scanf(“% c,& a”); Esta función se encarga de leer el buffer de entrada; cuando en él aparece el código ASCII del enter guarda en la variable carácter, el último caracter ingresado. a=getchar ( ); Esta función trabaja de igual modo que la anterior. fflush ( ); Se encarga de efectuar la limpieza del buffer. Necesita como parámetro el nombre del buffer a limpiar. (el buffer de entrada se llama stdin.
Ejemplo: Para limpiar el buffer de entrada : fflush (stdin); Nota: Las funciones mencionadas residen en stdio.h. a=getch ( ); Esta función guarda en la variable caracter especificada, el código ASCII del caracter correspondiente a la tecla presionada (esta función finaliza cuando registra un cambio en el buffer de entrada). El caracter ingresado no es mostrado en pantalla. a=getche(); Idem al anterior pero muestra el caracter en pantalla. Nota: Estas dos funciones residen en conio.h.
Cadena de caracteres Para imprimir algún texto en pantalla se puede usar printf("Hola"); o sino algo más exclusivo para imprimir texto que es puts("Hola");
mediante esta función se imprime solamente texto. Se pueden usar los modificadores al igual que printf y además esta función agrega un retorno de carro al final del texto impreso.
Vector de caracteres: Un vector es un conjuntos de datos de igual tipo. Char a,b,c,d,e; Char x[5] = "Hola";
en esta sentencia se esta declarando un vector de 5 elementos
Favaro Santiago 2° 2° E
4
En la asignación anterior (asignamos "hola" al vector x) se puede ver que por cada elemento del vector se agrega cada letra, o sea al elemento 1 le corresponde la h, al 2° la o y así sucesivamente. C++ agrega al final de cada vector de caracteres un carácter nulo (/0), con lo cual significa que en esa posición de la cadena termina el vector de caracteres, por lo que podemos decir que el elemento 5 de ese vector contiene al carácter nulo. Por lo que podemos graficar lo siguiente: Vector x | H | o | l | a | /0 | Elemento n° 0 1 2 3 4 Obsérvese que el elemento que antes había dicho que era el 1 en el gráfico lo puse como 0, con lo cual podemos decir que, por ejemplo, si queremos imprimir el carácter "a" de ese vector tendremos que hacer los siguiente: Puts(x[3]); Ejemplo: Realice un programa que permita ingresar por teclado una palabra de hasta 10 caracteres para luego imprimirla. #include <stdio.h> void main(void) { char w[15]; definimos un vector de 15 elementos para asegurarnos de que se va a guardar lo escrito correctamente, o sea que siempre es conveniente definir a nuestro vectores un poco mas grandes de lo que los necesitamos. gets(w); esta función sirve para leer vectores de caracteres o cadenas de texto (de ahí proviene la s del final: string, cadena en inglés). Requiere como parámetro un vector de carácteres puts(w); } Ejercicio Realice un programa que permita ingresar una cadena de hasta 15 caracteres. Se necesita imprimir, si es que exista la segunda palabra. #include <stdio.h> #include main() { char Cadena[15]; int i,in; clrscr(); printf("Ingrese una oraci¢n de 15 letras:\n"); gets(Cadena); in=0; i=0; while((Cadena[i] != '\0') && (i < 15)) { if ((Cadena[i] == ' ') && (in == 1)) {break;} if (Cadena[i] == ' ') {in=1;} if (in==1){ printf("%c",Cadena[i]);} i=i+1; } getch(); }
Favaro Santiago 2° 2° E
5
Uso de funciones Ejemplo: Diseñe un programa que permita realizar, utilizando funciones, la suma de dos valores ingresados Int suma(int,int);
prototipo de la función (en esta línea se declara que va a existir una función que se llama suma. Esto se hace una vez por cada función al principio del programa).
Void main(void) { int a,b,c; scanf("%d",&a); scanf("%d",&b); c=suma(a,b); printf("%d",c); } int suma(int x,int y)
el primer int antes de suma significa el tipo de valor que va a devolver la función suma. Entre paréntesis van los tipos de variables que se van a usar como parámetros.
{ int w; w=x+y; return w; } Ejercicio: Realice un programa que permita efectuar las cuatro operaciones básicas utilizando funciones. #include <stdio.h> #include #include "operacio.h" float float float float
Suma(float,float); Resta(float,float); Multiplicar(float,float); Dividir(float,float);
void main(void) { float x,y,result; char letra; clrscr(); printf("\t\t\tCALCULADORA CON BORLAND C++\n\n\n"); printf("Ingrese la operaci¢n a efectuar:\n1- Suma\n2- Resta\n3Producto\n4- Divisi¢n\n\t"); fflush(stdin); scanf("%c",&letra); printf("\nIngrese un valor: "); scanf("%f",&x); printf("Ingrese otro valor: "); scanf("%f",&y); if (y == 0 && letra==52) {letra=48;}
Favaro Santiago 2° 2° E
6
switch (letra) { case '2': result=Resta(x,y);break; case '1': result=Suma(x,y);break; case '3': result=Multiplicar(x,y);break; case '4': result=Dividir(x,y);break; default:printf("Operaci¢n invalida\n");break; } printf("\nOperaci¢n = %f",result); getch(); } float Suma(float a, float b) { float r; r=a+b; return r; } float Resta(float a, float b) { float r; r=a-b; return r; } float Multiplicar(float a, float b) { float r; r=a*b; return r; } float Dividir(float a, float b) { float r; if (b -= 0) {r=a/b;} else {r=0;} return r; }
Favaro Santiago 2° 2° E
7
Vectores Numéricos Ejemplo: Realice un programa con el que se puedan ingresar 10 valores numéricos para ser cargados en un vector y posteriormente impresos en el orden ingresado. void main (void) { int x[10],i; for (i=0;i< 10;i++) { scanf("%d",&x[i]); } for (i=0;i< 10;i++) { printf("%d\t",x[i]); } Ejemplo 2 – Ordenamiento de vectores mediante el método de Burbujeo Realice un programa que permita ingresar 10 valores e imprimirlos ordenados de manera ascendente ... for (i=0; i < 9;i++) { for (j=i+1;i < 10; j++) { if (x[j] > x [i])
' Este es el caso para ordenar ascendentemente, pero si se quiere ordenar descendentemente se debe cambiar el signo mayor (>) por el menor (<)
{ w=x[i]; x[i]=x[j]; x[j]=w; } } } ...
Favaro Santiago 2° 2° E
8
Matrices Ejercicio Realice un programa que le permita a una playa de estacionamiento almacenar la información siguiente: a) Número de patente b) Hora de ingreso c) Hora de egreso d) Tiempo de estadía e) Dinero abonado f) Tipo de vehículo (categorías 1,2 y 3) #include <stdio.h> #include void main(void) { int est[20][6],i; for (i=0;i < 20;i++) { clrscr(); printf("Ingrese el número de patente: "); scanf("%d",&est[i][0]); printf("Ingrese la hora de ingreso: "); scanf("%d",&est[i][1]); printf("Ingrese la hora de egreso: "); scanf("%d",&est[i][2]); printf("Ingrese el tipo de vehículo: "); scanf("%d",&est[i][4]); est[i][3]=est[i][2] - est[i][1]; printf("El tiempo de estadía fue %d\n",est[i][3]); est[i][5]=est[i][3]*est[i][4]; printf("El dinero abonado fue de $ %d\n",est[i][5]); getch(); } }
Favaro Santiago 2° 2° E
9
Recorriendo la memoria: Punteros Un puntero guarda una dirección de memoria de otra variable. El puntero tiene que ser declarado como una variable común pero con una diferencia: el * (asterisco) que se debe anteponer al nombre de la variable. La organización de la memoria en la computadora La mayoría de las memorias en la computadora está organizada de manera parecida a una matriz de 8 elementos por un cantidad x de filas (esta cantidad está determinada por el tamaño de la memoria: 8 MB, 16 MB, 32 MB, etc). Cada “casillero de esa matriz” tiene un valor de 1 o 0, lo se denomina bit; cada fila, que se denomina posición de memoria, está compuesta por ocho casilleros que forman 1 byte. La nomenclatura de las posiciones de memoria suele ser ØØØ1 para el caso de la posición 1. En el siguiente gráfico se puede observar una estructura de una memoria:
0 0 0 0
0 0
0 0
0 1
0 0
0 0
0 0
Variable A (Con el valor 8 en decimal) Está guardada en la posición ØØØ1
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 1
0 0 0 0 0 1
0 1 0 1 0 1
Puntero Y
0 0 0 0 0 0
Posición ØØØ6 Puntero X Variable B
La variable A está declarada como int por lo que tiene que ocupar 16 bits (ya que int va de –32768 a 32767, y para formar todos estos número se necesitan 16 bits) si cada posición de memoria tiene 8 bits, esta variable debe ocupar 2 posiciones de memoria. Cabe aclarar que para un mismo puntero o una misma variable, las posiciones de memoria deben ser correlativas, esto significa que si la variable ocupa 4 posiciones de memoria tendría que ser por ejemplo ØØ25, ØØ26, ØØ27, ØØ28. Por mas que ocupe dos posiciones se debe decir que ‘A’ se encuentra en la posición ØØØ1. El valor de ‘A’ está en binario que se lee poniendo la posición ØØØ1 + ØØØ2, entonces quedaría 0000000000001000, en decimal sería 8. Cabe aclarar que el primer bit es el bit de signo. En el caso de los punteros se guarda, en binario, el valor de la posición de memoria de la variable a la que hacen referencia. Por ejemplo el puntero X está guardando el valor ØØØ1. Aclaraciones Cuando uno escriba un programa como el siguiente, la primera función printf lo que va a hacer es imprimir el valor de la posición de memoria a la que el puntero está haciendo referencia, y el segundo imprimirá el valor de la variable a la que el puntero hace referencia, en este caso es el numero 50. ... Int *x,a; A=50; X=&a; Printf (“%d”,x); Printf (“%d”,*x); … Por lo tanto para manejar el valor de una variable mediante un puntero se deberá anteponer al nombre del puntero un * (asterisco). Y para manejar el numero de posición de memoria no se le antepone nada. En el programa anterior en la instrucción x=&a se le está pasando el valor de la posición de memoria de ‘a’ a ‘x’.
Favaro Santiago 2° 2° E
10
Para modificar el valor de, por ejemplo ‘a’ en este caso, se deberá poner *x=25; si es que se le quiere asignar 25 a ‘a’. Es bueno tener en cuenta que cuando se quiere hacer una división entre dos punteros, no hay que escribir los siguiente: z=(*x/*y); ya que esto retornará un error. ¿Por qué? Porque la parte .../*... el compilador lo va a tomar como el inicio de un comentario, por lo tanto para que ande habrá que escribirla de la siguiente forma: z=(*x/(*y)). Programa de ejemplo que hace referencia al gráfico de la memoria … int suma(int*,int*); // Prototipo de la función suma. La diferencia entre los prototipos comunes es que se debe agregar el asterisco después del tipo de variable para poder usar los punteros. Cuando un parámetro de cualquier función es una variable, se dice que se está pasando el parámetro por valor (pasaje por valor, ByVal); cuando el parámetro es un puntero, pasándose la dirección de memoria, se dice que se pasa el parámetro se está pasando por referencia (ByRef). void main(void) { int a,b,z; scanf(“%d”,&a); scanf(“%d”,&b); z=suma(&a,&b); //Se le pasa la dirección de memoria de a y de b a la función printf(“%d”, z); } int suma(int *x,int *y) { return(*x + *y); } Otro ejemplo más completo (una calculadora muy simple) #include <stdio.h> #include #include <smGenLib.h> #define SUMA '1' #define RESTA '2' #define DIVI '4' #define MULT '3' float operar(float*,float*,int*); void main(void) { int op; float a,b,z; op=mgMenu("Ingrese opci¢n","A + B","A - B","A * B","A / B","",1); clrscr(); printf("\nIngrese A: "); scanf("%f",&a); printf("Ingrese B: "); scanf("%f",&b); z=operar(&a,&b,&op); printf("\nResultado: %.2f",z); getch();
Favaro Santiago 2° 2° E
11
} float operar(float *x,float *y,int *op2) { switch (*op2) { case SUMA: {return ((*x)+(*y));break;} case RESTA: {return ((*x)-(*y));break;} case MULT: {return ((*x)*(*y));break;} case DIVI: { if (*y!=0) {return ((*x)/(*y));} else {return (0.0);} break; } } return (0.0); } Mas consideraciones para tener en cuenta en el uso de punteros (cuestiones con vectores) El ordenamiento de un vector en la memoria: V Ele V Ele
e men e men
c to c to
t [ t [
o 0 o 1
r ] r ]
V e c t o r Ele men to [ 2 ] V e c t o r Ele men to [ 3 ]
Favaro Santiago 2° 2° E
12
O sea, que en este ejemplo gráfico se puede observar claramente que un vector en la memoria está ordenado con posiciones de memoria consecutivas. Ejemplo: si la primera posición de memoria, o sea, si el elemento [0] se encuentra en la posición de memoria ØØØ6, el elemento siguiente o sea el [1] se encontrará en la posición ØØØ8 y asi consecutivamente hasta que se acaben todos los elementos (¿por qué ØØØ8 y no ØØØ7? Simple, porque si el vector es del tipo int, entero, cada elemento pasa a ocupar 2 posiciones de memoria). Por lo tanto cuando tenemos un puntero, al mismo le podemos pasar la primera posición de memoria del vector y asi, moviéndonos de posición de memoria para abajo podemos averiguar todos sus valores. ¿Cómo sería esto? Vamos a un ejemplo práctico (suponiendo como que el vector ya tuviera valores cargados):
#include <stdio.h> void main(void) { int x[10],i; int *p; //Declaración del puntero ‘p’ p=&x[0]; //En esta línea lo que hago es asignarle la primera posición de memoria del vector al puntero p. for (i=0;i<10;i++) { printf(“%d”,p); //Imprimo el valor a que está apuntando p, en la primera vuelta del for va a ser el primer valor del vector. Se puede observar, que en realidad el printf para una variable común sería printf(“%d”,&p), pero como en este caso ‘p’ es un puntero, quedaría printf(“%d”,&*p) (porque se tendría que pasar la posición de memoria de la variable que se quiere imprimir (por eso el &) pero como es un puntero, en realidad es la variable a que apunta (por eso el *)). Pero igual, esto ultimo se puede simplificar a exactamente como esta escrita esta linea. p++; //Con esta segunda línea lo que hago es mover el puntero dos posiciones de memoria más abajo (dos posiciones por el tipo del puntero es int), logrando así que se esté leyendo el valor que tiene el vector en el elemento x[1]. } } En este ejemplo, hace lo que queremos y bien. Pero... ¿qué pasa si despues de imprimir los 10 valores queremos volver a imprimir el elemento [0]? Lo que tenemos que hacer, es mover al puntero a la posición que inicialmente tenía. ¿Cómo se logra esto? Se podría hacer un for pero al revés, y poner, en el lugar de p++, p--; lo que lograríamos ir bajando al puntero hasta logra llegar a la posición que incialmente tenía. Esto sirve pero es un método relativamente lento. Esto se puede corregir leyendo, a través del puntero, el valor que hay 8 lugares mas abajo en la memoria (8 es un ejemplo). Esto se logra poniendo la siguiente instrucción: En forma general: printf(“%d”,*(p+LUGARES_A_MOVER)); A modo de ejemplo: printf(“%d”,*(p+8)); O sea que se pone el asterisco para indicar que se quiere leer el valor de determinada posición, y entre paréntesis el nombre del puntero más menos las posiciones de memoria que se quieren leer más abajo o más arriba. Esto, para el ejemplo anterior no sirve de nada saberlo pero a la hora de ordenar matrices o vectores por medio de punteros, es necesario. Los LUGARES_A_MOVER se refiere a cuantos bloques de memoria debe leer el puntero mas abajo o mas arriba de la actual posición (considerando a un bloque
Favaro Santiago 2° 2° E
13
de memoria a, por ejemplo, si es int el puntero, un bloque de memoria sería dos posiciones de memoria, si es float, cuatro, etc).
En el siguiente ejemplo, se va a cargar un vector por medio de una función que usa parámetros con punteros: #include <stdio.h> void Cargar(int *,int); //Prototipo de la función para cargar el vector. El primer ‘int *’ es para pasar la posición de memoria del comienzo del vector (el elemento matriz[0]), ésta variable es un puntero. El otro int es para poder pasar el alto total del vector (en este caso 10 elementos). Y por usar punteros, ésta función no va a devolver ningún valor sino que los va a modificar desde esa misma función, o sea que modifica el valor de la memoria directamente. void main (void) { int x[10]; //Declaración de un vector normal (sin punteros, sin nada especial) Cargar(&x[0],10); //El primer parámetro que se está pasando es el de la posición de memoria en donde comienza el vector (que siempre un vector empieza donde está el primer elemento). El segundo es la altura total del vector o, mas claro, la cantidad total de elementos. } void Cargar(int *vector, int alto) { int i,aux; for (i=0; i< alto;i++) { scanf(“%d”,%aux); *vector=aux; //Asigno el valor de aux al elemento actual al que está apuntando del vector x (declarado en main) vector++; //Muevo al vector una posición mas abajo para poder, en la siguiente vuelta del bucle, cargar el siguiente elemto del vector x } } Comentario: En el último comentario puse mover para abajo una posición de memoria, ya que se da por sobreentendido que se mueve de a cuantas posiciones sean necesarias para pasar al siguiente elemento. Ejemplo: si el puntero es int, se va a mover de a dos posiciones, si es float de a cuatro, etc.
Volviendo a lo explicado depues del primer ejemplo con vectores y punteros la función cargar del ejemplo anterior se puede simplificar a lo siguiente:
void Cargar(int *vector, int alto) { int i,aux; for (i=0; i< alto;i++) { scanf(“%d”,%aux); *(vector+i)=aux; //Asigno el valor de aux al elemento “posición inicial del vector + i bloques de memoria para abajo” } }
Favaro Santiago 2° 2° E
14
Mas consideraciones para tener en cuenta en el uso de punteros (cuestiones con Matrices) Para matrices es exactamente igual que para vectores todos los comentarios que se pueden dar, pero hay algo que es muy útil: “mover” a un puntero de la posicón de memoria de la matriz[0][0] a cualquier otro lado como por ejemplo matriz[9][12]. La cosa sería así: Lo primero que hay que saber es que una matriz en la memoria esta ordenada como varios vectores cosecutivos; exactamente, está puesta toda la primera fila como un vector, y después la otra fila, etc. Un ejemplo más entendible es el siguiente: Supongamos una matriz declarada asi: Int x[3][3];
Ésta va a estar ordenada asi: X[0][0] X[0][1] X[0][2] X[1][0] X[1][1] X[1][2] X[2][0] X[2][1] X[2][2] Por lo tanto, podemos sacar la siguiente conclusión que es muy útil: x[2][1]=*(x+FILA*ANCHO_TOT+COLUMNA)=*(x+2*3+1) El 3 marcado es que significa que hay que poner la cantidad total de columnas (que es 3 y no 2 (este último caso sería considerando el 0, pero para esta fórmula no hay que considerar el 0).
Favaro Santiago 2° 2° E
15
Estructuras Una estructura, es una colección de datos de cualquier tipo. Declaración: Struct [etiqueta] { [declaración de variables] } [nombre de la estrcutura]; Donde: La declaración de variables son todas aquellas variables que se van a usar dentro de esta estructura, pueden ser de cualquier tipo, incluso vectores o matrices. El nombre de la estructura es un identificador para luego manejar a la estructura como si fuese una variable cualquiera. La estiqueta es opcional, para lo único que sirve es para poder declarar varias estructuras iguales sin tener que copiar y pegar toda la estructura las veces que sean necesarias. Ejemplo: Struct empleados { int edad; float sueldo; char nombre[10]; }datos; void main(void) { datos.edad=30; //Asigno el valor 30 al miembro edad de la estructura datos scanf(“%f”,&datos.sueldo); //Asigno un valor para el miebro sueldo de la estructura datos gets(datos.nombre); //Asigno una cadena al miembro nombre de la estructura datos } Este tema no es muy dificil de entender, lo único que hay que hacer es declarar una estructura (con cada variable que vamos a usar como lo veniamos haciendo); y luego cuando querramos usar esa estructura, ponemos su nombre, un punto (‘.’) y la variable que querramos usar dentro de esa estructura. Usos: El principal uso que se le da a las estructuras es el de poder acceder a archivos tanto para su lectura como a su escritura y por lo tanto su creación. Además se pueden usar para tener una buena organización en la programción, ya que mediante éstas, por ejemplo, se puede tener todos los datos de un empleado bajo “un mismo nombre de variable” (que vendría ser el nombre de la estructrura). Consideraciones: Si se tiene que declarar, por ejemplo, diez veces una misma estructura para tener diez estructuras de datos de diez trabajadores, se puede hacer lo siguiente: Struct empleados { int edad; float sueldo; char nombre[10]; }datos0; struct empleados {
Favaro Santiago 2° 2° E
16
int edad; float sueldo; char nombre[10]; }datos1; struct empleados { int edad; float sueldo; char nombre[10]; }datosn; // Donde n es el numero de empleado También una forma mejor es hacer lo siguiente: Struct empleados { int edad; float sueldo; char nombre[10]; }datos0; struct empleados datos1; struct empleados datos2; struct empleados datosn; Otra forma sería: Struct empleados { int edad; float sueldo; char nombre[10]; }datos0,datos1,datos2,datosn; Y también se puede hacer un vector de esa estructura de la siguiente forma: Struct empleados { int edad; float sueldo; char nombre[10]; }datos[10]; de esta forma, para acceder a cada empleado sería: datos[0].edad=25; // Para la edad del empleado 1 datos[9].nombre=gets(); // Para el nombre del ultimo empleado
Favaro Santiago 2° 2° E
17
Archivos Mediante el manejo de archivos, uno es capaz de guardar cualquier clase de información en la máquina sin problema que se pierda para la próxima vez que se corra nuestro programa. El siguiente es un ejemplo de cómo se utilizaría un archivo para la lectura: Void main (void) { char a; FILE *p; // Declaramos un puntero del tipo File que es el que va a guardar la dirección de memoria de un archivo determinado (dicha posición de memoria se “crea” cuando se abre un archivo) p=fopen(“c:\\casa.txt”,”rt”); //Mediante esta función, abrimos el archivo c:\casa.txt en este caso para lectura (rt). La función fopen necesita como primer parámetro la ruta en donde encontrar el archivo (las dos barras en realidad es para que se tomen una sola: la primera sirve para indicar que el siguiente carácter es uno especial); como segundo parámetro necesita el modo de apertura que en este caso es de lectura en forma de texto. Fopen(Ruta,modo_de_apertura). a=fgetc(p); //Lee el carácter actual y lo guarda en la variable ‘a’, es decir, que cuando apenas abrimos el archivo el primer carácter que va a leer es el primero, y si después pondríamos devuelta esta sentencia, leería el segundo, y así sucesivamente hasta que llega un momento que en vez de devolver un carácter llega al final del archivo y esto lo indica con una constante que se llama EOF. fclose(p); // Cerramos el archivo. Esto siempre se debe hacer siempre que dejemos de trabajar con ese archivo para no dejar cosas cargadas en memoria que no sirvan. La p es el nombre del puntero que declaramos al principio. } Modificares para el modo de apertura Modificador r
Función Abre un archivo como solo lectura
w
Crea un archivo para escritura. Sobrescribe si ya existe
a +
Anexa; abre un archivo y se coloca en la posición final del archivo (EOF) para poder escribir, o crea un archivo para escritura. Agrega un símbolo para permitir la lectura/escritura
b
Abre un archivo en forma binaria
t
Abre un archivo en forma de texto
Ejemplo completo de archivos #include #include #include #include
<stdio.h> <dos.h> <smGenLib.h>
void CrearF(void); void AnexarF(void); void LeerF(void); #define LargoRuta 200 void main(void) { char Op;
Favaro Santiago 2° 2° E
18
do { Op=mgMenu("Seleccione que desea hacer","Crear un archivo","Anexar datos a un archivo","Leer un archivo","Salir","",1); switch(Op) { case '1':{CrearF();break;} case '2':{AnexarF();break;} case '3':{LeerF();break;} } }while (Op!='4'); }
void CrearF(void) { FILE *f; char Ruta[LargoRuta],Op; clrscr(); printf("Ingrese la ruta para crear el archivo:\n"); gets(Ruta); if ((f=fopen(Ruta,"rt"))!=NULL) { Op=mgMenu("El archivo ya existe...","Para reemplazar","Para no borrarlo","","","",1); fclose(f); if (Op=='2') { printf("\nFue cancelada la creaci¢n del archivo."); goto Fin; } if ((f=fopen(Ruta,"wt"))==NULL) printf("\nNo se puede cancelada",Ruta); else printf("\nEl archivo %s se } else { if ((f=fopen(Ruta,"wt"))==NULL) printf("\nNo se puede cancelada",Ruta); else printf("\nEl archivo %s se } Fin: fclose(f);
escribir sobre el archivo %s. Acci¢n ha creado con exito",Ruta);
escribir sobre el archivo %s. Acci¢n ha creado con exito",Ruta);
delay(2500); }
void LeerF(void) { FILE *f; char Ruta[LargoRuta],Aux;
Favaro Santiago 2° 2° E
19
clrscr(); printf("Ingrese la ruta para leer el archivo:\n"); gets(Ruta); if ((f=fopen(Ruta,"rt"))==NULL) printf("\El archivo %s no existe",Ruta); else { Aux=fgetc(f); while (Aux!=EOF) { printf("%c",Aux); Aux=fgetc(f); } } fclose(f); printf("\nPresione una tecla para continuar..."); getch(); } void AnexarF(void) { FILE *f; char Ruta[LargoRuta],Aux; clrscr(); printf("Ingrese la ruta del archivo para anexar datos:\n"); gets(Ruta); if ((f=fopen(Ruta,"at"))==NULL) printf("\nEl archivo %s no existe",Ruta); else { printf("\nIngrese car cteres para anexar, termine apretando #:\n"); Aux=getch(); while (Aux!='#') { fputc(Aux,f); printf("%c",Aux); Aux=getch(); } } fclose(f); }
Favaro Santiago 2° 2° E
20
Código fuente de la librería smGenLib.h #include #include #include #include
<stdio.h> <string.h>
/*Modulo General de funciones comunes a los programas del colegio hecho por Santiago Favaro 2001*/
/*-------------------------------------------------------------Funci¢n que crea un menu para elegir como max. 5 opciones los parametros son: sTitulo: El titulo del menu sOpX: La opcion 1 hasta la 5, si se pasa una cadena vacia se toma como que no existe esa opci¢n iSombra: Menu con o sin sombra La funci¢n devuelve*/ char mgMenu(char[50],char[50],char[50],char[50],char[50],char[50],int); char mgMenu(char sTitulo[50],char sOp1[50],char sOp2[50],char sOp3[50],char sOp4[50],char sOp5[50],int iSombra) { #define cBorde 'Û' //Este es el caracter con que se van a hacer los bordes #define cSombra '±' //Este es el caracter con que se va a hacer la sombra int MaxCaracs,MaxOps=0,i; char Tecla; clrscr(); //Calculo la maxima cant. de caracteres para centrar el cuadro MaxCaracs=strlen(sTitulo); if (strlen(sOp1) > MaxCaracs) MaxCaracs=strlen(sOp1); if (strlen(sOp2) > MaxCaracs) MaxCaracs=strlen(sOp2); if (strlen(sOp3) > MaxCaracs) MaxCaracs=strlen(sOp3); if (strlen(sOp4) > MaxCaracs) MaxCaracs=strlen(sOp4); if (strlen(sOp5) > MaxCaracs) MaxCaracs=strlen(sOp5); //Calculo la cantidad if (strlen(sOp1) > 0) if (strlen(sOp2) > 0) if (strlen(sOp3) > 0) if (strlen(sOp4) > 0) if (strlen(sOp5) > 0)
maxima de menues MaxOps=MaxOps+1; MaxOps=MaxOps+1; MaxOps=MaxOps+1; MaxOps=MaxOps+1; MaxOps=MaxOps+1;
//Me posiciono en la esq. sup. izq. gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra); for (i=0;i<MaxCaracs/2*2+6;i++) {printf("%c",cBorde);} gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+1); printf("%c %s",cBorde,sTitulo); gotoxy(40+MaxCaracs/2+2,13-3-MaxOps/2-iSombra+1);
Favaro Santiago 2° 2° E
21
printf("%c",cBorde); if (iSombra==1) printf("%c",cSombra); gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+2); for (i=0;i<MaxCaracs/2*2+6;i++) {printf("%c",cBorde);} if (iSombra==1) printf("%c",cSombra); if (strlen(sOp1)!=0) { gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+3); printf("%c 1-%s",cBorde,sOp1); gotoxy(40+MaxCaracs/2+2,13-3-MaxOps/2-iSombra+3); printf("%c",cBorde); if (iSombra==1) printf("%c",cSombra); } if (strlen(sOp2)!=0) { gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+4); printf("%c 2-%s",cBorde,sOp2); gotoxy(40+MaxCaracs/2+2,13-3-MaxOps/2-iSombra+4); printf("%c",cBorde); if (iSombra==1) printf("%c",cSombra); } if (strlen(sOp3)!=0) { gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+5); printf("%c 3-%s",cBorde,sOp3); gotoxy(40+MaxCaracs/2+2,13-3-MaxOps/2-iSombra+5); printf("%c",cBorde); if (iSombra==1) printf("%c",cSombra); } if (strlen(sOp4)!=0) { gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+6); printf("%c 4-%s",cBorde,sOp4); gotoxy(40+MaxCaracs/2+2,13-3-MaxOps/2-iSombra+6); printf("%c",cBorde); if (iSombra==1) printf("%c",cSombra); } if (strlen(sOp5)!=0) { gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+7); printf("%c 5-%s",cBorde,sOp5); gotoxy(40+MaxCaracs/2+2,13-3-MaxOps/2-iSombra+7); printf("%c",cBorde); if (iSombra==1) printf("%c",cSombra); } gotoxy(40-MaxCaracs/2-3,13-3-MaxOps/2-iSombra+MaxOps+3); for (i=0;i<MaxCaracs/2*2+6;i++) {printf("%c",cBorde);} if (iSombra==1) printf("%c",cSombra); if (iSombra==1)
Favaro Santiago 2° 2° E
22
{ gotoxy(40-MaxCaracs/2-3+1,13-3-MaxOps/2-iSombra+MaxOps+4); for (i=0;i<MaxCaracs/2*2+6;i++) {printf("%c",cSombra);} } fflush(stdin); do { fflush(stdin); Tecla=getch(); }while(Tecla<49 || Tecla > 48+MaxOps); return(Tecla); } //--------------------------------------------------------------------// /*
FUNCION PARA DECIR QUE PALABRA ESTµ PRIMERA
Se le tiene que pasar las dos cadenas como vectores de caracteres de hasta 15 letras y la funci¢n devuelve: - 0 si la primera cadena esta primera - 1 si la segunda cadena esta primera - 2 si las dos son iguales*/ int mgSCompare(char c1[15],char c2[15]) { int j,Res=2; c1=strupr(c1); c2=strupr(c2); for (j=0;j<15;j++) { if ((c1[j]=='\0') && (c2[j]=='\0')) {break;} if (c1[j] < c2[j]) {Res=0;break;} if (c1[j] > c2[j]) {Res=1;break;} } return(Res); }
Favaro Santiago 2° 2° E
23