Curso-lenguaje-C/fundamentos-programacion/PEC1/README.md

29 KiB
Raw Blame History

PEC 1

Volver a la página principal de "Fundamentos de la Programación"

Índice

1. Tipos de datos

Los objetos son entidades que tienen un estado y un comportamiento. Los tipos de datos son la forma de representar los objetos en un programa.

1.1. Tipo elementales y objetos

Una variable es un nombre simbólico que hace referencia a una información concreta guardada en memoria.

Atributos de una variable:

  • Nombre: identificador de la variable.
  • Tipo: tipo de dato que almacena.
  • Valor: valor que almacena.
  • Dirección: dirección de memoria donde se almacena.
  • Visibilidad: ámbito de la variable.

Una constante es un valor que no puede ser modificado durante la ejecución del programa.

1.1.1. Tipos elementales

1.1.1.2. Enteros

Los enteros son números sin parte decimal. Pueden ser positivos o negativos. Los valores que se pueden asignar a una variable de tipo entero está entre dos valores concretos, un entero mínimo MIN_INTEGER y un entero máximo MAX_INTEGER que dependerán del ordenador que se utilice.

Identificador Descripción
Tipo integer
Rango de valores desde MIN_INTEGER hasta MAX_INTEGER
Operadores internos - (cambio de signo), + , - , * , div, mod
Operadores externos =, ≠, <, >, ≤, ≥
Ejemplos 3, -123, 9876, 0

Los operadores internos son aquellos que hacen que el resultado de operar dos valores de un tipo devuelva un valor del mismo tipo, mientras que los operadores externos son aquellos cuyo resultado de la operación es un valor de un tipo diferente.

De los operadores indicados en la tabla, los menos conocidos son div y mod que precisamente en programación se utilizan bastante.

div - devuelve el cociente de la división entera de dos números. mod - devuelve el resto de la división entera de dos números.

La división (/) no se ha incluido en la lista de operadores ya que no es un operador válido para el tipo entero.

1.1.1.3. Reales

Los reales son números con parte decimal. Pueden ser positivos o negativos. Los valores que se pueden asignar a una variable de tipo real está entre dos valores concretos, un real mínimo MIN_REAL y un real máximo MAX_REAL que dependerán del ordenador que se utilice.

Identificador Descripción
Tipo real
Rango de valores desde MIN_REAL hasta MAX_REAL
Operadores internos - (cambio de signo), + , - , * , /
Operadores externos =, ≠, <, >, ≤, ≥
Ejemplos 3.0 , -123.56 , 5.0E 8, 49.22E 8, 1.0E5

¡cuidado con las divisiones! Antes de dividir hay que comprobar siempre que el divisor sea diferente de 0. Si se divide por 0 durante la ejecución del programa se producirá un error y el programa dejará de funcionar.

1.1.1.4 Carácter

Los caracteres son símbolos que se pueden representar en la pantalla. Los valores que se pueden asignar a una variable de tipo carácter están entre dos valores concretos, un carácter mínimo MIN_CHAR y un carácter máximo MAX_CHAR que dependerán del ordenador que se utilice.

Internamente los caracteres están representados por números. A cada carácter le corresponde un número. El conjunto de correspondencias entre caracteres y números se llama código. Hay diferentes códigos, pero el más utilizado y que se ha convertido en estándar es el código ASCII (American Standard Code for Information Interchange), que utiliza un byte para representar cada carácter.

Identificador char
Rango de valores Conjunto finito de valores que depende del código utilizado por el ordenador
Operadores internos No hay
Operadores externos =, ≠, <, >, ≤, ≥
Ejemplos 'a', 'A', '?', '@', 'à'
1.1.1.4 Booleano

El tipo de dato booleano es un tipo de dato que puede tener uno de dos valores: verdadero o falso. En algunos lenguajes de programación se representa con 1 y 0, pero en otros se representa con true y false.

Su nombre procede del álgebra de Boole y toma del álgebra los operadores lógicos and, or y not.

a b a and b a or b not a
true true true true false
true false false true false
false true false true true
false false false false true
Identificador Descripción
Tipo boolean
Rango de valores false, true
Operadores internos and, or, not, =, ≠, <, >, ≤, ≥
Operadores externos no hay
Ejemplos false, true

1.2.1. Declaración de constantes

Sintaxis:

const
    CONST_NAME: type = value;
end const

El primer carácter del nombre ha de ser siempre alfabético. El resto pueden ser alfabéticos, numéricos o el carácter _. No puede haber espacios entre los caracteres.

Ejemplos:

const
    PI: real = 3.1415926;
    MAX_STUDENTS: integer = 50;
    IVA: integer = 21;
    BLANK_CHAR: char = ' ';
end const

1.2.2. Declaración de variables

Sintaxis:

var
    var_name: type;
end var

Igual que con las constantes, el primer carácter del nombre ha de ser siempre alfabético. El resto pueden ser alfabéticos, numéricos o de carácter _. No puede haber espacios entre los caracteres.

Si hay diversas variables del mismo tipo, podemos declararlas en la misma línea separándolas por comas:

var
    variableName1, variableName2, variableName3: type;
end var

Por convención, los nombres de las variables se escriben en minúscula y, si el nombre de la variable está formado por dos palabras, la primera letra de las palabras, exceptuando la de la primera palabra, se escribe en mayúscula. CamelCase.

var
    roomLength: real;
    roomWidth: real;
    currentNumberStudents: integer;
    initialLetter: char;
end var

oat roomLength;
oat roomWidth;
int currentNumberS
char initialLetter;

En las declaraciones de variables y constantes se puede ver una serie de palabras que forman parte de la sintaxis del lenguaje algorítmico y sirven para que el compilador (el intérprete del código escrito) entienda en cada momento qué se quiere hacer. Estas palabras se llaman palabras clave (o reservadas) del lenguaje y no se pueden utilizar como nombres ni de variables ni de constantes. Cada lenguaje de programación tiene sus palabras clave, aunque la mayoría son coincidentes entre los diferentes lenguajes.

1.2.3. Asignación a variables

En notación algorímitca, para asignar un valor a una variable, se utitliza el operador de asignación := que se lee "toma por valor". El operador = es el equivalente en C.

var
    variableName: type;
end var

variableName := value;
type variableName;
variableName=value;
var
    roomLength: real;
    roomWidth: real;
    currentNumberStudents: integer;
    initialLetter: char;
end var

    {Inicializamos las variables}
roomLength:=0.0;
roomWidth:=0.0;
currentNumberStudents:=0;
initialLetter:=' ';

oat roomLenght;
oat roomWidth;
int currentNumberStudents;
char initialLetter;
roomLenght=0.0;
roomWidth=0.0;
currentNumberStudents=0;
initialLetter=' ';

1.2 Tipos enumerativos

Los tipos enumerativos son aquellos que permiten definir un conjunto finito de valores que puede tomar una variable. Los valores que se pueden asignar a una variable de tipo enumerativo están entre los valores que se han definido en la declaración del tipo.

type
    enumType = (value1, value2, value3, ..., valueN);
end type

typedef enum { VALUE1, VALUE2, VALUE3, ... , VALUEN } typeName;

Ejemplo con los días de la semana:

type
    daysOfTheWeek = {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}
end type

var
    rstDay: daysOfTheWeek;
    lastDay: daysOfTheWeek;
end var

typedef enum { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
daysOfTheWeek;
daysOfTheWeek rstDay;
daysOfTheWeek lastDay;

1.2.1 Operaciones con tipos enumerativos

Los únicos operadores que se pueden aplicar a los tipos enumerativos son los operadores relacionales externos ( =, #, <, >, #, # )

1.3. Expresiones

Una expresión es una combinación de valores, variables, operadores y funciones que se evalúa para obtener un resultado con un valor de alguno de los tipos primitivos del lenguaje..

Dentro de todo el conjunto de expresiones, las que devuelven un resultado numérico se llaman expresiones aritméticas. Las que devuelven un resultado booleano se llaman expresiones lógicas. Y existen más como las expresiones de cadena o las expresiones de caracteres.

1.3.1. Semántica de una expresión

La semántica de una expresión es el significado que tiene la expresión. En el caso de las expresiones aritméticas, la semántica es el valor numérico que se obtiene al evaluar la expresión. En el caso de las expresiones lógicas, la semántica es el valor booleano que se obtiene al evaluar la expresión.

No todas las expresiones sintácticamente correctas se pueden evaluar. También es necesario que sean semánticamente correctas. Ejemplos:

  • 3/0 no se puede evaluar ya que el resultado de dividir un número por 0 no está definido.
  • 6 + 8.8 Porque suma un entero y un real.
  • true < 35 Porque compara un booleano y un entero.
  • c + 34 < b Porque suma un caracter y un entero
  • 45 < 56 < 90 Compara primero dos enteros y el resultado, que es un booleano, se compara con un entero.

1.3.2. Prioridad de los operadores

La prioridad de los operadores es el orden en que se evalúan las operaciones. Los operadores con mayor prioridad se evalúan antes que los de menor prioridad. El contenido de los paréntesis son las primeras. Si dos operadores tienen la misma prioridad, se evalúan de izquierda a derecha. Las prioridades:

Prioridad Operadores
1 (cambio de signo), not
2 *, /, div, mod
3 +,-
4 =, ≠, >, <, ≤, ≥
5 and
6 or

1.4. Funciones de conversión de tipo

Las funciones de conversión de tipo son funciones que permiten convertir un valor de un tipo a otro tipo. Las funciones disponibles en lenguaje algorítmico son:

  • integerToReal, que convierte un entero en real.
  • realToInteger, que dado un real retorna su parte entera.
  • codeToChar, que dado un código ASCII retorna el carácter correspondiente.
  • charToCode, que dado un carácter retorna su código ASCII.

Ejemplos:

  • realToInteger(789.78) = 789.
  • codeToChar(65) = A.
  • charToCode(s) = 115.
  • integerToReal(10) = 10.0.

2. Tipos básicos de datos en C

2.1 Objetos elementales del lenguaje C

Nombre o identificador ¿Es correcto? Comentario
ventas Es recomendable escribir en minúsculas.
_articulo No No empieza por un carácter alfabético.
aux2 Poco recomendable. Es mejor usar nombres descriptivos.
1_articulo No No empieza por un carácter alfabético.
numero articulos No Los espacios en blanco no son permitidos.
numeroArticulos Es un nombre descriptivo.
piezaCamión No No se pueden utilizar caracteres especiales ni acentos (la "ñ" se considera un carácter especial)
const No Es

2.1.1. Tipos elementales en C

2.1.1.1. Tipo booleano

Para poder usar la librería stdbool.h será necesario importarla previamente al inicio de nuestros programas en lenguaje C de la siguiente forma:

#include <stdbool.h>
Característica Lenguaje algorítmico Lenguaje C
Identificador boolean bool
Rango de valores true, false true, false
Operadores internos not, and, or, =, ≠, <, ≤, >, ≥ !, &&,
2.1.1.2. Tipo carácter

En C los caracteres van delimitados por comillas simples como en el lenguaje algorítmico. La tabla siguiente resume las características del tipo carácter y su traducción a C.

Característica Lenguaje algorítmico Lenguaje C
Identificador caracter char
Rango de valores conjunto finito de valores conjunto finito de valores definidos por el código ASCII
Operadores externos =, ≠, <, ≤, >, ≥ ==, !=, <, <=, >, >=
Sintaxis de valores 'a', 'W', '1' 'a', 'W', '1'
2.1.1.3. Tipo entero

La siguiente tabla resume las características del tipo entero y su traducción a C.

Característica Lenguaje algorítmico Lenguaje C
Identificador integer int
Rango de valores MIN_INTEGER a MAX_INTEGER -2147483648, 2147483647
Operadores internos - (cambio de signo), +, -, *, div, mod - (cambio de signo), +, -, *, /, %
Operadores externos =, ≠, <, ≤, >, ≥ ==, !=, <, <=, >, >=
Sintaxis de valores 3, 465434, -2134567 3, 465434, -2134567

El rango de los enteros puede variar según el compilador y el ordenador donde se ejecute el programa.

2.1.1.4. Tipo real

La siguiente tabla resume las características del tipo real y su traducción a C.

Característica Lenguaje algorítmico Lenguaje C
Identificador real float
Rango de valores MIN_REAL a MAX_REAL (no todos) ±3.4E±38 (7 dígitos significativos)
Operadores internos - (cambio de signo), +, -, *, / - (cambio de signo), +, -, *, /
Operadores externos =, ≠, <, ≤, >, ≥ ==, !=, <, <=, >, >=
Sintaxis de valores 0.6, 5.0E-8, -49.2E+0.8, 1.0E5, 4.0 0.6, 5.0E-8, -49.2E+0.8, 1.0E5, 4.0

El lenguaje C permite reales con más dígitos significativos: los tipos double y long double.

2.1.2. Declaración de objetos en C

Para declarar una constante, se utiliza la construcción:

const tipo nombre = valor;

A veces es conveniente definir constantes con valor conocido ya durante la compilación. Se puede hacer con la directiva #define:

#define NOMBRE valor

Para declarar una variable, se usa la sintaxis siguiente:

tipo nombre;

Por ejemplo, para declarar tres variables i, j, k de tipo entero:

int i, j, k;

2.1.3. Expresiones en C

Las expresiones en lenguaje C siguen las mismas reglas de construcción y evaluación que en el lenguaje algorítmico. En caso de duda, sin embargo, siempre es aconsejable poner un paréntesis de más para indicar claramente la orden de evaluación de la expresión.

2.1.4. Definición de tipos. Tipos enumerados en C

El constructor de tipos enumerados en C sigue la siguiente sintaxis:

typedef enum {valor1, valor2..., valorn} nombre;

2.1.5. Funciones de conversión de tipos

Lenguaje algorítmico Lenguaje C Ejemplo
realToInteger (int) (int) -3.99
integerToReal (float) (float) 3
charToCode (int) (int) 'A'
codeToChar (char) (char) 65

2.2 Especificación de algoritmos

Sintaxis de C para los comentarios.

/* Pre: precondición */
algoritmo
/* Post: postcondición */

2.3. Estructuras algorítmicas

2.3.1. Estructura general de un programa en lenguaje C

La estructura de un programa en lenguaje C es la siguiente:

/* Programa estructura.c Estructura básica de un programa en C
Jordi Riera, 2018
*/
/* Inclusión de ficheros de cabecera */
#include <stdbool.h>
#include <fichero2>
/* ... */
/* Declaración de constantes en tiempo de compilación */
#define NOMBRE_CONSTANTE1 valor_define1
#define NOMBRE_CONSTANTE2 valor_define2
/* ... */
/* Declaración de tipos */
typedef definicion_de_tipo1 nombre_tipo1;
typedef definicion_de_tipo2 nombre_tipo2;
/* ... */
int main() {
    /* Definición de constantes */
    const tipo_de_constante1 nombre_constante1 = valor_constante1;
    const tipo_de_constante2 nombre_constante2 = valor_constante2;
    /* ... */
    /* Declaración de variables */
    tipo_de_variable1 nombre_variable1;
    tipo_de_variable2 nombre_variable2;
    /* Cuerpo del programa */
    accion1
    accion2
    /* ... */
}

2.3.2. Acciones elementales: la asignación

La acción de asignación del lenguaje algorítmico, ":=" se traduce en el operador de asignación en lenguaje C, "=".

La distinción entre acción y operador es muy importante, ya que implica que el lenguaje C permite hacer asignaciones en cualquier punto del código donde una expresión sea válida.

Por ejemplo, es un error muy común hacer una asignación, en vez de una comparación en la condición de una sentencia condicional, por usar el operador de asignación "=" en lugar del operador relacional de igualdad "==", lo cual tiene graves repercusiones de cara al buen funcionamiento del programa.

3. Funciones de entrada/salida

Cuando pensamos en entrada de datos nos referimos a cualquier tipo de entrada; pueden ser las teclas que se pulsan en un teclado, la posición del ratón o pantalla táctil, un fichero en disco, una dirección de internet, un lector de códigos de barras, una webcam o el micrófono.

Del mismo modo, cuando hablamos de salida nos podemos referir a un amplio abanico de opciones, desde la pantalla del ordenador, un archivo, una impresora o el sistema de control de un robot.

Si no se cambia explícitamente, la entrada estándar (o stdin del inglés standard input) es el teclado, y la salida estándar (o stdout del inglés standard output) es la pantalla.

3.1. Entrada

Cuando se pulsan teclas en un teclado, estas se convierten en su código ASCII y se almacenan como caracteres en lo que se llama un buffer, el cual contiene toda la secuencia de caracteres que han escrito y que ningún programa ha leído todavía.

keyboard --> buffer --> programa

Este buffer es una estructura conocida como FIFO (First In First Out)

Para leer la información de este buffer, tenemos a nuestra disposición un conjunto de instrucciones en lenguaje algorítmico según el tipo de datos que queremos leer:

Instrucción Descripción
readChar Lee un caracter del buffer
readBoolean Lee un boolean del buffer
readInteger Lee un entero del buffer
readReal Lee un real del buffer
readString Lee una cadena de caracteres del buffer

3.2. Salida

Cuando escribimos en la salida estándar, toda la información queda guardada en forma de caracteres en un buffer, que se va leyendo y mostrando en la pantalla.

keyboard --> Buffer --> screen

Instrucción Descripción
writeChar Escribe un caracter en el buffer
writeBoolean Escribe un boolean en el buffer
writeInteger Escribe un entero en el buffer
writeReal Escribe un real en el buffer
writeString Escribe una cadena de caracteres en el buffer

3.3. Entrada y salida en C

Con la librería stdio (standard input/output) se pueden realizar operaciones de entrada y salida en C. Se debe incluir la librería al inicio del programa:

# include <stdio.h>
Tipo de dato Especificativo de tipo Ejemplo de datos
Caracter %c 'a'
Booleano %d 0 (equivalente de false), 1 (equivalente de true)
Enumerativo %u {VALUE1, VALUE2, ... VALUEN}
Entero %d 34 o -32
Real %f 3.1415
String %s "Hello World"
Puntero %p 0x000000AA; los punteros los trataremos en el módulo "13. Punteros en C".

3.3.1. Entrada

El método genérico para la entrada de datos es el método scanf que permite leer datos de la entrada estándar. La sintaxis es la siguiente:

scanf("formato", &variable);
Método Traducción a C
readChar scanf("%c", &c)
readBoolean scanf("%d", &b)
readInteger scanf("%d", &i)
readReal scanf("%f", &r)
readString scanf("%s", s)

Además, con la instrucción getchar se puede leer un carácter de la entrada estándar.

c = getchar();

Al leer un carácter después de otro tipo de dato en C, el salto de línea del dato anterior puede interferir. Para solucionarlo, se puede usar getchar() para limpiar el búfer antes de scanf():

scanf("%d", &i);
getchar();
scanf("%c", &c);

3.3.2. Salida

El método genérico para la salida de datos es el método printf que permite escribir datos en la salida estándar. La sintaxis es la siguiente:

printf("formato", variable);
Método Traducción a C
writeChar printf("%c", c)
writeBoolean printf("%d", b)
writeInteger printf("%d", i)
writeReal printf("%f", r)
writeString printf("cadena de caracteres")
writeString printf("%s", s)

Adicionalmente, podemos añadir modificaciones a cómo queremos que se muestren los datos. Estos modificadores se ponen entre el símbolo % y el especificativo de tipo:

%[modificadores][ancho][.precisión]especificativo

Más info: https://www.tutorialspoint.com/c_standard_library/c_function_printf.htm

3.4. Ejemplos

3.4.1. Ejemplo 05_01: entrada

algorithm sum

    var
        a: integer;
        b: integer;
        s: integer;
    end var

    a:= readInteger();
    b:= readInteger();
    s:= a + b;

end algorithm

# include <stdio.h>
int main() {
    int a;
    int b;
    int s;
    scanf("%d", &a);
    scanf("%d", &b);
    s=a+b;
    return 0;
}

3.4.2. Ejemplo 05_02: salida

algorithm sumaSalida

    var
        a: integer;
        b: integer;
    end var
    a:= 2;
    b:= 2;
    writeString("La suma de a y b es :");
    writeInteger(a + b);

end algorithm

# include <stdio.h>
int main() {
    int a=2;
    int b=2;
    printf("La suma d'a i b és : %d", a + b);
    return 0;
}

3.4.3. Ejemplo 05_03: entrada y salida

algorithm sumaEntradaSalida

    var
        a: integer;
        b: integer;
        c: integer;
        m: real;
    end var

    a:= readInteger();
    b:= readInteger();
    c:= readInteger();
    m:= integerToReal(a+b+c)/3.0;
    writeReal(m);

end algorithm

# include <stdio.h>
int main() {
    int a;
    int b;
    int c;
    oat m;
    scanf("%d", &a);
    scanf("%d", &b);
    scanf("%d", &c);
    m=(a+b+c)/3.0;
    printf("%f", m);
    return 0;
}

Volver arriba