La función printf()
Antes de analizar las asignaciones y comparaciones lógicas veremos una función similar al cout que se utiliza en la programación en el lenguaje C. Tiene el propósito de visualizar algo en la pantalla, este algo está dentro de unos paréntesis, rodeados a su vez por signos de comillas. Ej: printf (“Este texto aparecerá por pantalla.\n”);
Como vemos, con la función printf se puede utilizar también el caracter de retorno de carro.
A continuación veremos el programa 10PRINTF.CPP en el que se utiliza esta función con diferentes tipos de datos, modificando el formato de salida por pantalla.
#include <stdio.h> main() { int a; // tipo entero simple long int b; // tipo entero expandido short int c; // tipo entero comprimido unsigned int d; // tipo entero sin signo char e; // tipo caracter float f; // tipo punto flotante double g; // punto flotante doble precisión a = 1023; b = 2222; c = 123; d = 1234; e = 'X'; f = 3.14159; g = 3.1415926535898; printf("a = %d\n",a); // salida decimal printf("a = %o\n",a); // salida octal printf("a = %x\n",a); // salida hexadecimal printf("b = %ld\n",b); // salida decimal long printf("c = %d\n",c); // salida decimal short printf("d = %u\n",d); // salida sin signo printf("e = %c\n",e); // salida de caracter printf("f = %f\n",f); // salida en flotante printf("g = %f\n",g); // salida doble flotante printf("\n"); printf("a = %d\n",a); // salida simple entera printf("a = %7d\n",a); // usa un campo de 7 caracteres printf("a = %-7d\n",a); // justif. izda. de 7 caracteres printf("\n"); printf("f = %f\n",f); // salida simple float printf("f = %12f\n",f); // usa un campo de 12 caracteres printf("f = %12.3f\n",f); // usa 3 decimales printf("f = %12.5f\n",f); // usa 5 decimales printf("f = %-12.5f\n",f); // justificacion izquierda } <pre>
Como se observa en la primer línea, el archivo de cabecera para utilizar la función printf no es el mismo que para el cout. En este caso la biblioteca es stdio.h, que controla las operaciones de entrada y salida.
Después de declarar varios tipos de variables y asignarles un determinado valor, nos encontramos, a partir de la línea 20, con declaraciones printf que utilizan el caracter %.
Este caracter se utiliza con el printf para la visualización de una variable. Este signo señala el principio de variables de distinto tipo. Por ejemplo, si el caracter que sigue a % es una letra d, nos indica que la variable que a continuación aparece es de tipo decimal.
Todos los caracteres entre signos de comillas definen el patrón de los datos para ser mostrados por el mandato y después de este patrón hay una coma seguida por la variable que quiere ser mostrada. Podemos añadir más campos de salida y más variables entre las llaves para imprimir más variables en el mandato, pero siempre debemos tener en cuenta que el número de descriptores de campo y el número de variables debe ser el mismo o se producirá un error.
Seguidamente, una lista de conversión de caracteres, y la forma de usarla con printf.
d: Notación decimal.
o: » octal.
x: » hexadecimal.
u: » sin signo.
c: » de caracter.
s: » de cadena.
f: » de punto flotante.
Cada caracter de los anteriores es precedido por un signo de porcentaje, indicando el tipo de conversión de salida, y entre estos dos caracteres, puede incluirse cualquiera de los siguientes:
-: Justificación izquierda en este campo.
(n): Especificador de mínimo de caracteres por campo.
.: Para separar n de m. (n.m)
m): Dígitos significativos de la fracción flotante.
l: Indica un «long».
MANDATOS DE ASIGNACIÓN DE ENTEROS
El programa 11ASIG_INT.CPP es un buen ejemplo de los mandatos de asignación:
#include <stdio.h> main() { int a,b,c; a = 12; b = 3; c = a + b; printf("a= %d| b= %d| c= %d\n\n",a,b,c); c = a - b; printf("a= %d| b= %d| c= %d\n\n",a,b,c); c = a * b; printf("a= %d| b= %d| c= %d\n\n",a,b,c); c = a / b; printf("a= %d| b= %d| c= %d\n\n",a,b,c); c = a % b; // módulo o residuo printf("a= %d| b= %d| c= %d\n\n",a,b,c); c = 12*a + b/2 - a*b*2/(a*c + b*2); printf("a= %d| b= %d| c= %d\n\n",a,b,c); c = c/4+13*(a + b)/3 - a*b + 2*a*a; printf("a= %d| b= %d| c= %d\n\n",a,b,c); a = a + 1; printf("a= %d| b= %d| c= %d\n\n",a,b,c); b = b * 5; printf("a= %d| b= %d| c= %d\n\n",a,b,c); a = b = c = 20; // asignación múltiple printf("a= %d| b= %d| c= %d\n\n",a,b,c); a = b = c = 12*13/4; printf("a= %d| b= %d| c= %d\n\n",a,b,c); }
Tres variables se definen para su uso en el programa, y las demás son para ilustrar acerca de otros tipos de asignación. Las dos primeras líneas asignan valores numéricos a “a” y a “b”, y las 4 siguientes líneas ilustran el uso de las 5 funciones aritméticas básicas. En la línea 17 se utiliza el operador modular (%) que da el resto de la división de a por b. Esto sólo puede ser aplicado a variables tipo int o char, y sus extensiones, tales como long, short, etc. Siguiendo, en las líneas 19 y 21 se ilustra la manera de combinar variables en algunas expresiones complejas, utilizando paréntesis.
En las líneas 28 y 30 se usa la asignación múltiple, construcción muy útil sobre todo cuando hay que inicializar variables en grupo.
El operador cin
Este operador se utiliza para leer datos desde el teclado. Se usa con el llamado operador de extracción (>>).
Con el operador cin pueden asignarse a las variables valores ingresados por el usuario.
Veamos como ejemplo el programa 12OPER_CIN.CPP:
#include <iostream.h></pre> main() { int a; float b; char c; cout << "Ingrese un valor entero: "; cin >> a; cout << "Ingrese un valor float: "; cin >> b; cout << "Ahora ingrese un caracter: "; cin >> c; cout << "\nLos datos ingresados son: "; cout << "\n'a' = " << a; cout << "\n'b' = " << b; cout << "\n'c' = " << c; } <pre>
COMPARACIONES LÓGICAS
El programa 13COMPARAR.CPP contiene algunos ejemplos de comparaciones en C
<pre><em id="__mceDel"> #include <iostream.h> main() { int x = 11,y = 11,z = 11; char a = 40,b = 40,c = 40; float r = 12.987,s = 12.987,t = 12.987; // Primer grupo de mandatos comparadores if (x == y) z = -13; // Esto asignará z = -13 if (x > z) a = 'A'; // Esto asignará a = 65 if (!(x > z)) a = 'B'; // Esto no cambiará nada if (b <= c) r = 0.0; // Esto asignará r = 0.0 if (r != s) t = c/2; // Esto asignará t = 20 // Segundo grupo de mandatos comparadores if (x = (r != s)) z = 1000; // Esto asignará x = algún número // positivo y z = 1000 if (x = y) z = 222; // Esto asigna x = y, y z = 222 if (x != 0) z = 333; // Esto asigna z = 333 if (x) z = 444; // Esto asigna z = 444 // Tercer grupo de mandatos comparadores x = y = z = 77; if ((x == y) && (x == 77)) z = 33; // Esto asigna z = 33 if ((x > y) || (z > 12)) z = 22; // Esto asigna z = 22 if (x && y && z) z = 11; // Esto asigna z = 11 if ((x = 1) && (y = 2) && (z = 3)) r = 12.00; // Esto asigna x = 1, y = 2, z = 3, r = 12.00 if ((x == 2) && (y = 3) && (z = 4)) r = 14.56; // Esto no cambia nada // Cuarto grupo de comparadores if (x == x); z = 27.345; // z siempre se cambia if (x != x) z = 27.345; // Nadie cambia aquí if (x = 0) z = 27.345; // Esto asigna x = 0, z sigue igual }
Empezamos definiendo e inicializando nueve variables para usarlas en los mandatos comparadores.
El primer grupo de comparaciones representa el más simple, ya que sólo compara 2 variables. Cada variable podría ser sustituida por una constante, y la comparación seguiría siendo válida, pero dos variables es el caso más frecuente. La primera comparación averigua si “x” e “y” son iguales, usando el doble igual “==“ para esta comparación. La segunda comparación verifica si “x” es mayor de “z”.
La tercera introduce el operador NOT (!), el cual puede usarse para negar una comparación lógica ( !(x>z) : que x no sea mayor que z). La cuarta comprueba que “b” sea menor o igual que “c”, y la última verifica que “r” y “s” no sean iguales (r != s). Tal como vimos anteriormente, si la comparación resulta cierta, el mandato acompañante del if será ejecutado.
Las comparaciones del segundo grupo son más complicadas. Para comprender esto debemos entender tan solo lo que significan verdadero y falso en lenguaje C. Falso está definido como valor 0, y verdadero es definido como no cero. Cualquier variable entera o tipo char puede usarse para el resultado de tipo verdadero/falso, o el resultado puede ser transformado en un valor entero o char.
Observemos primero la comparativa del segundo grupo de comparadores. La expresión “r!=s” será evaluada como cierta, teniendo en cuenta que “r” fue probablemente inicializada antes a 0.0, por tanto el resultado será un no cero, tal vez un 1. Tengamos presente que cuando se evalúen dos variables float, el resultado será siempre de tipo integer. Dado que no se le ha dado una variable para almacenar el resultado de la comparación, lo hará produciendo directamente un entero. Finalmente, el resultado, 1 en este caso, será asignado a “x”. Si hubiésemos usado el doble igual, el valor fantasma llamado 1, sería comparado internamente con “x”, pero como hemos empleado el igual simple, el valor es asignado a “x”, aunque el mandato esté entre paréntesis. Finalmente, dado que el resultado de la asignación entre paréntesis es no cero, la expresión evaluada es cierta, y el valor 1000 es asignado a “z”. Por tanto, hemos conseguido 2 cosas: hemos asignado un nuevo valor a “x”, probablemente 1, y hemos destinado 1000 a “z”. Lo más importante a recordar es que valores verdadero/falso y muchas cosas más pueden ser asignadas a este mandato condicional. El valor asignado a “x” es 1, pero distintos compiladores podrían asignar otros valores.
El ejemplo que proponemos servirá para aclarar conceptos. En él , “x” es asignado al valor de “y”, y dado que el valor es 11, es no cero, lo cual es, por tanto, verdad. De este modo, a “z” se le asigna el valor 222.
El tercer ejemplo del segundo grupo compara “x” y 0. Si el resultado es verdad, significa que “x” es no cero, por tanto a “z” se le asigna el valor 333. El tercer ejemplo ilustra el mismo caso, ya que el resultado de “x” es no cero. La comparación a cero no es actualmente necesaria, ya que el resultado de la misma es verdad. El tercer y cuarto ejemplo son idénticos.
CONCEPTOS ADICIONALES SOBRE COMPARACIÓN
El tercer grupo de comparaciones nos introducirá nuevos conceptos sobre comparaciones, tales como el AND y el OR. Asignamos el valor 77 a tres variables enteras, simplemente para empezar otra vez con valores definidos. La primera comparación del tercer grupo contiene el nuevo controlador “&&”, el cual es el “AND“ lógico. El mandato en su totalidad lee si “x” es igual a “y” y si “x” es igual a 77, entonces el resultado será verdad. Si es verdadera, la variable “z” toma el valor 33.
La siguiente comparación introduce el operador “¦¦”, el cual equivale a “OR”. El mandato verifica que si “x” es mayor que “y” o que si “z” es mayor de 12, entonces el resultado es verdad. Dado que “z” es mayor de 12, no importa que “x” sea mayor que “y” o no, porque sólo con que una condición sea cierta, ya se cumple el mandato entero. La condición tiene resultado verdad, por lo cual asignamos el valor 22 a “z”.
EVALUACIÓN LÓGICA
Cuando una expresión compuesta se evalúa, la evaluación se realiza de izquierda a derecha, y tan pronto como se cumple el resultado de la misma, se para. Nos referimos a “evaluación lógica” cuando empleamos un AND y, uno de los términos evaluados da falso, la evaluación es discontinua, aunque los demás términos sean verdad, la condición en su totalidad resulta falso. Tratándose del OR, sólo con que uno de los términos evaluados sea cierto, la condición ya se cumple ahí mismo, caso contrario del AND. En caso de términos adicionales anidados, las reglas para su evaluación se describen en la sgte. página.
Yendo al siguiente ejemplo del tercer grupo, encontramos 3 variables simples, usadas en la parte condicional de la comparación. Como todas las variables tienen valor no cero, todas son verdad, hay por tanto el “AND” de esas 3 variables, “r”, “s” y “t” son de tipo float, por lo cual no podrían ser usadas para este propósito, pero pueden ser comparadas con cero, y el mismo tipo de expresión podría aplicárseles.
Continuando con el cuarto ejemplo del tercer grupo, encontramos 3 asignaciones en la parte comparadora del if. A las tres variables se les asignan nuevos valores, los cuales son no cero, por lo tanto producen un resultado verdad.
El último ejemplo del tercer grupo contiene una pequeña trampa, pero como ya hemos hablado acerca de esto, parte de la comparación evalúa falso. El resto de la comparación no es evaluada, porque es un AND, que al dar falso en la primera comparación, ya la resuelve. Si el programa dependía del valor de “y”, que había sido inicializada a 3, en la siguiente parte de la comparación cesará porque parará al encontrar el falso en el primer término. Por tanto, “z” no tomará valor 4, y la variable “r” no cambiará.
ÁREAS POTENCIALES DE PROBLEMAS
El último grupo de comparaciones ilustra tres posibilidades que pueden resultar algo confusas. Las tres tienen como resultado el que “z” no tome el valor deseado, pero por diferentes motivos. En el primero, la comparación evaluada resulta verdad pero el ; siguiente al segundo paréntesis termina la cláusula if y el mandato implícito a “z” es ejecutado, siempre en el siguiente mandato. El if, por tanto, no tiene efecto por el punto y coma, que ignora el resto de la línea. El segundo mandato es más sencillo, porque “x” siempre es igual a si mismo, por tanto la inigualdad jamás será cierta, y el mandato no hará nada, por tanto es un esfuerzo inútil.
El último mandato siempre asignará 0 a “x”, y por tanto, la comparación siempre dará falso, no ejecutando jamás la parte condicional del if.
El mandato condicional es extremadamente importante, y, debe ser minuciosamente estudiado, para escribir buenos programas en C.