sábado, 11 de diciembre de 2021

INTRODUCCIÓN


¿Qué es C++?

 

Es un lenguaje de programación de propósito general que combina distintos paradigmas o modelos de programación. El lenguaje nació en la década de los ochenta en los laboratorios Bell de AT&T, donde fue diseñado por el Profesor Bjarne Stroustrup. Inicialmente conocido como “C con clases”, empezó a ganar popularidad muy rápido y a principios de los años 90 comenzó su proceso de normalización. 


IMPORTANCIA DEL C++

C++ es uno de los lenguajes más usados. Según las estimaciones realizadas por la consultora IDC, el número de desarrolladores que usan C++ está por encima de los 3 millones. Especialmente desde 2010 hay un interés renovado por el lenguaje, puesto que tanto en las aplicaciones móviles como en los grandes centros de datos el rendimiento por vatio (cantidad de cálculos realizados por cada vatio de energía consumido) se ha convertido en una métrica fundamental.


¿Qué ventajas tiene respecto a otros lenguajes de programación?

 

El lenguaje C++ tiene una orientación clara hacia el uso eficiente de los recursos y al mismo tiempo permite construir abstracciones complejas que hagan uso de los computadores. Si bien es cierto que existen otros lenguajes de programación que pueden competir en el uso eficiente de los recursos, normalmente fracasan en la gestión de la complejidad. En resumen, no existen muchas más alternativas para escribir software complejo si se desea obtener un buen rendimiento. Por esta razón, C++ triunfa especialmente en el desarrollo de sistemas de software complejo que necesita una alta velocidad o bien necesita ejecutarse en entornos muy restringidos. Esto hace que el lenguaje sea usado desde en aplicaciones de simulación financieras hasta en sistemas de control de vehículos. Como curiosidad, una parte relevante del software que controla la sonda Mars Rover está escrita en C++.



Todo principiante en el campo de la programación se enfrenta a numerosos interrogantes. Independientemente de si se trata de la codificación, de los métodos o de sus herramientas, sin experiencia es muy difícil tener una visión general. Aprender a programar desde cero es una tarea compleja, especialmente si quieres aprenderlo por tus propios medios. En estas secciones hemos resumido aspectos importantes y que necesitas saber para dar tus primeros pasos en el mundo del código, de los comandos y del lenguaje en C++.

viernes, 10 de diciembre de 2021

ARREGLOS EN C++

Expresado formalmente, un Array o Arreglo de datos, es una estructura de datos que permite almacenar un conjunto de datos del mismo tipo, definiendo el intervalo con un límite inferior y un límite superior, con un número denominado Índice hacemos referencia a cada elemento individual del arreglo. Se utilizará indistintamente el término Array o Arreglo.

Para comprender mejor los arrays, resulta muy útil la siguiente descripción gráfica.


La sintaxis para definir un arreglo en C++ es la siguiente:

TipoDato nombreArray[TamañoArray];

en donde,

TipoDato: Tipo de dato que tendrán los elementos del arreglo.
nombreArray: Nombre que asignamos para referirnos al arreglo.
TamañoArray
: Valor entero que delimita el tamaño del arreglo.

 Declarando un Arreglo

Si deseamos declarar un arreglo llamado arrTemp con 5 elementos de punto flotante, debemos hacerlo de esta forma:

float arrCalif[5]; //Declara un arreglo de 5 elementos de punto flotante llamado arrCalif

También podemos declarar una arreglo sin límites predeterminados,

float arrCalif[ ]; //Declara un arreglo de elementos de punto flotante llamado arrCalif sin límite.

Accediendo a los elementos del Arreglo

Nota: Los índices de los arreglos se numeran a partir de 0, de modo que si un arreglo tiene por ejemplo 4 elementos, los índices serán 0, 1, 2, 3

Para acceder a un elemento del arreglo debemos usar el nombre del arreglo utilizando el índice del elemento que nos interesa. Por ejemplo, si queremos asignar los valores 2, 5, 8, -9, 100 al arreglo arrTemp lo haremos de la siguiente forma:

arrTemp[0] = 2;

arrTemp[1] = 5;

arrTemp[2] = 8;

arrTemp[3] = -9;

arrTemp[4] = 100;

Para que visualices lo que hemos hecho hasta el momento, apóyate en la siguiente imagen.

Acceso a los elementos de un Arreglo
 

Podemos recuperar de varias formas un elemento de un arreglo, pero el concepto siempre es el mismo, tomar el índice del elemento que nos interesa y asignarlo a una variable del mismo tipo. 

Por lo tanto en resumen un arreglo en C++ es un conjunto de datos que se almacenan en memoria de manera contigua con el mismo nombre. Para diferenciar los elementos de un arreglo se utilizan índices detrás del nombre del arreglo y encerrados por [ ].

EJEMPLO: int vector [10]; // array de 10 enteros: vector[0]..vector[9].

 

Arreglos unidimensionales en C++


En el lenguaje C++ un arreglo puede tener varias dimensiones, en esta ocasión hablaremos de los arreglos unidimensionales (una dimensión).

Arreglos Unidimensionales

Un arreglo unidimensional es una lista de valores guardados bajo el mismo nombre y del mismo tipo. Cada valor dentro del arreglo se le conoce como elemento del arreglo.

Para declarar un arreglo unidimensional en C++ se utiliza la siguiente línea de código:

tipo_dato identificador[tamaño];

En “tipo de dato” introduciremos que tipo de dato queremos (int, char, float.. etc) , luego en “identificador” introducimos como llamaremos a nuestro arreglo para ubicarlo e identificarlo de manera rápida. Y entre los corchetes colocaremos el tamaño que le demos a nuestro array. Quedando de esta manera:

int arreglo[3];

Ya que tenemos declarado nuestro arreglo necesitamos declarar cada uno de los elementos que lo conforman, para esto utilizamos lo siguiente:


Iniciamos con el nombre de nuestro arreglo en el apartado que dice arreglo, entre los corchetes colocaremos que parte del array utilizaremos, en C++ los valores se inician en 0, esto quiere decir que si nuestro arreglo es de tamaño 3, al hacer nuestro índice hay que tomar el 0 como valor inicial quedando [0] , [1] y [2] completando así nuestros 3 valores del tamaño antes mencionado.

En la parte “valor” asignaremos el valor que le daremos a ese elemento quedando de la siguiente manera:

 Ejemplo: el siguiente programa carga el arreglo sqrs con los cuadrados de los números del 1 al 10 y luego los visualiza .


La forma como se almacenan los valores en el arreglo es la siguiente:

sqrs[0] = 1*1

sqrs[1] = 2*2

sqrs[2] = 3*3

sqrs[3] = 4*4

sqrs[4] = 5*5

sqrs[5] = 6*6

sqrs[6] = 7*7

sqrs[7] = 8*8

sqrs[8] = 9*9

sqrs[9] = 10*10

ARREGLOS BIDIMENSIONALES


¿Qué es un “Arreglo bidimensional”?: Es una matriz de datos de tamaño m x n que contiene información almacenada del mismo tipo de datos (int, float, char, etc). Este tipo de arreglos necesita dos subíndices para ser declarado o para acceder a la información de un elemento en específico, a diferencia de una matriz unidimensional que solo necesita un subíndice. Un arreglo bidimensional es utilizado cuando queremos guardar mucha información sobre un tipo de dato en específico en distintas filas. Por ejemplo, si quieres crear una base de datos donde queremos guardar varios nombres, en un vector no se podría hacer pues solo podrías guardar un nombre, en cambio, con un arreglo bidimensional puedes guardar un nombre por fila, por lo tanto, si creamos varias filas podemos guardar varios nombres.

 

¿Cómo declarar un arreglo bidimensional?: La sintaxis para declarar un arreglo bidimensional es la siguiente:

Código:

tipo_dato nombre_arreglo [tamaño_fila][tamaño_columna];

Donde:

·         tipo_dato: Nos referimos al tipo de dato que estaremos manejando en el arreglo, puede ser char, int, float, etc.

·         nombre_arreglo: El nombre con el que identificaremos nuestra matriz.

·         tamaño_fila: La cantidad de filas que tendrá nuestra matriz.

·         tamaño_columna: La cantidad de columnas que tendrá nuestra matriz.

Por ejemplo, si queremos crear una matriz de 3 filas y 4 columnas de tipo de dato int y con nombre “matriz”, lo haríamos de la siguiente manera:

Código:

int matriz[3][4];

Esta matriz tendría 12 espacios para guardar información (3x4), y gráficamente lo veríamos de la siguiente manera:


Inicialización de un arreglo bidimensional: Podemos inicializar un arreglo bidimensional al momento de declararlo, indicando los valores que queremos entre corchetes y separados por coma, por ejemplo:

Código:

int matriz[4][5] = {1,2,3,4,5,6,7,8,9,10,11,12};

Y gráficamente los valores estarían guardados de la siguiente manera:


 

Ejercicio

Realizar un programa en el que se puedan guardar 5 nombres de máximo 20 caracteres. El usuario ingresará los nombres que quiere guardar y posteriormente se mostrarán los nombres que ingresó.

Programa

Código:

/* Introducción a Arreglos - Por Solución Ingenieril*/

#include <stdio.h> /* Declaración librerías*/

#include <stdlib.h>

#include <string.h>

 

int main(){

        int contador;//Variable contadora de ciclos

        char nombre[5][20]; //Arreglo que guardara los nombres

       

        //Ciclo en el que solicitamos los nombres a ingresar

        for(contador=0;contador<5;contador++){

               printf("Ingresa un nombre: ");

               gets(nombre[contador]);

        }

       

        //Ciclo que imprime los nombres guardados

        printf("\nNombres ingresados: \n");  

        for(contador=0;contador<5;contador++){

               puts(nombre[contador]);

        }

       

        return 0;             

}

Resultados


 

PASOS DE ARREGLOS FUNCIONES


Por default, los arrreglos en C se pasan a una función como referencia y no como valor. Esto significa que todas las modificaciones que hagamos dentro de la función en C al arreglo que recibimos como parámetro, realmente se realizan en el arreglo original que se utilizó como argumento al momento de llamar a la función.

Al escribir una función en C, la forma de indicar que uno de los parámetros que se va a recibir es un arreglo de una dimensión, es decir de que tipo va a ser el arreglo y el nombre con el cual vamos a manipular dicho arreglo dentro de nuestra función seguido de corchetes que abren y cierran; nuestra función también debe recibir un segundo parámetro que nos indique el tamaño del arreglo, o dicho de otra forma, el número de elementos de los que consta nuestro arreglo, recordemos que como el arreglo se pasa a la función como referencia, lo que esta recibiendo la función en realidad es un apuntador al primer elemento del arreglo, pero no sabe en donde termina el arreglo, por eso es necesario que la función también reciba como parámetro el número de elementos del arreglo.

Por ejemplo, el prototipo de una función en C que va a regresar un entero y va a recibir un arreglo de 10 elementos de tipo entero sería algo asi:

int MiFuncion(int mi_arreglo[], int num_elemetos);

Para llamar a la función anterior, se pone como primer argumento el nombre del arreglo (sin corcehetes) y como segundo argumento el número de elementos del arreglo. Supongamos que tenemos un arreglo de 10 elementos de tipo entero llamado numeros y queremos guardar en una variable llamada «x» el valor que nos regresa la función «MiFuncion» al llamarla pasandole como argumentos el arreglo «numeros», haríamos algo como esto

x = MiFuncion(numeros, 10);

El siguiente programa solicita al usuario que ingrese 10 números de tipo entero y los almacena en un arreglo; después le pide que introduzca un número para que busque su posición dentro del arreglo..

El programa utiliza una función llamada BuscaNumero que recibe como parámetros el arreglo con los 10 números capturados, el número de elementos del arreglo (en este caso 10) y el número del cual se desea saber su posición dentro del arreglo.. La función regresa -1 si el número que se busca no se encuentra en el arreglo y en caso contrario, regresa la primera posición del arreglo que contiene dicho número.

El programa también utiliza una función llamada MuestraArreglo que no regresa valor alguno, sólo recibe como parámetros el arreglo y el número de elementos. Esta función imprime en pantalla los elementos del arreglo separados por un tabulador.


Para pasar a una función un arreglo de dos dimensiones, si debemos indicar el tamaño de la segunda dimensión del arreglo

Ejemplo:int MiFuncion(int mi_arreglo[][5], int num_elementos);

El siguiente programa le pide al usuario que introduzca 9 números y los almacena en un arreglo de dos dimensiones, en este caso una matriz de 3×3; posteriormente utiliza una función llamada ImprimeMatriz para mostrar como quedaron almacenados los números en la matriz. Dicha función recibe como parámetros, la matriz de 3×3 y el tamaño de la primera dimensión (normalmente la primera dimensión son filas y la segunda dimensión columnas).



VÍDEOS DE APOYO





 


martes, 7 de diciembre de 2021

PUNTEROS:

 Los punteros (o apuntadores) son variables que se utilizan para almacenar direcciones de memoria, puntualmente las direcciones de memoria que fueron asignadas a variables convencionales en las que se almacenan datos de distinto tipo. Vale la pena entonces recordar que a todas las variables en C++ se les asigna un espacio de memoria en el cual se va almacenar el valor que se le asigne en algún punto de la aplicación a esa variable, el tamaño de dicho espacio va depender del tipo de dato que se pretende almacenar en la variable, del compilador y de la arquitectura del procesador. Cada uno de los espacios de memoria cuenta con una dirección para identificarlo, esta dirección es por lo general un número en representación hexadecimal. Es precisamente ese número correspondiente a la dirección lo que se almacena en un puntero.

Los punteros se usan ampliamente en C y C++ para tres propósitos principales:

·         para asignar nuevos objetos en el montón,

·         para pasar funciones a otras funciones

·         para recorrer en iteración los elementos de matrices u otras estructuras de datos.

Los punteros permiten simular el paso por referencia, crear y manipular estructuras dinámicas de datos, tales como listas enlazadas, pilas, colas y árboles. Generalmente las variables contienen valores específicos. Para obtener o modificar el valor de la variable a la que apuntan se utiliza el operador de indirección. Los punteros, al ser variables deben ser declaradas como punteros antes de ser utilizadas.

Sintaxis

int *ptrID, ID;
ID = 8;
ptrID = &ID; // puntero a ID

ptrID es un puntero a int, mientras que la variable ID es solo una variable del tipo int. Todo puntero debe ser precedido por un asterisco (*) en la declaración.

Se puede declarar más de un puntero en la misma sentencia. En el ejemplo que sigue se ve la declaración de dos punteros a int.

int *ptrY, *ptrX; 

C++ moderno proporciona punteros inteligentes para asignar objetos, iteradores para recorrer estructuras de datos y expresiones lambda para pasar funciones. Al usar estas instalaciones de lenguaje y biblioteca en lugar de punteros sin formato, hará que el programa sea más seguro, más fácil de depurar y más sencillo de entender y mantener.

Ejemplo de punteros

Muy bien, ya hemos creado y usado nuestro primer puntero ¿Notaste el uso del asterisco y del ampersand? espero que sí y además de eso hay otros detalles que debemos considerar, veamos:

Detalles al crear y usar punteros en C++

  • El tipo de dato del apuntador debe coincidir con el de la variable cuya posición en memoria apuntan. En el ejemplo vemos que tanto variable como apuntador son enteros.
  • Siempre que queremos usar el apuntador debemos anteponer el asterisco (*) para indicar que usaremos el valor en la posición de memoria apuntada.
  • De no usar el asterisco el comportamiento sería impredecible. Estaremos haciendo uso de la dirección de memoria más no del valor almacenado en ésta.
  • Después de usar un puntero, especialmente si trabajamos con arreglos o matrices, es MUY recomendable liberar la memoria utilizada con la función delete (tal como en el ejemplo)
  • Un puntero o apuntador puede ser de cualquier tipo de dato, inclusive los podemos usar con tipos complejos.

 

OPERADORES

Ya que sabemos algunos trucos y detalles sobre los apuntadores en C++, vamos a definir formalmente la utilidad del operador & y del asterisco.

Los punteros y el ampersand

El ampersand es un operador de C++ y es comúnmente utilizado para los punteros. Este operador nos permite obtener la dirección de memoria de una variable cualquiera y es justo esto (la dirección en memoria) lo que utilizan los punteros para referenciar valores.

Los apuntadores y el asterisco

El asterisco es, por decirlo de alguna forma, el operador por excelencia de los punteros. SU utilidad radica en que si el valor de dicho apuntador corresponde a una dirección de memoria, el asterisco nos permite resolverla y acceder al valor almacenado allí. Viéndolo desde otro enfoque, un apuntador es únicamente una dirección de memoria (un número) y el asterisco es el que hace la magia de obtener el valor referenciado por dicha dirección.


En otras palabras existen dos operadores a tener en cuenta cuando trabajamos con punteros. El operador de dirección (&) que devuelve la dirección de memoria de su operando y el operador de indirección (*) que devuelve un alias para el objeto al cual apunta el operando del puntero.

En el siguiente ejemplo vemos como se inicializa una variable X con el valor 15. Luego se crea un puntero a int y por último el puntero pasa a apuntar a la variable X. Esto es, ptrX es un puntero a X.

int X = 15;
int *ptrX;
ptrX = &X;


DECLARACIÓN DE PUNTEROS


Declaraciones

Se puede declarar un puntero para almacenar la dirección de memoria correspondiente a la variable var, es decir, se puede "apuntar" un puntero a la variable var. Para declarar un puntero se utiliza la sintaxis para declaración de variables: calificadores opcionales, modificadores opcionales, tipo de dato obligatorio y un identifador para el puntero que también es obligatorio. El tipo de dato del puntero debe ser obligatoriamente el mismo tipo de dato de la variable a la que se pretende apuntar, es decir, si se requiere almacenar la dirección en memoria de una variable de tipo int, entonces el tipo de dato del puntero también debe ser int. Un puntero se distingue de otras variables porque en su declaración se utiliza el operador * luego del tipo de dato y antes del identificador del puntero. Observe a continuación la declaración de varios punteros:


int *puntero_a_int;

float *puntero_a_float;

ClaseA *puntero_a_objeto_claseA;


Para apuntar un puntero a una variable se utilizan el operador de asignación =, el operador & y la variable a la que se quiere apuntar. Con el operador & se obtiene la dirección de la variable y se le asigna al puntero mediante el operador de asignación =.

Para declarar un puntero se le debe informar a C que es lo que uno desea almacenar en memoria, por lo tanto se le informa el tipo de lo almacenado, por ejemplo:

 

§  char *p; (puntero a char)

§  int *p; (puntero a int)

§  float *p; (puntero a float)

 

La forma general de la declaración de un puntero es tipo *variable;

 

OPERACIONES CON PUNTEROS


Un puntero es un tipo de dato similar a un entero, y hay un conjunto de operaciones definidas para punteros:

  • La suma o resta de un entero produce una nueva localización de memoria.
  • Se pueden comparar punteros, utilizando expresiones lógicas, para ver si están apuntando o no a la misma dirección de memoria.
  • La resta de dos punteros da como resultado el número de variables entre las dos direcciones.

Veamos un ejemplo de utilización de punteros:

#include <iostream.h>

main()
{
  int vector[3];
  int* princPunt = vector;
  int* finPunt = &vector[2];

  vector[2] = 15;
  cout << *(princPunt+2) << '\t' << *finPunt <<'\n';

  if (princPunt == finPunt)
    cout << " Esto no puede suceder " << '\n';

  cout << "Numero de elementos \t" <<finPunt-princPunt << '\n';
}


El resultado de la ejecución de este programa es:

15      15

Numero de elementos     2

 

Veamos cómo trabaja este programa:

  • princPunt es la dirección del primer elemento de vector, y finPunt la dirección del último elemento. int princPunt = vector; es una combinación de declaración y definición.
  • La expresión *(princPunt+2) incrementa el valor del puntero princPunt en dos y devuelve el número guardado en esa localización, es decir, apunta a la tercera localización de memoria y su valor es 15.
  • Se pueden utilizar también enteros en formato hexadecimal. Así,

cout << *(princPunt + 17 )

y

cout << *(princPunt + 0x11 )

producen la misma salida.

  • La expresión princPunt == finPunt comprueba si los dos punteros son iguales. Esto sólo puede ser verdad si los dos punteros apuntan a la misma variable.

Siempre que se realiza una operación aritmética sobre un puntero, sumando o restando un entero, el puntero se incrementa o decrementa un número apropiado de sitios tal que el nuevo valor apunta a la variable que está n elementos (no n bytes) antes o después que el dado. De la misma forma, al restar dos punteros se obtiene el número de objetos entre las dos localizaciones. Finalmente, dos punteros son iguales si y sólo si apuntan a la misma variable (el valor de las direcciones es el mismo). No son necesariamente iguales si sus valores indirectos son los mismos, ya que estas variables podrían estar en diferentes localizaciones de memoria.

 

VÍDEOS DE APOYO






INTRODUCCIÓN

¿Qué es C++?   Es un lenguaje de programación de propósito general que combina distintos paradigmas o modelos de programación. El lenguaje n...