lenguaje de programacion

Page 1

PROGRAMANDO EN C++ DEFINICION EJEPLOS


I

N

T

R

O

D

U

C

C

I

O

N

Estos apuntes corresponden a un peque単o intento de ordenar los temas

abordados en el curso de Computacion para Matematicos dictado el Primer Semestre de 1998. No pretendo que sean tomados muy en serio, en el sentido que estan dise単ados para satisfacer las minimas necesidades del curso, sirviendo como un ayuda-memoria de los topicos abordados, para futura referencia. No se consideran todas las posibilidades del lenguaje, y las explicaciones estan reducidas al minimo o estan ausentes del todo, de modo que creo son mas utiles para quienes ya sepan algo de C++ (idealmente los alumnos del curso una vez terminado este) y quieran recordar algun detalle de sintaxis ya olvidado. Tambien pueden servir para personas con alguna experiencia en otros lenguajes de programacion y que deseen comenzar el aprendizaje de C++. El mundo esta lleno de manuales a los cuales se puede acudir en caso de urgencias mas elevadas. Solo el Tiempo y mi tiempo diran

si estos apuntes seran extendidos alguna vez.


ESTRUCTURAS EN C++ Las estructuras de datos se emplean con el objetivo principal de organizar los datos contenidos dentro de la memoria del ordenador. Así, nuestra primera experiencia con estructuras comienza desde el momento mismo en que usamos en nuestros programas variables de tipos primitivos (char, short, int, float, etc). A la memoria del ordenador se le puede considerar como un gran bloque compuesto por una serie de BYTES dispuestos secuencialmente uno detrás de otro. por ejemplo, si un ordenador posee una memoria de 128MB (128 megas) entonces se le puede leer o escribir desde el BYTE 0 hasta el BYTE 128MB - 1 ( 0000000H .. 7FFFFFFH ). La idea de ver la memoria como un serie de bytes es buena, sin embargo no es suficiente ya que en la misma podemos guardar números, cadenas de caracteres, funciones, objetos, etc. de tal manera que surge la necesidad de establecer los mecanismos adecuados para dar cuenta de la forma, tamaño y objetivo de los datos almacenados. Según el tipo de microprocesador, estos tienen la capacidad para manipular o direccionar estructuras compuestas por uno, dos, cuatro, etc, bytes; de donde se derivan los tipos que comunmente se conocen como: BYTE, WORD, DWORD, QWORD y TWORD. La estructura mínima de información manipulable en un sistema de memoria de ordenadores es el BIT el cual se agrupa normalmente en bloques de 8 para formar un BYTE. Cabe mencionar que los BITS no son direccionables directamente, sino a travez de compuertas AND, OR, NOT, XOR, mismas que en C,C++ se escriben como &, |, ~ y ^ conocidos como "Bitwise operators". En C,C++ existe una serie de estructuras básicas o tipos primitivos, los cuales pueden ser usados por el programador para declarar variables, y también son el fundamento sobre el cual se crean estructuras complejas. El tamaño de los tipos primitivos no es estándar ya que los mismos dependen de factores tales como: * Tipo del microprocesador * El compilador Sin embargo, en la actualidad, la mayoria de compiladores de C,C++ soportan los siguientes tipos con la longitud indicada:


Estructuras básicas en C, C++ Tipos primitivos Nombre común BYTE char 8 bits WORD short 16 bits DWORD int 32 bits DWORD long 32 bits DWORD float 32 bits QWORD double 64 bits TWORD long double 80 bits

Nombre C

Longitud

Matrices o Arreglos Una Matriz (en inglés, array, también denominado arreglo) es una estructura usada para agrupar bajo un mismo nombre listas de datos de un mismo tipo. Matrices estáticas Una matriz estática es una estructura cuyo tamaño es determinado en tiempo de compilación, es decir, una vez establecido el tamaño de la matriz ésta no podrá cambiarse durante el tiempo de ejecución. En C, C++ para declarar un arreglo estático de datos se emplea la sintaxis: tipo identificador[ [tamaño] ] [ = { lista de inicialización } ] ; donde, * tipo se refiere al tipo de datos que contendrá la matriz. El tipo puede ser cualquiera de los tipos estándar (char, int, float, etc.) o un tipo definido por el usuario. Es más, el tipo de la matriz puede ser de una estructura creada con: struct, union y class. * identificador se refiere al nombre que se le dará a la matriz. * tamaño es opcional e indica el número de elementos que contendrá la matriz. Si una matriz se declara sin tamaño, la misma no podrá contener elemento alguno a menos que en la declaración se emplee una lista de inicialización. * lista de inicialización es opcional y se usa para establecer valores para cada uno de los componentes de la matriz. Si la matriz es declarada con un tamaño especifíco, el número de valores inicializados no podrá ser mayor a dicho tamaño. Ejemplos: int intA[5]; long longA[5] = { 1, 2, 3, 4, 5 }; char charA[] = { 'a', 'b', 'c' };


Acceso a los miembros de una matriz de datos: En orden de acceder a los miembros de una matriz se debe indicar el nombre de la matriz seguido de dos corchetes, dentro de los cuales se debe especificar el índice del elemento deseado. Se debe aclarar que los índices son números o expresiones enteras y que en C, C++ estos tienen un rango permitido de 0 a T-1 ( T = tamaño de la matriz ). Ejemplos: dadas las matrices intA, charA, longA ( ejemplo anterior ) intA[0] = 100;

// establece el valor del elemento 0 de intA a 100.

charA[3] = 'O';

// establece el valor del elemento 3 de charA a 'O'.

cout << longA[0];

// muestra por pantalla el elemento 0 de longA, que es longA[0].

Matrices dinámicas Una matriz dinámica es una estructura compleja y, ya que C estándar no da el soporte para operar con estos tipos de estructuras, le corresponde al programador crear los algoritmos necesarios para su implementación. Crear lista dinámicas de datos en C estándar no es una tarea para programadores inexpertos, ya que para lograr tal objetivo se necesita tener conocimentos solidos acerca de los punteros y el comportamiento de los mismos. Los usuarios de C++ pueden auxiliarse de la librería estándar de plantillas, conocidas por sus siglas en ingles como STL.Estructuras compuestas (struct, union, class) Con base en los tipos básicos mostrados arriba, se pueden crear nuevos tipos con estructuras compuestas por uno o más de uno de los tipos mencionados. En C, C++ en orden de crear nuevas estructuras se emplean la palabras reservadas struct, union y class. * struct: esta orden se emplea para agrupar variables de tipos iguales o diferentes en un solo registro, con la misma se pueden crear estructuras anónimas, estructuras con nombre, y un tipo especial de estructura conocida como bit-fields ( banderas o campos de bits ). * union: una union es similar a una struct, salvo que en una estructura creada con union los campos o variables comparten una dirección de almacenamiento común. * class: una clase es una estructura en donde se agrupan variables y funciones, la misma es usada en Programación Orientada al Objeto. Las clases no son soportadas por el C estándar.


Sintaxis general: struct struct [ <nombre tipo de estructura > ] { [ <tipo> <nombre-variable[, nombre-variable, ...]> ] ; [ <tipo> <nombre-variable[, nombre-variable, ...]> ] ; ... } [ <variables de estructura> ] ; Nota: recuerde que lo que se muestra entre corchetes es opcional. struct: Sintaxis ( variación uno, estructura anónima ) De acuerdo con la sintaxis general de la orden struct es posible crear estructuras de datos anónimas. Solamente hay que tener en cuenta que en una declaración anónima se debe definir al menos una variable al final de la declaración. Por ejemplo, con el siguiente fragmento de código: struct { int a, b; } p1; se declara y define la variable estructurada p1, misma que se compone por los miembros a y b; ambos del tipo int. Ahora bien, la sintaxis mostrada arriba no es tan común ni conveniente, ya que con la misma solamente se esta creando una variable estructurada pero no un nuevo tipo. Es decir, si desearamos tener otra variable que tuviera las mismas caracteristicas que posee la variable p1, necesitariamos escribir exactamente la misma instrucción, salvo que cambiando el nombre de la variable. Por ejemplo: struct { int a, b; } p2; Por supuesto, en una misma línea de instrucción podemos definir más de una variable. Ejemplo: struct { int a, b; } p1, p2; Entonces, para crear nuevos tipos con struct deberemos de modificar la sintaxis mostrada en los ejemplos anteriores.


Sintaxis: struct ( variación dos, estructura con nombre ) Observe que, la sintaxis para declarar estructuras con nombre es bastante parecida a la sintaxis para declarar estructuras anónimas; salvo que una declaración de estructura con nombre se debe especificar el nombre deseado para la misma. Además, en una declaración de estructura con nombre la o las variables definidas al final de la misma son opcionales. Ejemplos: struct pareja { int a, b; } p1; En el fragmento de código anterior se declara la estructura identificada como pareja, misma que se compone de los miembros a y b, ambos de tipo int. En el mismo ejemplo, se define la variable p1; la cual es una variable estructurada de tipo pareja. Una vez que una estructura con nombre ha sido creada, la misma puede ser usada para declarar cualquier número de variables. Por ejemplo, en el siguiente fragmento de código se crea la estructura tiempo compuesta por los miembros hora, minuto y segundo; todos del tipo int. En el mismo ejemplo, se declaran las variables t1 y t2. /* declaración de estructura tiempo */ struct tiempo { int hora, minuto, segundo; }; /* declaración de variables de tipo tiempo */ struct tiempo t1, t2; Nota: en C++ puede olviarse la palabra struct a la hora de declarar variables. Así, en C++ la línea de instrución struct tiempo t1, t2; ( del ejemplo anterior) puede escibirse como: tiempo t1, t2; Acceso a los miembros de una estructura En orden de poder leer o escribir uno de los miembros de una variable estructurada se debe usar el operador de acceso ( . ), o sea, el nombre de la variable seguida por un punto seguido por el nombre del miembro o componente deseado de la estructura. Por ejemplo, para acceder a los miembros de la variable t1 (mostrada arriba) podemos hacerlo de la siguiente manera: t1.hora = 12; t1.minuto = 0; t1.segundo = 0; printf ("%i\n", t1.hora); cout << t1.minutos << endl;


Estructuras anidadas Los miembros de una estructura pueden ser ellos mismos otra estructura previamente identificada o bien una estructura anรณnima. Por ejemplo, en el siguiente fragmento de cรณdigo se crean las estructuras pareja y pareja2. Observese cรณmo dentro de los miembros de pareja2 se declara el miembro X, mismo que es una estructura del tipo pareja. Luego, las variables declaradas a raiz de la estructura pareja2 poseerรกn los miembros variables a y b heredados de pareja, y c. struct pareja { int a, b ; }; struct pareja2 { struct pareja X; int c; } P3; Ahora bien, para acceder a los miembros de una estructura dentro de otra estructura se emplea el mismo mecanismo de acceso (el punto). Por ejemplo, para desplegar el miembro a de la variable P3 declarada en el ejemplo anterior, lo haremos mรกs o menos asรญ: printf( "%i\n", P3.X.a ); Estructura de campos de bits Un campo de bit es un elemento de una estructura definido en terminos de bits. Usando un tipo especial de definicion de struct, se pueden declarar elementos de estructura con rangos de 1 a 16 de largo. (dependiendo de la arquitectura de la PC y del compilador, el rango para una estructura de campos de bits puede ser de 1 a 16, 1 a 32, 1 a 64). Antes de ver un ejemplo del uso de struct para crear estructuras de campos de bits consideremos el caso en donde se tiene una variable del tipo short (16 bits) y que para la misma se desea que los bits tengan significados especificos. digamos que el primer bit servirรก para controlar alguna condiciรณn; los siguientes cuatro bits, o sea del segundo al quinto bit, controlarรกn otra condiciรณn; el bit 6 tendrรก otra funcion; y el resto, o sea del septimo al decimosexto bit se emplearรกn para contralar otra condiciรณn. De tal manera que si queremos, por ejemplo, saber si el primer bit de la variable tiene almacenado un 1 o un 0 podemos emplear la siguiente sintaxis: int X = 123; int r = X & 1; la cosa parece sencilla, pero ahora consideremos el caso en el cual deseamos saber cual es el valor contenido por el grupo de bits ( segundo al quinto ), entonces nos daremos cuenta que no basta con una prueba mediante AND ( X & 1 ) sino que hay que realizar otros pasos. Precisamente, para problemas como el planteado arriba es que el lenguaje C,C++ da soporte a las estructuras de campos de bits. Por ejemplo, la estructura struct campo_de_bit { int bit_1 : 1; int bits_2_a_5 : 4; int bit_6 : 1; int bits_7_a_16 : 10; } bit_var;


corresponde a la siguiente colección de campos bits:

El mecanismo de estructuras de campos de bits soportado por C,C++ es una herramienta útil y poderosa, sobre todo en programación de bajo nivel; ya que mediante el mismo es posible aislar y dar nombres a todos y cada de los bits de un dato y también crear en un mismo campo grupos de bits (como se muestra arriba). Ahora bien, no hay que olvidar que la estructura minima de información en un sistema de memoria de una PC es el bit, y que para aislar a cada uno de estos se puede emplear el operador AND ( &, en C ), pero mediante el mecanismo mencionado el compilador genera los algoritmos necesarios para llevar a cabo el aislamiento de los bits. Por ejemplo, para escribir y leer bit identificado como bit_1 de la variable bit_var del ejemplo anterior, podemos emplear las siguientes instrucciones: bit_var.bit_1 = 1; printf("%i\n", bit_var.bit_1 ); Nota: acerca de las estructuras de campos de bits hay que hacer la aclaración que, aunque cada uno de los campos de la estructura pueden declarse como enteros con signo o enteros sin signo, la misma no tendrá una longitud mayor a un entero largo. union: Sintaxis general union [ <nombre tipo de union > ] { <tipo> <lista de variables>; } [ <variables de union> ] ; * De la misma manera que con la orden struct, con la orden union se pueden crear estructuras con nombre y estructuras sin nombre. * El mecanismo de acceso a los miembros de una union es igual al mecanismo de acceso a los miembros de una struct. * Los miembros de una union comparten un espacio de almacenamiento común. * En una union, el compilador reserva el espacio de almacenamiento para la misma de acuerdo con el el tipo de la variable de mayor tamaño.


Ejemplo: union anónima union { short a; long b; } u1; En el ejemplo anterior se declara la variable u1, la cual es una estructura tipo union. El espacio de almacenamiento para la variable a es compartido por la variable b, en consecuencia, al escribir sobre cualquiera de estas dos variables se altera el contenido de ambas. Ejemplo: union con nombre union ux { short a; long b; } u1; En el ejemplo anterior se declara la variable u1, la cual es una estructura tipo union. El espacio de almacenamiento para la variable a es compartido por la variable b. Es decir, el compilador reservará espacio en la memoria para la variable de mayor tamaño (que para éste caso es b ). Ahora bién, suponiendo que en su equipo el tipo long ocupa 32 bits y que el tipo short ocupa 16 bits, entonces la variable a ocupará solamente los 16 bits menos significativos, miemtras que la variable b ocupará todo el espacio, o sea los 32 bits; Observe que en la sintaxis se ha especificado el nombre ux, mismo que puede ser empleado para declarar cualquier número de variables de la union. Por ejemplo, a continuación se declaran las variables u2 y u3 del tipo union ux creado en el ejemplo anterior. union ux u2, u3;


ESTRUCTURAS EN JAVA * <classkey> es una de las palabras "class", "struct", o "union". * <baselist> lista de clas(es) base de donde se deriva esta clase. <baselist> es opcional. * <member list> declara los datos miembros y funciones miembros de la clase. * [lista de variables] esta entrada es opcional y se usa para instanciar variables u objetos de esta clase. Nota: Dentro de una clase, * los datos son llamados "datos miembros" * las funciones son llamadas "funciones miembros". * El mecanismo para acceder a los miembros de una class es igual que aquel utilizado para acceder a los miembros de una struct Las clases son algo así como "super" estructuras capaces de agrupar no solo datos miembros sino también funciones miembros. En el lenguaje común a los datos miembros de una clase se les conoce como atributos; mientras que a las funciones miembros de una clase se les llama métodos. Normalmente, los métodos se emplean para leer o escribir los atributos. Es decir, la norma general es no permitir el acceso directo a los atributos de una clase, con la idea de aumentar la seguridad de los datos. En seguida se mostrará el código para crear la clase Pareja, misma que poseerá los atributos a y b, y los métodos setA(), setB(); getA(), getB(), y mostrar(); class Pareja { int a, b; public: void setA(int n) { a = n; } void setB(int n) { b = n; ) int getA() { return a; } int getB() { return b; } void mostrar() { cout << "a = " << a << "; b = " << b << endl; } } p1; Nota: por omisión, los miembros de una clase son privados, lo cual significa que los objetos instanciados de dicha clase no tendrán acceso a los mismos. Así, en el ejemplo anterior se está creando la clase Pareja, y al mismo tiempo el objeto p1. Luego, para leer o escribir los atributos de p1 se debe hacer a traves de los métodos definidos con tal objetivo. Por ejemplo, con el siguiente fragmento de código se establecen respectivamente a 100 y a 200 los atributos a y b; y posteriormente se despliegan por medio del método mostrar().


LISTAS EN C++ Una lista es una estructura de datos que nos permite agrupar elementos de una manera organizada. Las listas al igual que los algoritmos son importantísimas en la computación y críticas en muchos programas informáticos. Las listas están compuestas por nodos, estos nodos tienen un dato o valor y un puntero a otro(s) nodo(s). Existen varios tipos de listas: Simplemente enlazada, doblemente enlazada, circular simplemente enlazada, circular doblemente enlazada. Vamos a revisar las listas enlazadas simples, por ser el punto de partida y fundamentales para poder entender las otras. Una lista enlazada tiene un conjunto de nodos, los cuales almacenan 2 tipos de información: El dato que contienen y un puntero al siguiente nodo en la lista. El último nodo de la lista tiene como siguiente nodo el valor NULL. Entonces las listas enlazadas simples solo pueden ser recorridas en una dirección, apuntando al nodo siguiente, mas no a un nodo anterior.

LISTAS SIMPLES EN C++ La forma más simple de estructura dinámica es la lista abierta. En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el último no apunta a nada, es decir, el puntero del nodo siguiente vale NULL. En las listas abiertas existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo o llamaremos a ese nodo la cabeza de la lista. Eso es porque mediante ese único puntero podemos acceder a toda la lista. Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está vacía. El nodo típico para construir listas tiene esta forma:


ejemplo include <stdio.h> struct _agenda { char nombre[20]; char telefono[12]; struct _agenda *siguiente; }; struct _agenda *primero, *ultimo; void mostrar_menu() { printf("\n\nMenú:\n=====\n\n"); printf("1.- Añadir elementos\n"); printf("2.- Borrar elementos\n"); printf("3.- Mostrar lista\n"); printf("4.- Salir\n\n"); printf("Escoge una opción: ");fflush(stdout); } /* Con esta función añadimos un elemento al final de la lista */ void anadir_elemento() { struct _agenda *nuevo; /* reservamos memoria para el nuevo elemento */ nuevo = (struct _agenda *) malloc (sizeof(struct _agenda)); if (nuevo==NULL) printf( "No hay memoria disponible!\n"); printf("\nNuevo elemento:\n"); printf("Nombre: "); fflush(stdout); gets(nuevo->nombre); printf("Teléfono: "); fflush(stdout); gets(nuevo->telefono); /* el campo siguiente va a ser NULL por ser el último elemento de la lista */ nuevo->siguiente = NULL; /* ahora metemos el nuevo elemento en la lista. lo situamos al final de la lista */ /* comprobamos si la lista está vacía. si primero==NULL es que no hay ningún elemento en la lista. también vale ultimo==NULL */ if (primero==NULL) { printf( "Primer elemento\n"); primero = nuevo; ultimo = nuevo; } else { /* el que hasta ahora era el último tiene que apuntar al nuevo */ ultimo->siguiente = nuevo; /* hacemos que el nuevo sea ahora el último */ ultimo = nuevo;


Listas doblemente enlazadas Una lista doblemente enlazada es una lista lineal en la que cada nodo tiene dos enlaces, uno al nodo siguiente, y otro al anterior. Las listas doblemente enlazadas no necesitan un nodo especial para acceder a ellas, pueden recorrerse en ambos sentidos a partir de cualquier nodo, esto es porque a partir de cualquier nodo, siempre es posible alcanzar cualquier nodo de la lista, hasta que se llega a uno de los extremos. El nodo típico es el mismo que para construir las listas que hemos visto, salvo que tienen otro puntero al nodo anterior: struct nodo \{ int dato; struct nodo *siguiente; struct nodo *anterior; }; typedef struct _nodo \{ int dato; struct _nodo *siguiente; struct _nodo *anterior; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Lista;

Listas circulares Una lista circular es una lista lineal en la que el último nodo a punta al primero. Las listas circulares evitan excepciones en la operaciones que se realicen sobre ellas. No existen casos especiales, cada nodo siempre tiene uno anterior y uno siguiente. En algunas listas circulares se añade un nodo especial de cabecera, de ese modo se evita la única excepción posible, la de que la lista esté vacía. El nodo típico es el mismo que para construir listas abiertas:


struct nodo \{ int dato; struct nodo *siguiente; }; typedef struct _nodo \{ int dato; struct _nodo *siguiente; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Lista;


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.