sábado, 12 de junio de 2021

P2-Operadores y P3-Sentencias

 Símbolos de manipulación de datos 

Operadores de C

Los operadores de C son un subconjunto de los operadores integrados de C++.
Hay tres tipos de operadores. Una expresión unaria consta de un operador unario antepuesto a un operando, o la palabra clave sizeof seguida de una expresión. La expresión puede ser el nombre de una variable o una expresión de conversión. Si la expresión es una expresión de conversión, se debe incluir entre paréntesis. Una expresión binaria consta de dos operandos unidos por un operador binario. Una expresión ternaria consta de tres operandos unidos por el operador de expresión condicional.
C incluye los operadores unarios siguientes:
TABLA 1

Símbolo NOMBRE
- ~ !    Operadores de negación y complemento
* &        Operadores de direccionamiento indirecto y address-of
sizeof Operador de tamaño
+         Operador unario más
++ -- Operadores unarios de incremento y decremento


Los operadores binarios se asocian de izquierda a derecha. C proporciona los operadores binarios siguientes:
TABLA 2
Símbolo NOMBRE
* / %         Operadores de multiplicación
+ -                 Operadores aditivos
<< >>         Operadores de desplazamiento
< > <= >= == != Operadores relacionales
& | ^         Operadores bit a bit
&& ||         Operadores lógicos
,                 Operador de evaluación secuencial
 
El operador de expresión condicional tiene menos prioridad que las expresiones binarias y se diferencia de ellas en que es asociativo a la derecha.

Las expresiones con operadores también incluyen expresiones de asignación, que usan operadores de asignación unarios o binarios. Los operadores de asignación unarios son los operadores de incremento ( ++ ) y decremento ( -- ); los operadores de asignación binarios son el operador de asignación simple ( = ) y los operadores de asignación compuesta. Cada operador de asignación compuesta es una combinación de otro operador binario con el operador de asignación simple.

Operadores relacionales y de igualdad de C

Los operadores relacionales y de igualdad binarios comparan el primer operando con el segundo para probar la validez de la relación especificada. El resultado de una expresión relacional es 1 si la relación probada es true y 0 si es false. El tipo del resultado es int .

Sintaxis

relational-expression:

    shift-expression

    relational-expression < shift-expression

    relational-expression > shift-expression

    relational-expression <= shift-expression

    relational-expression >= shift-expression

equality-expression:

    relational-expression

    equality-expression == relational-expression

    equality-expression != relational-expression

Los operadores relacionales y de igualdad prueban las relaciones siguientes:

Operador Relación probada

< Primer operando menor que el segundo operando

> Primer operando mayor que el segundo operando

<= Primer operando menor o igual que segundo operando

>= Primer operando mayor o igual que segundo operando

== Primer operando igual a segundo operando

!= Primer operando no igual a segundo operando

Los cuatro primeros operadores de la lista anterior tienen mayor prioridad que los operadores de igualdad (== y !=). Vea la información de prioridad en la tabla Prioridad y asociatividad de los operadores de C.

Los operandos pueden tener tipo entero, flotante o puntero. Los tipos de operando pueden ser diferentes. Los operadores relacionales realizan las conversiones aritméticas habituales sobre operandos de tipo entero y flotante.

Operadores lógicos de C

Los operadores lógicos realizan operaciones AND lógicas ( && ) y OR lógicas ( || ).

Sintaxis

logical-AND-expression:

    inclusive-OR-expression

    logical-AND-expression && inclusive-OR-expression


logical-OR-expression:

    logical-AND-expression

    logical-OR-expression || logical-AND-expression

Los operadores lógicos no realizan las conversiones aritméticas habituales. En su lugar, evalúan cada operando para ver su equivalencia con 0. El resultado de una operación lógica es 0 o 1. El tipo del resultado es int .

A continuación se describen los operadores lógicos de C:

Operador                                           Descripción

&& El operador AND lógico genera el valor 1 si ambos operandos tienen valores          distintos de cero. Si alguno de los operandos es igual a 0, el resultado es 0. Si el primer  operando de una operación AND lógica es igual a 0, el segundo operando no se evalúa.

|| El operador OR lógico realiza una operación OR inclusivo en sus operandos. El resultado es 0 si ambos operandos tienen valores 0. Si cualquiera de los operandos tiene un valor distinto de cero, el resultado es 1. Si el primer operando de una operación OR lógica tiene un valor distinto de cero, el segundo operando no se evalúa.

Los operandos de las expresiones AND y OR lógicas se evalúan de izquierda a derecha. Si el valor del primer operando es suficiente para determinar el resultado de la operación, el segundo operando no se evalúa. Esto se denomina "evaluación de cortocircuito". Hay un punto de secuencia después del primer operando. Vea Puntos de secuencia de C para obtener más información.

Sentencias de selección

 Las sentencias ("Statements") especifican y controlan el flujo de ejecución del programa. Si no existen sentencias específicas de selección o salto, el programa se ejecuta de forma secuencial en el mismo orden en que se ha escrito el código fuente (es el que podríamos considerar orden "natural" de ejecución).

En este capítulo explicaremos los distintos tipos de sentencias que existen en C++, pero antes ofreceremos una descripción formal de las mismas señalando qué se entiende por sentencia.

Una expresión es una secuencia de operadores; operandos; elementos de puntuación y palabras clave, que especifican una computación. Tiene sentido computacional en sí misma y equivale a una frase en el lenguaje normal. Entre sus características distintivas están las de poder producir un resultado y posibles efectos laterales. Ejemplo:

extern x;        // No produce un valor

y = 22;          // Produce un valor

z = i++;         // Valor + efectos laterales

Las sentencias de selección, también llamadas de control de flujo, permiten decidir entre distintos cursos de acción en función de ciertos valores.  En C++ existen tres tipos de estas sentencias de selección:

if...else  .

else if    .

switch   .



Recuerde que de no ser por estas sentencias, el flujo de ejecución del programa estaría siempre constreñido a la ejecución de sus sentencias en el orden en que están colocadas en el fuente.

  if … else

En su forma abreviada, cuando no existe la cláusula else, esta sentencia permite escoger entre ejecutar o no una sentencia, en función del resultado de una expresión lógica.  En su forma ampliada, cuando la cláusula else está presente, permite escoger entre dos opciones alternativas.

 Sintaxis

if ( <condición> )  <sentencia1>;

[ else  <sentencia2>; ]

  Descripción

  <condición> debe ser una expresión relacional que devuelve un valor lógico, es decir, un bool ( 3.2.1b), y estar obligatoriamente entre paréntesis.  Pueden declararse variables dentro de la <condición>.  Por ejemplo, la siguiente es una sintaxis válida:

if (int val = func(arg))

   val = z ;

else  val = y;

El ámbito de la variable val incluye toda la sentencia if,  incluyendo, en su caso, el bloque <sentencia2> de else.  La cláusula else es opcional, pero no puede haber sentencias entre el if y else.    Recuerde las precauciones indicadas respecto de las expresiones relacionales , ya que son motivo frecuente de error en este tipo de sentencias.

  <sentencia1>. Es una sentencia o bloque de código que se ejecuta si <condicion> se evalúa como cierto (true  !=  0).

  <sentencia2> es una sentencia o bloque de código que se ejecuta si existe un else y <condicion> resulta falso (false  ==  0)

Puesto que el if simplemente chequea el valor resultante de <condicion> (igual o desigual a cero), las dos expresiones siguientes son equivalentes:

if ( expresion )  <sentencia> ;

if ( expresion !=0 ) <sentencia> ;

La forma más general es:

if (<condicion>) {

   <sentencia1>;

}

else  {

   <sentencia2>;

}

 Ejemplo

Uno sencillo:

if (salida == 'S') break;

Otro ejemplo:

if (a > b)

   z = a;

else

   z = b;

Se podría haber escrito de forma más comprimida:

if (a > b) z = a;

else z = b;

También:

a > b ? z = a : z = b ;

o mejor aún:

z = (a > b ? a : b);

Puesto que la cláusula else es opcional, en los if... else anidados podría haber ambigüedad sobre a qué if corresponde un else;  esto se evita asociando el else al if más interno sin else.   Por ejemplo, en los dos trozos de código siguientes, el primero tiene una indentación que no se corresponde con la realidad lógica del programa.

// mal indentado: ------------

if ( n > 0 )

   if ( a > b )

      z = a;

else

   z = b;

// bien indentado: -----------

if ( n > 0 )

   if ( a > b )

      z = a;

   else

      z = b;

 Else if

Estas sentencias no representan en realidad nada nuevo, solo una sucesión de if  else anidados, aunque de uso muy frecuente, por lo que haremos una consideración especial de este caso.

if ( <expresion1> )

   <sentencia1> ;

else if ( <expresion2> )

   <sentencia2> ;

else if ( <expresion3> )

   <sentencia3> ;

else

   <sentencia4> ;

En realidad, a la luz de lo expuesto en el apartado anterior, su indotación correcta sería:

if ( <expresion1> )
   <sentencia1> ;
else
   if ( <expresion2> )
      <sentencia2> ;
   else
      if ( <expresion3> )
         <sentencia3> ;
      else

         <sentencia4> ;


Las expresiones <expresion> son evaluadas correlativamente hasta que se encuentra la primera que devuelve un valor cierto ( != 0 ), en cuyo caso se ejecuta el bloque de código <sentencia> correspondiente y acaba la evaluación. En caso de que ninguna de las <expresion> sea cierta, se ejecuta la <sentencia> correspondiente al else (si existe).

switch

Se trata de una sentencia condicional multi-salida en la que las decisiones se toman en función de un valor numérico entero de entre una serie de opciones posibles.  Puede existir una cláusula por defecto o bien no adoptarse ninguna acción.

 Sintaxis

switch ( <expresion> ) {

  case <const1> : <sentencia1>; [break;]

  case <const2> : <sentencia2>; [break;]

  case <constN> : <sentenciaN>; [break;]

 [default : <sentenciaD>; ]

}

 Descripción

La sentencia switch comprueba cuando una expresión <expresion> entre paréntesis (que se traduce en un valor numérico) coincide con alguno de una serie de valores enteros constantes y diferentes  (<constX>). En cuyo caso, se ejecuta un bloque de código específico <sentencia>.  En caso de estar presente la cláusula opcional default y no existir concordancia con ninguno de los valores anteriores, se ejecuta una sentencia por defecto (<sentenciaD>).

Sentencias de iteración

Las sentencias de iteración permiten repetir una sentencia o conjunto de ellas. Es lo que se denomina ejecutar un bucle. En C++ existen tres formas de iteraciones: los bucles while; do…while y for.
Observe que en todos los casos el bucle puede estar constituido por una sola sentencia o por varias. En cuyo caso se trata de un bloque de código delimitado por un par de corchetes { } . Si se trata de una sola sentencia, los corchetes no son necesarios.


Bucle   while

La sentencia while permite ejecutar repetidamente un bloque de código mientras se cumpla una determinada condición que es chequeada antes de cada iteración.

Sintaxis

while ( <condicion> ) <sentencia> ;

La sentencia while ejecuta iterativamente el bucle definido por el bloque de código <sentencia> siempre que el valor devuelto por la expresión <condición> (que debe estar entre paréntesis) sea cierto.
Nota: recordemos que cierto (true) equivale numéricamente a distinto de cero, mientras que falso (false) equivale al valor cero.
Puesto que la condición se evalúa antes que cada ejecución del bucle, si al comienzo <condicion> devuelve falso, <sentencia> no se ejecuta ninguna vez, y el control pasa a la siguiente sentencia. Si <condición> devuelve cierto se ejecuta el bucle <sentencia>, y a continuación se vuelve a evaluar <condicion> con lo que se repite el ciclo.

Ejemplos

while (*p == ' ') p++;

while ( i <= j) i++;

La sentencia puede estar vacía, realizándose entonces toda la computación requerida en la cláusula <condición>. 

Ejemplo:

while ( getchar() != 'Z' );

Aunque lo normal es que la <sentencia> sea un bloque de código entre corchetes:

while (i < n) {

  cout << i << endl;

  ++i;

}

Intente por sí mismo la explicación de las salidas del programa adjunto antes de leer el comentario final (esta disposición es muy utilizada en bucles que deben repetirse un número n de veces).


#include <iostream>

using namespace std;

int main() {   // ==========

  int x = 5, y = 5;

  while ( x-- ) {

    cout << "x = " << x << endl;

  }

  while ( --y ) {

    cout << " y = " << y << endl;

  }

  cout << "Terminado!!" << endl;

}

Salida:

x = 4

x = 3

x = 2

x = 1

x = 0

y = 4

y = 3

y = 2

y = 1

En ambas iteraciones, la condición indicada en el paréntesis es chequeada antes de ejecutar la iteración (la salida en pantalla).  La diferencia entre ambos es que el postdecremento (x--) se realiza después de la evaluación del paréntesis (comprobación de que su contenido es cierto). En consecuencia, el ciclo del primer bucle es como sigue:
comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
decremento unitario de x
dos posibilidades:

R == true  →  ejecutar el bucle (salida en pantalla) →  volver al punto 1.

R == false  →  abandonar el bucle.

En cambio, en el segundo bucle, el predecremento (--x) se realiza antes de la evaluación del paréntesis (comprobación de la condición del bucle). En consecuencia, el ciclo del segundo bucle puede resumirse así:
decremento unitario de x
comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
dos posibilidades:

R == true  →  ejecutar el bucle (salida en pantalla) →  volver al punto 1.

R == false  →  abandonar el bucle.

Bucle  do...while

La sentencia do ...  while permite ejecutar repetidamente un bloque de código mientras se cumpla una determinada condición que es chequeada después de cada iteración.

 Sintaxis

do <sentencia> while ( <condición> );


La sentencia do ejecuta repetidamente el bucle definido por el bloque de código <sentencia> hasta que la sentencia de control <condición> devuelve el valor falso.
Puesto que el control se evalúa después de cada ejecución del bucle, resulta que este se ejecuta al menos una vez, aunque <condición> devuelva el valor falso desde el principio (si requiere que el bucle no se ejecute ninguna vez, es mejor utilizar while).
La forma más genérica de la expresión suele ser:

do {

   <sentencia> ;

}  while ( <condición> );

 Ejemplo
Este programa solicita una clave de acceso indefinidamente hasta que el usuario proporciona una que coincide con el valor almacenado en la matriz checkword.

#include <stdio.h>

#include <string.h>

int main () {        // ===================

   char checkword[80] = "password";

   char password[80]  = "";

   do {

      printf ("Introducir clave: ");

      scanf("%s", password);

   } while (strcmp(password, checkword));

   return 0;

}

A continuación se muestra un caso simétrico al presentado para los bucles while , que utiliza los operadores unitarios de decremento. Intente explicar por sí mismo las salidas obtenidas antes de leer el comentario:

#include <iostream>

using namespace std;

int main() {    // ========

  int x = 5, y = 5;

  do {

    cout << "x = " << x << endl;

  } while ( x-- );

  do {

    cout << "y = " << y << endl;

  } while ( --y );

  cout << "Terminado!!" << endl;

}

Salida:

x = 5

x = 4

x = 3

x = 2

x = 1

x = 0

y = 5

y = 4

y = 3

y = 2

y = 1


En este caso, las el bloque de código (salida en pantalla) es ejecutado antes del chequeo de la condición expresada en el paréntesis. La diferencia entre ambos bucles es que en el primero, el postdecremento (x--) se realiza después de la evaluación del paréntesis (comprobación de que su contenido es cierto). En consecuencia, el ciclo es como sigue:
ejecutar el bloque de código (salida en pantalla)
comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
decremento unitario de x
dos posibilidades:

R == true  →  volver al punto 1.

R == false  →  abandonar el bucle.

En cambio, en el segundo bucle, el predecremento (--x) se realiza antes de la evaluación del paréntesis (comprobación de la condición del bucle). En consecuencia, su ciclo puede resumirse así:
ejecutar el bloque de código (salida en pantalla)
decremento unitario de x
comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
dos posibilidades:

R == true  →  volver al punto 1.

R == false  →  abandonar el bucle.

 Bucle  for

Esta sentencia permite realizar un bucle repetidamente en base a una condición, la cual suele estar basada en el valor de un contador que se actualiza después de cada ejecución del bucle.
 Sintaxis

for ( [<inicio>] ; [<condicion>] ; [<incremento>] ) <sentencia>

Descripción

La sentencia for realiza un bucle iterativo, es equivalente al:

for <inicio> to <condición> step <incremento>

   <sentencia>

next

de otros lenguajes. <inicio> e <incremento> pueden ser llamadas a funciones o sentencias de asignación. <sentencia> es del cuerpo del bucle, y puede ser cualquier bloque de código.
La utilización más común suele adoptar la forma:

for ( <inicio> ; <condición> ; <incremento> ) {

   <sentencia>;

}

Ejemplo

for(i=0; i<n; i++) { /* sentencias del bucle */ }

  <inicio> inicia las variables para el bucle antes de la primera iteración. Puede ser una expresión o una declaración. El ejemplo que sigue sería correcto en C++:

for (int i=0; i<10; i++)  printf("i =%5.0d\n", i);

En cambio, para compilarlo en C sería necesario declarar i en una expresión anterior:

int i;

for (i=0; i<10; i++)  printf("i =%5.0d\n", i);

El ámbito de una variable definida en la expresión <inicio> es variable, depende del interruptor -Vd del compilador .
  <condición> Debe ser una expresión relacional (devuelva un valor lógico). Es comprobada antes de la primera ejecución del bloque <sentencia>, que es ejecutado repetidamente hasta que <condición> sea falso, por lo que si <condición> devuelve falso desde el principio, el bucle no se ejecuta nunca.
  <incremento>. Después de cada iteración del bucle, <incremento> incrementa un contador de bucle; en consecuencia j++ es funcionalmente equivalente a ++j.
  <sentencia> es el bucle de for; sentencia o bloque de código que se ejecuta iterativamente. El ámbito de cualquier identificador declarado dentro él se limita al final de la sentencia de control.
  Todas las expresiones son opcionales, pero los separadores ; no pueden faltar. Si falta <condición>, se supone que es siempre cierta, por lo que se trata de un bucle indefinido del que se saldrá por otro mecanismo externo al propio for, que pueden ser un break o un return. Es típico utilizar este tipo de construcciones para construir bucles con una o más condiciones de salida


No hay comentarios.:

Publicar un comentario

P6-Estructuras

 Estructuras en C Las estructuras son colecciones de variables relacionadas bajo un nombre. Pueden contener variables de muchos tipos difere...