Herramientas de usuario

Herramientas del sitio


curso-cpp:variables-valores-tipos

Variables, valores, expresiones y tipos

Valores

En programación, un valor es un dato en concreto. La computadora manipula valores permanentemente, transformándolo unos en otros mientras realiza sus cálculos y procesamientos.

Así por ejemplo, el número 32 es un valor. El 48 es otro valor. Cuando ingresamos datos a la computadora a través del teclado, lo que estamos ingresando son valores.

No solamente los números en sí son valores: como hemos dicho, cualquier dato que pueda ser manipulado por la computadora constituye un valor en concreto. Si está leyendo esto en una computadora, entonces quedará claro que las computadoras manipulan textos. Por lo tanto, un texto como “Patoruzito” es también un valor, así como lo son los textos “Enero”, “Febrero”, y “Esta oracion autorreferencial es un dato.”.

Podemos observar que no todos los datos son “similares”: 12, 32, 48 y 50 son todos números, mientras que en cambio “Lunes”, “Martes” y “Miércoles” son todos textos. Esto nos lleva a la siguiente noción fundamental, que es la de tipo.

Tipos

Un tipo de datos (o más brevemente, un tipo) es un conjunto de valores que son “similares”, en cuanto a que pueden ser tratados de la misma manera por la computadora. En los ejemplos anteriores ya vimos dos tipos de datos bien distintos: Los números enteros, como 42 y 10, y las cadenas de texto, como “Domingo” y “Viernes”. Cada tipo tiene asociadas operaciones potencialmente diferentes: los números los podemos restar, y por ejemplo 42 - 10 da por resultado 32. Sin embargo... ¿Qué significaría una operación como “Domingo” - “Viernes”? ¿Qué significa en general restar textos?

Vemos entonces que las operaciones válidas para hacer en un programa, dependen del tipo de los valores que estemos manipulando.

En C++, los tipos tienen nombres particulares, y estos nombres se usan en los programas. Ya estuvimos usando en programas anteriores los tipos de datos más comunes para representar números y cadenas de texto:

  • int: El tipo int es uno de los más comunes. Se utiliza para representar números enteros. Así, los textos como “Seminario” no pueden ser valores de tipo int. El tipo int representa números enteros, ya sean positivos, negativos, o cero, pero no se puede usar para números arbitrariamente grandes: Únicamente permite números desde -2147483648 (que es 2 a la 31 negativo) hasta 2147483647 (que es 2 a la 31 menos 1), inclusive. Si las cuentas intermedias que realicemos en nuestro programa generan números por fuera de este rango, se producirán resultados erróneos. A eso lo llamamos overflow, y es un peligro con el que siempre se tiene que tener cuidado cuando los números con los que trabajamos puedan volverse grandes.
  • string: El tipo string se utiliza para representar cadenas de texto. Como hemos explicado antes, no podremos entonces restar dos valores de tipo string. Para utilizar string hay que agregar la línea #include <string> al comienzo del programa.
  • char: Este es un tipo de datos que nunca usamos antes. Un valor de tipo char representa un caracter, es decir, una letra particular de un texto. Así como anotamos los valores de tipo string entre comillas dobles , anotamos los valores de tipo char entre comillas simples. Por ejemplo, 'a' , 'b' , 'A' , ')' , '+' , ' ' son todos valores distintos de tipo char. Es decir, cada letra en particular de un valor de tipo string, será un valor de tipo char.

Expresiones

Las expresiones son porciones de código fuente en las cuales se aplican operaciones a valores básicos, para denotar así valores más complejos que son el resultado de las operaciones. Por ejemplo (1+2)*4 es una expresión, que denota el valor 12 (ya que indica que se deben sumar los valores 1 y 2, lo cual daría 3, y luego eso multiplicarlo por 4). Lo que en matemática es “una cuenta”, en programación se dice que es una expresión.

Notar que como en programación hay muchos más valores que solamente números (por ejemplo, nosotros vimos ya que hay cadenas de texto), una expresión en programación es más general que “una cuentita” en el sentido matemático. En particular, según el tipo que tengan los valores con los que estemos trabajando, serán válidas expresiones que usen algunas operaciones y no otras.

En cualquier expresión, siempre se pueden utilizar paréntesis para indicar el orden en que se realizan las operaciones.

Expresiones aritméticas

Las expresiones aritméticas son las más sencillas, y son las que se obtienen directamente utilizando los operadores aritméticos básicos: suma, resta, producto y división (+,-,* y / respectivamente), además de los paréntesis. Estas son las que se corresponden directamente con cuentas matemáticas.

Así, (1 + 5) * 3 es una expresión aritmética. Otra más larga es ( ( (1+5)*2)/3)*8. Si x es un int, entonces x+1 es una expresión que denota al entero que le sigue a x, y 2*x es una expresión que indica el doble de x.

Además de estas 4 operaciones aritméticas básicas, es común también utilizar la operación %, que se llama “módulo”, y sirve para obtener el resto de la división. De esta forma, la expresión 9 / 2 da por resultado 4 (ya que cuando trabajamos con enteros, como trabajaremos casi siempre, la operación da el resultado de hacer la división entera), y la operación 9 % 2 da por resultado 1, pues al dividir 9 por 2 se obtiene un cociente de 4, y un resto de 1. Similarmente, 14 % 5 da por resultado 4, mientras que 14 / 5 da por resultado 2.

Expresiones con strings

El tipo string de C++ es un tipo que soporta varias operaciones útiles. Mencionamos a continuación 3 de las más comunes.

Si s es un string, podemos consultar la longitud de s con el operador especial .size(). Por ejemplo, si s fuera el string “Limon”, que tiene 5 letras, la expresión s.size() tendría por resultado 5.

Otro operador interesante es la llamada concatenación, que en C++ se indica con el operador + (el mismo que la suma normal, pero al operar con strings tiene otro significado), y no es otra cosa que “pegar” las dos cadenas, una a continuación de la otra, en el orden indicado. Así, si a es una cadena “Abra” y b es una cadena “Cadabra, entonces la expresión a+b denotará el string “AbraCadabra”, mientras que b+a denotará el CadabraAbra.

Un detalle de C++ es que cuando escribimos directamente una cadena entre comillas en el código, como por ejemplo “Abra”, el tipo de ese valor no es exactamente string, sino que es otro tipo más complicado, del cual no hablaremos pues escapa a este curso introductorio. Este tipo no funciona con los dos operadores mencionados, de manera tal que “Abra”.size() y “Abra” + “Cadabra” no funcionarán en C++. Esto se puede resolver encerrando a las cadenas entre comillas con string(...) (lo cual le indicará al compilador, que queremos que esos valores sean strings que se pueden sumar y operar). En los ejemplos anteriores, string(“Abra”).size() y string(“Abra”) + string(“Cadabra”) funcionarán sin problemas.

El último operador que nos interesa sobre strings es el de acceso a un caracter. Si tenemos un string s, podemos obtener su primera letra (que será de tipo char) haciendo s[0]. La segunda será s[1], la tercera s[2], y así siguiendo, donde notar que se comienza a contar desde cero. Así por ejemplo, la expresión “Cadabra”[3] denota un char con la cuarta letra de “Cadabra”, es decir, 'a' . Similarmente “Cadabra”[2] tendría el valor 'd' . Este operador funciona sin problemas sin necesidad de usar string(...) sobre las constantes.

Notar que las expresiones pueden ser combinadas libremente, de manera que “Pepe”[1+2] denota un caracter con una e, y por ejemplo (string(“Juan”) + string(“Perez”) ).size() denota al int 9

Expresiones con char

La operación fundamental entre caracteres es la aritmética. Esto puede parecer ilógico en principio, pues no queda claro qué significa por ejemplo sumar una 'a' con una 'b'.

Las letras, y todos los demás caracteres en la computadora, están ordenados con cierto criterio. En el caso de C++ en las computadoras usuales, para los valores que más comúnmente utilizamos, el orden de los caracteres está dado por el llamado código ASCII.

De esta forma, si c denota un cierto caracter, c+1 denota al caracter siguiente en este ordenamiento. Similarmente, c-1 denota al anterior. Una propiedad útil de este ordenamiento es que las letras mayúsculas están todas juntas y en el orden del alfabeto inglés (sin la eñe). Similarmente con las letras minúsculas. Esto quiere decir que por ejemplo, 'a' + 3 es una expresión que tendrá por resultado 'd' , y 'Q' - 2 es una expresión que denota al caracter 'O' . Notar que mayúsculas y minúsculas son caracteres distintos.

Similarmente, podemos obtener la distancia en el abecedario entre dos letras haciendo su resta: 'e' - 'a' dará por resultado un int, en este caso 4 (pues desde la a hay que avanzar 4 letras para llegar a la e). Notar que si mezclamos mayúsculas con minúsculas, en estos casos tendremos resultados incorrectos, pues en la tabla ASCII mencionada las mayúsculas y minúsculas tienen códigos diferentes (no son el mismo caracter).

Otra propiedad útil del ordenamiento ASCII es que los dígitos del '0' al '9' están en orden y todos juntos en el ordenamiento; y por lo tanto, si sabemos que x es un char que corresponde a un dígito, con la expresión x - '0' podemos obtener el valor numérico del caracter, directamente como un número entero.

Variables

Hemos visto hasta ahora expresiones, que operan con valores directamente escritos en el programa. Por ejemplo, una expresión como 1 + 2 opera directamente con el 1 y el 2 allí escritos, obteniendo 3. Este tipo de expresiones no permiten al programa “adaptarse” a los datos: Siempre se opera igual.

Para que un programa pueda trabajar con datos arbitrarios, surge el concepto clave de variable.

Una variable es un espacio de memoria de la computadora, donde se almacena un valor. Podemos pensarlo como una caja, en la que guardamos el dato que nos interesa. Una variable tiene un nombre, que nos permite referirnos a ella. Es decir, la caja donde se guarda el dato tiene un nombre, con el cual podemos hablar tanto de la caja, como del valor que se guarda en ella.

Una variable en C++ puede guardar únicamente datos de un cierto tipo, que es el tipo con el cual se declara la variable. Esto es lo que hacemos en líneas como int x; en los programas que ya vimos: Esa línea declara que utilizaremos una variable de nombre “x”, y en la cual podremos guardar valores de tipo int. Cuando declaramos string nombre;, estamos indicando a la computadora que utilizaremos una caja, a la cual nos referiremos como “nombre”, y en la cual guardaremos datos de tipo string.

Ahora podemos entender el efecto de líneas como cin >> x: esta instrucción le ordena a la computadora que lea un dato ingresado por el usuario, y lo guarde en la variable x. Una propiedad central de las variables es que son una caja que guarda un solo valor, y ese valor guardado puede cambiar con el tiempo. Por lo tanto, cuando se almacena un nuevo valor en la caja, se pierde todo lo que hubiera allí antes.

Así por ejemplo, si tenemos el siguiente fragmento de programa:

int x;
cin >> x;  // Lectura 1
cout << x + 1 << endl; // Escritura 1
cin >> x;  // Lectura 2
cout << x + 1 << endl; // Escritura 2

Supongamos para el siguiente ejemplo, que el usuario va a introducir los números 7 y 23.

Al ejecutar la “Lectura 1”, la computadora leerá un número ingresado por el usuario, que guardará en la caja x. Cualquier dato que hubiera antes en x se pierde, y quedará a partir de ahora guardado en x el valor 7 que introduce el usuario. Luego, la computadora ejecuta la Escritura 1, en la cual se usa la expresión x + 1: Como en la caja x hay guardado un 7, esta expresión dará por resultado 7 + 1 = 8, y por lo tanto se mostrará por pantalla el valor 8.

Luego de esto, se ejecuta la Lectura 2, y entonces se almacena en x lo que el usuario ingrese. Como ingresa un valor de 23, en x queda guardado el valor 23. El viejo valor de x (que era 7) se pierde al almacenar en x un valor nuevo. Como consecuencia de esto, cuando a continuación de esto se ejecuta la Escritura 2, se imprimirá por pantalla un 24: Notar que las instrucciones de Escritura 1 y Escritura 2 son idénticas, pero sin embargo producen resultados distintos, porque el valor almacenado en x cambió entre medio de ambas. Esto nos muestra que el orden de ejecución de las distintas operaciones es fundamental.

Una variable puede utilizarse directamente en una expresión, como hemos hecho con x+1 en el ejemplo. Cuando esto se hace, la computadora utiliza en los cálculos y operaciones el valor que se encuentre almacenado en dicha variable en ese momento. Como este valor puede ir cambiando, como vimos, y depender de lo que haya ingresado el usuario, esto permite a un programa ser flexible y operar con cualquier dato que el usuario ingrese, mientras lo hayamos guardado adecuadamente en alguna variable para poder procesarlo luego.

El operador de asignación

Una operación fundamental en C++ viene dada por el operador de asignación. Con este nombre designamos al =: este es un operador que se utiliza para almacenar un valor en una variable. En nuestra analogía de cajas, este operador no significa más que una orden de meter un valor en una caja (Decimos que le asignamos un valor a una variable).

Cuando en C++ escribimos x = 2 + 5, estamos ordenando a la computadora que guarde el resultado de la expresión que está en el lado derecho del = (en este caso, un 7) en la caja que se indica en el lado izquierdo del =. Notar que = no es una igualdad en el sentido que se le da en matemática, sino que es una operación: = ordena a la computadora que almacene el resultado de una expresión (lado derecho de =), en una variable (lado izquierdo de =).

En particular, a = b y b = a significan cosas muy distintas, cosa que no ocurre en matemática: La primera ordena a la computadora guardar en la variable a, el valor que ahora se encuentre en la variable b. Mientras que la segunda ordena guardar en la variable b, el valor que ahora se encuentre en la variable a.

Así, si por ejemplo tenemos que a guarda un 5, y que b guarda un 10, luego de ejecutar a = b, ambas variables contendrán un 10, mientras que si se ejecutara b = a, ambas quedarían con un valor 5.

Por ejemplo, el siguiente fragmento de programa:

int x = 25;
int y = 10;
int z = x+y;
cout << x << " " << y << " " <<  z << endl;
x = 15;
cout << x << " " << y << " " <<  z << endl;
z = x+y;
cout << x << " " << y << " " <<  z << endl;

Mostraría por pantalla lo siguiente:

25 10 35
15 10 35
15 10 25

En este ejemplo se muestra una nueva posibilidad en la sintaxis de C++, que es la de usar el operador de asignación (es decir, el =) en la misma línea donde se declara la variable. Esto es extremadamente útil para darle un valor inicial a una variable, guardando en el mismo momento en que creamos la caja, un valor inicial en la misma. Esto se llama inicializar la variable, y es una muy buena costumbre, para asegurarnos de no olvidar guardar un valor en la variable antes de utilizarla: Si utilizamos una variable en la cual nunca hemos guardado un valor, no se sabe con qué valor “comienza”: Podría pasar cualquier cosa.

Operaciones de entrada / salida

Ya hemos estado trabajando con operaciones de entrada salida, mediante cin y cout: Resumimos aquí brevemente su uso con variables.

Cuando queremos recibir datos del usuario, debemos almacenarlos en alguna variable. Para eso utilizamos cin, que permite hacer justamente eso. Por ejemplo el siguiente fragmento de código:

int x;
cin >> x;
int y,z;
cin >> y >> z;
cin >> x >> y >> z;

Muestra un ejemplo de 3 lecturas de datos realizadas con cin: En la primera, se recibe un número entero y se guarda en la variable x. En la segunda, se reciben dos enteros más, y se guardan (¡En este orden!) en las variables y y z. Notar que es posible en una misma instrucción leer varias variables, utilizando para eso el operador >> varias veces. Finalmente, en la tercera y última lectura con cin se leen tres variables: x, y y z. Notar que en este caso, la tercera lectura borra los valores que se hayan leído en las primeras dos lecturas, ya que los nuevos valores son almacenados en las mismas variables donde se habían leído los valores anteriores, que se pierden al ser reemplazados por los nuevos.

Cuando queremos enviar datos a la salida, utilizamos cout. En este caso, cout se encarga de escribir en la pantalla el resultado de cualquier expresión que le indiquemos. Además, tenemos el elemento especial endl, que sirve para indicar a cout que pase a escribir a la siguiente línea. Al elemento endl se lo suele denominar el fin de línea.

Por ejemplo, el siguiente fragmento de código:

cout << "Mensaje1" << endl;
cout << "En la segunda linea " << "podemos enviar un texto en partes" << endl;
cout << "Sin endl, no se salta de linea.";
cout << "Por lo tanto esto se pega a la anterior.";
cout << endl; // Se puede enviar solamente el endl en una instruccion, para forzar el salto de linea.
cout << (1+2+3+4) << " " << (1+3)*10 << endl; // Se pueden enviar expresiones para que se escriban
int x = 42;
cout << x+10 << endl; // Las variables se pueden usar en cualquier expresion

Produciría por pantalla el siguiente resultado:

Mensaje1
En la segunda linea podemos enviar un texto en partes
Sin endl, no se salta de linea.Por lo tanto esto se pega a la anterior.
10 40
52

Const

A veces queremos tener variables que guarden un valor que nunca se va a modificar. Esto se hace por claridad y facilidad del programa: Por ejemplo, imaginemos que estamos haciendo un programa propio que calcula cuánto trabajo le toca hacer a cada uno de los integrantes de un grupo. Supongamos que nuestro grupo tiene 4 personas. Podríamos simplemente poner 4 en el código, cada vez que necesitemos utilizar la cantidad de personas. Sin embargo, esto no deja claro que ese 4 es la cantidad de personas, y no otra cosa que también sea 4 “de casualidad”. Similarmente, si un día quisiéramos cambiar el programa para que trabaje con 5 personas... ¡Tendríamos que ir por todo el programa buscando todos los 4, para ver cuáles se refieren a la cantidad de personas, y esos cambiarlos por un 5!

En lugar de usar el valor directamente, entonces, conviene guardarlo en una variable al comienzo:

int CANTIDAD_PERSONAS = 4;

Y luego utilizarlo cada vez que necesitemos hablar de la cantidad de personas en el programa: De esta forma, para cambiar la cantidad más adelante hay que cambiar un solo lugar, y el programa queda mucho más claro.

Como esta variable no la vamos a modificar, es muy recomendado declararla con const: const es una palabra especial que indica al compilador que no vamos a modificar nunca esta variable: Queremos que sea en realidad una constante, y no una variable que realmente puede cambiar de valor. De esta forma si por accidente la modificamos, el compilador nos avisará.

La declaración se hace simplemente agregando const al comienzo:

const int CANTIDAD_PERSONAS = 4;

Es una convención común (de muchas posibles) escribir las constantes en mayúsculas.

Ámbito de una variable

No se puede utilizar una variable en cualquier lugar del programa, sino que cada variable tiene un ámbito, y solo puede utilizarse dentro del mismo.

El ámbito de una variable es el bloque (conjunto de instrucciones delimitadas con llaves { y }) que contiene la declaración de la variable. Más adelante veremos instrucciones como if, while y for que contienen bloques de instrucciones, y una variable declarada dentro de uno de estos bloques, no puede utilizarse fuera de los mismos.

curso-cpp/variables-valores-tipos.txt · Última modificación: 2017/10/29 19:28 por santo