Funciones, Arreglos o Arrays, Punteros

7

Click here to load reader

description

programacion

Transcript of Funciones, Arreglos o Arrays, Punteros

Page 1: Funciones, Arreglos o Arrays, Punteros

FuncionesUna función es un conjunto de líneas de código que realizan una tarea específica y puede retornar un valor. Las funciones pueden tomar parámetros que modifiquen su funcionamiento. Las funciones son utilizadas para descomponer grandes problemas en tareas simples y para implementar operaciones que son comúnmente utilizadas durante un programa y de esta manera reducir la cantidad de código. Cuando una función es invocada se le pasa el control a la misma, una vez que esta finalizó con su tarea el control es devuelto al punto desde el cual la función fue llamada.

Ejemplo de una funciónPara comenzar, vamos a considerar el caso en el cual se desea crear la función cuadrado(), que deberá devolver el cuadrado de un número real (de punto flotante), es decir, cuadrado() aceptará números de punto flotante y regresará una respuesta como número flotante.

Nota: aunque para la función que veremos el tipo de retorno coincide con el tipo de parámetro pasado, algunas veces las cosas pueden cambiar, es decir, no es obligatorio que una función reciba un parámetro de un tipo y que tenga que regresar una respuesta de dicho tipo.

// regresar el cuadrado de un número

double Cuadrado(double n){ return n*n;}

Llamar a una funciónPara llamar a la función cuadrado() vista anteriormente, podemos emplear:

cout << cuadrado(25);cout << cuadrado(X);R = cuadrado(X); // guardar en R el cuadrado de X

Page 2: Funciones, Arreglos o Arrays, Punteros

Funciones voidBajo ciertas circunstancias se deseará escribir funciones que no regresen valor alguno (esto sería algo parecido a escribir procedures en Pascal) y para ello podemos declarar a la función como void. La palabra reservada void es utilizada para declarar funciones sin valor de retorno y también para indicar que una función específica no requiere de parámetros. Por ejemplo, la función pausa() que se verá en seguida, no devolverá valor alguno y la misma no requiere de parámetros.

// esta función requiere de la librería iostream

void pausa(void){ cout << "Por favor presione <Enter> HOLA..."; cin.get(); cin.ignore(255, '\n'); // rechazar caracteres introducidos antes de <Enter>

}

Notas: se debe de aclarar que el uso de la palabra void dentro de los parentesis es opcional al momento de declarar una función. Así, la función pausa() podría haberse declarado como void pausa(), y la misma puede invocarse como: pausa();.

Funciones de tipo puntero (*)En muchas ocasiones se desea que ciertas funciones regresen una referencia o puntero hacia un tipo (sea este estructurado o no) específico de dato en lugar de un valor específico. En tales casos, la función se deberá declarar como para que regrese un puntero.

Por ejemplo, supongamos que deseamos crear una función para convertir un número entero en notación decimal a una cadena de caracteres en forma de números binarios, luego, la función mencionada podría escribirse para que reciba el número entero como parámetro y regrese un puntero a una cadena de caracteres conteniendo la conversión.

Para ser más puntuales, vamos a escribir un programa en donde se verá la función binstr(), y cuyo objetivo será precisamente convertir números decimales en cadenas binarias.

Nota: observe que en la sintaxis para declarar funciones tipo puntero se debe de poner el símbolo * despues del tipo y antes del nombre de la función que se está declarando. Esto se puede ver en el programa, ya que la función binstr se declara como: char *binstr(unsigned int);

#include <iostream>#include <string.h>

using namespace std;

// declaración de prototipo

char *binstr(unsigned int);

// punto de prueba

int main(){ int n = 128; cout << "decimal = " << n << ", binario = " << binstr(n) << endl; cin.get();}

// definición de función binstr()

Page 3: Funciones, Arreglos o Arrays, Punteros

// nota: esta funcion requiere de la librería estándar string

char *binstr(unsigned int n){ static char buffer[65]; int i = 0;

strcpy(buffer, "0");

if (n > 0) { while (n > 0) { buffer[i] = ( n & 1 ) + '0'; i++; n >>= 1; } buffer[i] = '\0'; strrev(buffer); } // fin (n > 0)

return buffer;}

Arreglos o arrays en C++

Un arreglo en C++ es un conjunto de datos que se alamacenan en memoria de manera contigua con el mismo nombre. Para difenciar los elementos de un arreglo se utilizan índices detrás del nombre del arreglo y encerrados por []. El elemento 5° (quinto) de un arreglo, es representado por el índice [4], ya que los índices comienzan en 0. Esto significa que un arreglo de 10 elementos tendría los índices del 0 al 9: [0...9]

Ejemplos:

int arregloEntero[10]; //Declaracion de un arreglo de 10 elementos, sin inicializar. arregloEntero[5] = 45; //Asignacion de 45 al elemento 6 del arreglo.

double arrPuntoFlotante[3] = {1.1,1.2,1.3}; //Declaracion y asignacion en un arreglo de 3 elementos double.

int a[4], b[5]; //Declaracion de dos arreglos enteros, de 4 y 5 elementos.

Ahora veamos un ejemplo, donde se trata un arreglo de 10 elementos con ciclos for:

//Uso de arreglos en C++#include <iostream>using std::cout;using std::cin;using std::endl;int main(){ int arregloEntero[10] = {0}; //Arreglo entero de 10 elementos inicializados todos en 0.

Page 4: Funciones, Arreglos o Arrays, Punteros

cout << "Arreglo recien declarado: " << endl; for (int i = 0 ; i < 10 ; i++) //Notar el menor estricto (<) para ir desde 0 hasta 9 cout << "arregloEntero["<<i<<"]="<<arregloEntero[i] << endl; cout << "Introduzca 10 nuevos valores " << endl; for (int i = 0 ; i < 10 ; i++) //Notar el menor estricto (<) para ir desde 0 hasta 9 { cout << " Introduzca nuevo valor paraarregloEntero["<<i<<"]" << endl; cin >> arregloEntero[i]; } cout << "Luego de los valores introducidos, el arreglo quedo asi: " << endl; for (int i = 0 ; i < 10 ; i++) //Notar el menor estricto (<) para ir desde 0 hasta 9 cout << "arregloEntero["<<i<<"]="<<arregloEntero[i] << endl; return 0;}

PunterosUn puntero es una variable que contiene la dirección de memoria de un dato o de otra variable que contiene al dato. Quiere esto decir,

que el puntero apunta al espacio físico donde está el dato o la variable. Un puntero puede apuntar a un objeto de cualquier tipo, como por

ejemplo, a una estructura o una función. Los punteros se pueden utilizar para referencia y manipular estructuras de datos, para referenciar

bloques de memoria asignados dinamicamente y para proveer el paso de argumentos por referencias en las llamadas a funciones.

Muchas de las funciones estandares de C, trabajan con punteros, como es el caso del scanf o strcpy. Estas reciben o devuelve un valor

que es un puntero. Por Ej. A scanf se le pasa la dirección de memoria del dato a leer (esto es un puntero)...

char a;

scanf ("%c",&a);

Declarando punterosYa se dijo que un puntero es una variable que guarda la dirección de memoria de otra variable, haciendo logica a esto, decimos que un

puntero se declara igual que cualquier otra variable, pero anteponiendo un * (asterisco) antes del nombre de la variable.

Su sintaxis seria:

tipo *NombrePuntero;

Donde tipo es el tipo de dato al que referenciará este puntero, es decir, que si se necesita guardar la dirección de memoria de un

dato int, se necesita un puntero de tipo int.

ExplicaciónVeamos el siguiente codigo:

Page 5: Funciones, Arreglos o Arrays, Punteros

#include <stdio.h>

int main()

{

int a=0; //Declaración de variable entera de tipo entero

int *puntero; //Declaración de variable puntero de tipo entero

puntero = &a; //Asignación de la dirección memoria de a

printf("El valor de a es: %d. \nEl valor de *puntero es: %d. \n",a,*puntero);

printf("La direccion de memoria de *puntero es: %p",puntero);

return 0;

}

Igual que cuando usamos un &, en la lectura de datos con scanf, igual de esta forma lo usamos aquí, tal vez te acordaras que decíamos que

las cadenas de caracteres (%s) no usaban este operador, esto es por que en una cadena de caracteres es un arreglo de caracteres, por lo

que el primer carácter es la dirección de inicio de la cadena.

El operador *, nos permite acceder al valor de la direccion del puntero, en este caso nos permite acceder al valor que contiene a la variable

a. De esta forma "a" y "*puntero" muestran el mismo dato, pero esto no quiere decir que sea lo mismo, uno es un entero el otro un puntero.

La impresión con %p, es para poder imprimir la dirección de memoria en valor hexadecimal (0x...), también podemos imprimir: ...%p",&a) y

funciona de la misma forma, y es lógico que tanto a, como puntero tienen la misma dirección de memoria.

Diferentes direcciones?

Tal vez notaste que en cada ejecución la dirección de memoria cambia, esto es por que es el sistema operativo es quien esta encargado de

administrar la memoria y es este quien dice que espacios podra tomar el programa.

Esto quiere decir que uno no puede asignarle una dirección de memoria a un puntero directamente, es decir yo no puedo hacer lo siguiente.

int *puntero=0xbfc5b1c8;

Esto no puedo ni debo hacerlo ya que yo no se que esta haciendo esta dirección de memoria, si el sistema la tiene o no disponible, etc...

Pero si puedo hacer esto:

int *puntero=NULL;

NULL, es el espacio en memoria con dirección 0, esto quiere decir que existe, lo que significa que le asignamos una direccion valida al

puntero, pero el valor que tiene NULL no se nos permite modificarlo, ya que pertenece al sistema.