Curso-lenguaje-C/fundamentos-programacion/PEC3/README.md
2024-03-24 09:28:33 +01:00

14 KiB

PEC 3

Índice

5. Estructura de control alternativa

Estructuras de control de flujo.

5.1. Estructura alternativa

  • Consulta sobre el estado actual o condición - Reacciona en función del valor obtenido. Tendrá como respuesta un valor lógico (verdadero o falso), pudiendo de esta forma tomar una decisión entre dos caminos distintos.
  • Qué hacer cuando la condición es verdadera - Conjunto de instrucciones que se ejecutarán en caso verdadero.
  • Qué hacer cuando la condición es falsa (opcional) - Conjunto de instrucciones que se ejecutarán en caso falso.
  • Fin - Continua la ejecución del resto del programa.

5.2. Codificación de una estructura de control alternativa

Partes Codificiación en lenguaje algorítmico
Consulta sobre el estado actual o condición If estructura condicial then
Qué hacer cuando la condición es verdadero bloque de instrucciones
Qué hacer cuando la condición es falso else
bloque de instrucciones
Marca de fin de estructura alternativa end if

Ejemplos:

Si un número es par mostrar un mensaje.

algorithm ex4
  var
    n: integer;
  end var

  n := readInteger();

  if n mod 2 = 0 then
    writeString("Es par");
  end if

end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
  int n;
  scanf("%d", &n);

  if (n%2 == 0) {
    printf("Es par");
  }

  return 0;

}

Si la temperatura es menor que 21ºC encender la calefacción. Si la temperatura es mayor o igual que 21ºC apagar la calefacción.

algorithm ex5
  var
    t: real;
  end var
  t := readReal();
  if t < 21 then
    switchOnHeating();
  else
    switchOffHeating();
  end if
end algorithm


#include <stdio.h>

int main(int argc, char** argv) {
  oat t;
  scanf("%f", &t);

  if (t < 21) {
    switchOnHeating();
  } else {
    switchOffHeating();
  }
  return 0;
}

Si la temperatura es menor que 18ºC encender la calefacción. Si la temperatura es mayor que 26ºC encender el aire acondicionado. En cualquier otro caso apagar la calefacción y el aire acondicionado.

algorithm ex6
  var
    t: real;
  end var
  t := readReal();
  if t < 18 then
    switchOnHeating():
  else
    if t > 26 then
      switchOnAirConditioning();
    else
      switchOffHeating();
      switchOffAirConditioning();
    end if
  end if
end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
  oat t;
  scanf("%f", &t);

  if (t < 18) {
    switchOnHeating();
  } else {
    if (t > 26) {
      switchOnAirConditioning();
    } else {
      switchOffHeating();
      switchOffAirConditioning();
    }
  }
  return 0;
}

Si la edad es menor que 18 años mostrar un mensaje. Si la edad es mayor o igual que 18 años preguntar si tiene carnet de conducir. Si tiene carnet de conducir mostrar un mensaje. Si no tiene carnet de conducir mostrar otro mensaje.

algorithm carPooling
  var
    age: integer;
    hasDrivingLicense: boolean;
  end var
  writeString("How old are you?");
  age := readInteger();
  if age < 18 then
    writeString("You still cannot drive");
  else
    writeString("Do you have a driving licence?");
    hasDrivingLicense := readBoolean();
    if hasDrivingLicense then
      writeString("Nice, we can share the car");
    else
      writeString("I do. If you want we can use my car");
    end if
  end if
end algorithm

#include <stdio.h>
#include <stdbool.h>
int main(int argc, char **argv) {
  int age;
  bool hasDrivingLicense;
  int aux;
  printf("How old are you?\n");
  scanf("%d", &age);
  if (age < 18){
    printf("You still cannot drive\n");
  } else {
    printf("Do you have driving licence?\n");
    scanf("%d", &aux);
    hasDrivingLicense = aux;
    if (hasDrivingLicense) {
      printf("Nice, we can share the car\n");
    } else {
      printf("I do. If you want we can use my car\n");
    }
  }
  return 0;
}

6. Tipos de datos: Vectores y matrices

Podemos definir variables que contienen varios elementos de un mismo tipo. Según estas variables tengan 1 o 2 dimensiones, las llamaremos vectores o matrices respectivamente.

6.1. Vectores

Los vectores o arrays, son estructuras de una sola dimensión, que contienen n valores de un mismo tipo.

var
  t : vector[7] of real;
end var
/* Variable definition */
float t[7];

Para acceder a una posición de un vector se utiliza el índice de la posición deseada. El índice de un vector empieza en 0.

Es importante el valor que tiene la primera posición. En algunos lenguajes el valor 0 es el primer valor definido y en otros lenguajes el primer valor es 1.

En lenguaje algorítmico el primer valor es 1.

En lenguaje C el primer valor es 0.

Por ejemplo, para acceder a los valores de un vector de 7 posiciones en lenguaje algorítmico se haría de la siguiente forma:

algorithm tempAverage
  var
    t: vector[7] of real;
    m: real;
  end var
  t[1] := readReal();
  t[2] := readReal();
  t[3] := readReal();
  t[4] := readReal();
  t[5] := readReal();
  t[6] := readReal();
  t[7] := readReal();
  m := (t[1] + t[2] + t[3] + t[4] + t[5] + t[6] + t[7]) / 7.0;
  writeReal(m);
end algorithm

Y en lenguaje C se haría de la siguiente forma:

#include <stdio.h>

int main(int argc, char** argv) {
  oat t[7];
  oat m;
  scanf("%f", &t[0]);
  scanf("%f", &t[1]);
  scanf("%f", &t[2]);
  scanf("%f", &t[3]);
  scanf("%f", &t[4]);
  scanf("%f", &t[5]);
  scanf("%f", &t[6]);
  m=(t[0] + t[1] + t[2] + t[3] + t[4] + t[5] + t[6]) / 7.0;
  printf("%f", m);
  return 0;
}

Dado que cuando se carga un programa para su ejecución se reserva la memoria para sus variables, cuando definimos un vector podemos utilizar constantes para su dimensión, pero nunca variables, ya que estas no tienen un valor conocido hasta que ya se está ejecutando el programa.

#include <stdio.h>
#define N 3
int main(int argc, char** argv) {
  oat v[N];
}

#include <stdio.h>
int main(int argc, char** argv) {
  int m;
  m := 3;
  oat v[m];
}x

Cuando la longitud de un vector es un dato conocido, es una buena práctica definirla como una constante. De esta forma, si en algún momento necesitamos cambiar la longitud del vector, solo tendremos que modificar el valor de la constante.

6.1.1. Cadenas de caracteres o strings

Un tipo muy utilizado de vector son las cadenas de caracteres o strings. En C, las cadenas de caracteres son vectores de caracteres terminados en el carácter nulo \0 (Valor ASCII 0).

Por lo tanto, si queremos guardar una cadena de caracteres será necesario reservar memoria para una posición adicional.

algorithm sayHello
  var
    name: string;
  end var
  writeString("What's your name?");
  name := readString();
  writeString("Hello");
  writeString(name);
end algorithm

#include <stdio.h>

#define MAX_NAME_LEN 25
int main(int argc, char** argv) {
  char name[MAX_NAME_LEN];
  printf("What's your name?\n");
  scanf("%s", name);
  printf("Hello %s\n", name);
  return 0;
}

Cuando utilizamos la instrucción en C scanf no ponemos el símbolo & delante.

Con los strings podemos utilizar los mismos operadores externos que con los caracteres =, ≠, <, >, ≤, ≥ para compararlos. La comparación se hace siguiendo el orden alfabético empezando por el primer caracter.

6.1.2. Representación de memoria

Todas las posiciones de un vector se guardan en memoria consecutivamente. La dirección de memoria de la primera posición del vector es la dirección de memoria de la variable que lo contiene.

6.1.3. Inicialización

Como buena práctica, primero definimos el vector especificando su tamaño máximo y después lo inicializamos.

algorithm vectors
  var
    v1 : vector[3] of integer;
    v2 : vector[4] of integer;
  end var
  v1[1] := 3;
  v1[2] := 5;
  v1[3] := -1;
  v2[1] := 3;
  v2[2] := 5;
  v2[3] := -1;
end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
  /* Variable definition*/
  int v1[3];
  int v2[4];
  v1[0] = 3;
  v1[1] = 5;
  v1[2] = -1;
  v2[0] = 3;
  v2[1] = 5;
  v2[2] = -1;
  return 0;
}

En el caso de v2, es un vector de 4 posiciones del que solo inicializamos las 3 primeras.

En el caso de las cadenas de caracteres, podemos utilizar las comillas dobles ("), o tratarlo igual que un vector normal y asignar carácter a carácter. A continuación se muestra un ejemplo donde, para cada string, se muestra su contenido, el tamaño en bytes y la cantidad de caracteres (se contabilizan hasta encontrar el símbolo de final de cadena '\0')

#include <stdio.h>
#include <string.h>

int main(int argc, char** argv) {
  char a[4];
  char b[5];
  char c[4];
  char d[5];
  a[0] = 'a';
  a[1] = 'b';
  a[2] = 'c';
  a[3] = '\0';
  b[0] = 'a';
  b[1] = 'b';
  b[2] = 'c';
  b[3] = '\0';
  strcpy(c, "abc");
  strcpy(d, "abc");
  printf("a - %s --> (%d) bytes, (%d) chars\n", a, sizeof(a), strlen(a));
  printf("b - %s --> (%d) bytes, (%d) chars\n", b, sizeof(b), strlen(b));
  printf("c - %s --> (%d) bytes, (%d) chars\n", c, sizeof(c), strlen(c));
  printf("d - %s --> (%d) bytes, (%d) chars\n", d, sizeof(d), strlen(d));
  return 0;
}

6.2. Matrices

Las matrices son vectores de dos dimensiones. Se pueden definir como un vector de vectores.

algorithm matrix
  var
    m : vector[2][3] of integer;
  end var
  m[1][1] := 1;
  m[1][2] := 2;
  m[1][3] := 3;
  m[2][1] := 4;
  m[2][2] := 5;
  m[2][3] := 6;
end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
  /* Variable definition*/
  int m[2][3];
  m[0][0] = 1;
  m[0][1] = 2;
  m[0][2] = 3;
  m[1][0] = 4;
  m[1][1] = 5;
  m[1][2] = 6;
  return 0;
}

Primero se declara el número de filas y luego el de columnas.

Igual que en el caso de los vectores unidimensionales, con los de n-dimensiones el índice de las posiciones empieza por 1 con lenguaje algorítmico, y por 0 con lenguaje C.

Ejemplo que calcula el valor promedio de todos los valores de la matriz anterior:

algorithm matAverage
  var
  m : vector[2][3] of integer;
    r : real;
  end var
  m[1][1] := 1;
  m[1][2] := 2;
  m[1][3] := 3;
  m[2][1] := 4;
  m[2][2] := 5;
  m[2][3] := 6;
  r := integerToReal(m[1][1] + m[1][2] + m[1][3] + m[2][1] + m[2][2] + m[2][3]);
  r := r/6.0;
  writeReal(r);
end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
/* Variable definition*/
int m[2][3];
  oat r;
  m[0][0] = 1;
  m[0][1] = 2;
  m[0][2] = 3;
  m[1][0] = 4;
  m[1][1] = 5;
  m[1][2] = 6;
  r = (m[0][0] + m[0][1] + m[0][2] + m[1][0] + m[1][1] + m[1][2]) / 6.0;
  printf("%f\n", r);
  return 0;
}

Cuando se guarda en memoria, se hace por filas. Por tanto, una matriz como la anterior en memoria es equivalente a un vector de 2x3 = 6 posiciones y por tanto de 6x4 = 24 bytes.

6.3. Ejemplos

Algoritmo que calcule el producto escalar de dos vectores en un espacio de dos dimensiones (2D)

algorithm dotProduct
  var
    a : vector[2] of integer;
    b : vector[2] of integer;
    c : integer;
  end var
  a[1] := readInteger();
  a[2] := readInteger();
  b[1] := readInteger();
  b[2] := readInteger();
  c := a[1] * b[1] + a[2] * b[2];
  writeInteger(c);
end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
  /* Variable definition*/
  int a[2], b[2];
  int c;
  scanf("%d", &a[0]);
  scanf("%d", &a[1]);
  scanf("%d", &b[0]);
  scanf("%d", &b[1]);
  c = a[0] * b[0] + a[1] * b[1];
  printf("(%d,%d) * (%d,%d) = %d\n", a[0], a[1], b[0], b[1], c);
  return 0;
}

Algoritmo que calcule el producto entre la matriz identidad de 3x3 y un valor entero introducido por teclado.

algorithm dotProduct
  var
    id : vector[3][3] of integer;
    s : integer;
    r : vector[3][3] of integer;
  end var
  id[1][1] := 1;
  id[1][2] := 0;
  id[1][3] := 0;
  id[2][1] := 0;
  id[2][2] := 1;
  id[2][3] := 0;
  id[3][1] := 0;
  id[3][2] := 0;
  id[3][3] := 1;
  s := readInteger();
  r[1][1] := id[1][1] * s;
  r[1][2] := id[1][2] * s;
  r[1][3] := id[1][3] * s;
  r[2][1] := id[2][1] * s;
  r[2][2] := id[2][2] * s;
  r[2][3] := id[2][3] * s;
  r[3][1] := id[3][1] * s;
  r[3][2] := id[3][2] * s;
  r[3][3] := id[3][3] * s;
end algorithm

#include <stdio.h>

int main(int argc, char** argv) {
  /* Variable definition*/
  int id[3][3];
  int s;
  int r[3][3];
  id[0][0] = 1;
  id[0][1] = 0;
  id[0][2] = 0;
  id[1][0] = 0;
  id[1][1] = 1;
  id[1][2] = 0;
  id[2][0] = 0;
  id[2][1] = 0;
  id[2][2] = 1;
  scanf("%d", &s);
  r[0][0] = id[0][0] * s;
  r[0][1] = id[0][1] * s;
  r[0][2] = id[0][2] * s;
  r[1][0] = id[1][0] * s;
  r[1][1] = id[1][1] * s;
  r[1][2] = id[1][2] * s;
  r[2][0] = id[2][0] * s;
  r[2][1] = id[2][1] * s;
  r[2][2] = id[2][2] * s;
  return 0;
}

7. Cambio de tipos de datos en C

7.1. Reglas de coneversión

7.2. Cambio explícito de tipos de datos

8. Cadenas de carácteres en C

8.1. Cadenas de caracteres o strings

8.1.1. Definición

8.1.2. Asignación

8.1.3. Comparación

8.2. Programación segura