Programación en C (2013)

Apunte Español
Universidad Universidad Politécnica de Cataluña (UPC)
Grado Ingeniería de Sistemas Audiovisuales - 1º curso
Asignatura FO
Año del apunte 2013
Páginas 16
Fecha de subida 30/06/2014
Descargas 13
Subido por

Vista previa del texto

1 – Empezando a Programar ¿Cómo vemos un Ordenador? • Dispositivo electrónico que permite transmitir, recibir, almacenar, y manipular información de manera automática mediante la ejecución de programas.
• De manera simplificada, se compone de tres partes esenciales Programas • Los programas son un conjunto de instrucciones que el ordenador interpreta y ejecuta automáticamente, requiriendo la intervención del usuario solo cuando es necesario – Navegar por Internet – Jugar a videojuegos – Reproducir vídeos o música – Resolver problemas de ingeniería Programas = Algoritmos + Datos • Un algoritmo es un conjunto ordenado de pasos que conducen a la solución de un problema en un tiempo finito – Debe ser preciso: cada paso se debe seguir en orden – Debe estar bien definido: si seguimos dos veces el mismo algoritmo con los mismos datos, obtendremos el mismo resultado.
– Finito: ha de acabar en algún momento Datos • La unidad básica de información es el bit (Binary digIT) Solo puede tener dos valores posibles: 0 o 1.
• Los bits se pueden agrupar – Un byte es una agrupación de 8 bits. Puede representar 256 valores distintos (28) – Dos bytes, 16 bits, pueden representar 65.536 valores (216) – Cuatro bytes, 32 bits, pueden representar 4.294.967.296 valores (232) • Internamente al ordenador, los datos son ristras de bits: 0101001010101000111110010101 Lenguaje de programación – Conjunto de señales eléctricas (0 y 1) que representan una orden (instrucción) muy básica – Un programa en lenguaje máquina no es compatible entre diferentes tipos de máquinas • no puedo poner el Office del PC en el iPad • El lenguaje ensamblador permite que una persona pueda escribir programas en código máquina – Conjunto de instrucciones (texto) muy sencillas – Traducción casi directa al código máquina (0 y 1) mediante un programa ensamblador Lenguajes de alto nivel • Texto en un lenguaje que sigue una estructura formal determinada • Son fáciles de entender tanto para una persona como para una máquina • Un compilador nos permite traducir un programa en lenguaje de alto nivel a un programa en código máquina para una CPU concreta.
Pasos para crear un programa 1. Analizar el problema/tarea en cuestión 2. Pensar en el algoritmo que nos ayude a resolverlo, y los datos que necesita 3. Codificar el algoritmo en un lenguaje de programación 4. Prueba: ejecutar el programa y analizar si funciona bien. Si el resultado no nos satisface, mirar si en los pasos anteriores hemos hecho algo mal.
El lenguaje de programación C – Es fácil de usar por un humano (alto nivel) – Permite programar partes internas de la máquina sin recurrir al código máquina (bajo nivel) • Lenguaje formado por: – 40 palabras. Las más comunes: case char default for while double else enum extern float if int long return short struct typedef unsigned void – Varios símbolos y operadores + - * / ( ) ; > && || \ ! { } & " ' Estructura Variables • Una variable es un espacio en la memoria que guarda un dato (un número, una letra, un texto…) que se puede consultar y modificar en cualquier momento. Su valor puede cambiar a lo largo de la vida del programa.
• Al inicio de nuestro programa, hemos de definir qué variables se van a usar: – Elegir el tipo de dato que guardará: un número entero, un número con decimales, una letra, un texto… – Darle un nombre: será el nombre que nosotros queramos. Debe ser descriptivo del dato que guarda.
– Darle un valor inicial (opcional): podremos cambiar este valor a lo largo del programa • Ejemplos: int numero; // un numero entero, sin valor inicial double x = 2.2 , y = 1.1; //dos números reales con valor inicial char letra = 'A'; // un carácter, con valor inicial • Elegir un nombre para una variable – El nombre puede contener letras, números, y el signo de subrayado ‘_’ – La primera letra no puede ser un número – Diferencia entre mayúsculas y minúsculas Tipos de datos elementales: entero • Guarda un número entero (ℤ) • Ejemplo: short año = 2013; int DNI = 123445684; // No se usa el punto como separador de millones// Reales • Guarda un número real (ℝ) • Ejemplos: float a = 3.2f; double b = 3.3434334; long double c = -2.334e2500; Caracteres • Guarda un símbolo alfanumérico • Ejemplo char letra = 'F'; char simbolo = '!'; ¡Ojo! • Errores comunes – Confundir un carácter con un número char caracter = '1'; char numero = 1; // los ‘char’ también pueden guardar números del -128 al 127 (256 valores) // – Confundir un carácter con el nombre de variable char x = 'y'; // la variable x tiene valor ‘y’ char y = 'A'; // la variable y tiene valor ‘A’ (no ‘y’) – Confundir un carácter con una cadena de texto char correcto = 'V'; // Bien char erroneo = "V"; // Error!! Los caracteres se definen mediante comillas simples. Más adelante veremos que las comillas dobles se usan para definir cadenas de texto// Ejemplo: "Hola, esto es un texto completo" Importancia del tipo de variable • En una variable, solo se pueden almacenar datos del tipo especificado: – Un int no puede almacenar números con decimales float – Un char no podrá almacenar números superiores a 127 – Un short no podrá almacenar números superiores a 32767.
– Un float no podrá almacenar números de precisión double • Sin embargo...
– Un float puede almacenar int – Un int puede almacenar un short Constantes • Una constante es un identificador que representa un valor constante, que no se puede modificar. A diferencia de las variables, no tiene un tipo concreto. Solo es un valor.
• Sintaxis: #define nombre valor • Se definen en la cabecera del programa • Ejemplos: #define PI 3.1416 #define E 2.71828 • Por convenio, las variables se escribirán en minúsculas y las constantes en mayúscula.
Ejemplo: calcular la longitud de una circunferencia #define PI 3.1416 void main() { float radio, longitud; Sentencias • Cada sentencia determina una acción a realizar en el orden en que se ha escrito.
• Tipos: – Asignación de un valor a una variable: • Sintaxis: nombre_variable = expresión; • Ejemplo: int a,b,c; a = 3; b = 4 * 8; c = b + a; – Llamada a una función: conjunto de sentencias identificadas por un nombre que realizan una tarea determinada a partir de unos parámetros datos, y que puede retornar un valor • Sintaxis: nombre_funcion(expresión, expresión…) • Ejemplo: printf(“Hola!”); • Podemos crear nuestras propias funciones, o podemos usar alguna de las centenares de funciones que C trae definidas y guardadas en bibliotecas • Ojo! Cada sentencia debe finalizar con un punto y coma ‘ ; ’ que hace de separador entre sentencia y sentencia.
Expresiones • Fórmulas que son utilizadas por las sentencias que retornan un valor: – Constantes: a = 3; Se asigna a “a” el valor de la expresión constante “3” – Variables: a = b; Se asigna a “a” el valor que en ese momento tenga la variable “b” – Funciones: c = sin(a); Se asigna a “c” el valor que retorna la función “seno de a”, es decir, el seno del valor que tenga la variable a en ese momento – Combinadas mediante operadores aritméticos+ - * / % ++ *Operador aritmético % • Retorna el resto de una división entera *Operadores unarios ++ y -• Incrementan o decrementan el valor de una variable, y guardan ese nuevo valor en la variable. Además, lo retornan.
• Mostrar un mensaje en pantalla printf(“Hola!!\n”); • Mostrar un mensaje que variará según el valor de una variable: int a = 3; printf(“El valor de a es %d \n”, a); a++; printf(“El valor de a es %d \n”, a); • Sintaxis: – '\n' es un salto de línea (carácter especial) – %d dice que ahí hay que escribir el valor del número entero que va después del texto que hay entre comillas Entrada de datos • Leer un dato por el teclado, y guardarlo en la variable que se le pasa por parámetro int variable; scanf("%d",&variable); • IMPORTANTE! – La variable que se le pasa por parámetro lleva el símbolo & en el scanf, pero no en el printf.
– Con %d le decimos que ha de leer un entero (ver tablas sobre los tipos de datos en transparencias anteriores) – Para usar las funciones de entrada y salida básica, hay que incluir la biblioteca “stdio” al inicio de nuestro programa mediante la siguiente instrucción: #include <stdio.h> Funciones y Bibliotecas • Una función es un trozo de código que se escribe fuera de la función principal (main), con el objetivo de reutilizarse desde diferentes puntos del programa – printf y scanf son funciones • Una biblioteca es un archivo o conjunto de archivos que guardan grupos de funciones, que suelen tener una funcionalidad relacionada – Bibliotecas del sistema • Alguien las ha escrito y vienen con el compilador para que aprovechemos su trabajo; se tienen que definir al inicio de nuestro código mediante #include<nombre.h> • Ej: printf y scanf requieren un #include <stdio.h> – Bibliotecas de usuario • las escribimos nosotros en un archivo a parte (con extensión *.h) se definen al inicio del código mediante #include "nombre.h" Ejemplo: calcular la longitud de una circunferencia #include<stdio.h> #define PI 3.1416 void main() { float radio, longitud; printf(“Introduce el radio: “); scanf(“%f”, &radio); longitud = 2 * PI * radio; printf(“La longitud es %f”, longitud); } Comentarios dentro del código • Para ayudar a hacer el código legible, C permite insertar comentarios en él • El compilador los ignorará pero, nos sirven a nosotros como programadores • Los comentarios que ocupen varias líneas se deberán escribir entre los símbolos /* y */ • Los comentarios de una sola línea se pueden escribir después de los símbolos // Tema 2: Flujo del programa. Sentencias para controlarlo Flujo básico del programa • En el tema anterior, decíamos que las sentencias de un programa se ejecutaban en el mismo orden en que están escritas.
• Podemos realizar operaciones complejas mediante múltiples sentencias que consultan y modifican el estado del programa.
– Estado del programa: valor de sus variables en un momento dado.
• Dichas sentencias también realizan algunas operaciones de entrada/salida de datos (printf, scanf)Flujo básico del programa.
Ejemplo: int a = 3, b, c; b = a * 2; c = b + a; b = 7; a++; Controlando el flujo del programa • Generalmente, un programa escrito como una simple secuencia de pasos no nos permite hacer algunas tareas – Tareas complejas no se pueden expresar como un flujo secuencial de operaciones.
• Sentencias de control de flujo: – Condicionales: permiten que una sentencia o un grupo de sentencias se ejecuten solo si se da una condición.
– Iterativas: permiten que una misma sentencia o grupo de sentencias se ejecuten repetidas veces.
Condiciones • Una condición es una expresión: – Puede usar variables, constantes, y llamadas a funciones como operandos.
– Puede usar operadores aritméticos(+, ‐, *,/) – Puede agrupar expresiones dentro de paréntesis. Ej:(a+7)*b – Suele usar operadores relacionales(de comparación) • Mayor: La condición (a>b) es cierta si a tiene un valor mayor que b • Menor: La condición (a<b) es cierta si a tiene un valor menor que b • Mayor o igual: la condición (a>=b) es cierta si a tiene un valor mayor o igual que b • Menor o igual: La condición (a<=b) es cierta si a tiene un valor menor o igual que b • Igual: La condición (a==b) es cierta si a tiene el mismo valor que b • Diferente: La condición (a!=b) es cierta si a y b tienen diferente valor – También • Una expresión aritmética cuyo valor es 0 es una expresión falsa • Una expresión aritmética cuyo valor es ≠0 es una expresión cierta Condiciones: OJO! • No confundir el operador = con el operador == – El operador = asigna a la variable de su izquierda el valor de la variable, constante o expresión que hay a la derecha.
a = 0; // asigna a 'a' el valor 0 b = a; // asigna a 'b' el valor que en ese momento tenga 'a' c = a + b; //suma los valores de 'a' y 'b' y lo asigna a 'c' – El operador == indica que una condición es cierta si el valor de su izquierda es el mismo que el valor de su derecha.
1 == 1 es una condición cierta 1 == 0 es una condición falsa a + b == 7 será cierta si la suma de los valores de 'a' y 'b' es 7 en el momento en que se compruebe • Los operadores => y =< no existen. (elsímbolo = siempre alfinal) Operadores lógicos • Combinan varias condiciones simples en una condición más compleja – Operador AND (&&): Cond1 && Cond2 es cierto si Cond1 es cierto y Cond2 es cierto – Operador OR (||): Cond1 || Cond2 es cierto si Cond1 escierta, o si Cond2 es cierta, o si ambas son ciertas – Operador NOT (!): Cond1 es cierto si Cond1 es falso Sentencias de control de flujo • Sentencias Condicionales (ejecutan sentencias solo si se da una condición) – if – if‐else • Sentencias iterativas (ejecutan un mismo grupo de sentencias repetidas veces) – while – for La sentencia 'if' (condicional) • Ejecuta un conjunto de sentencias solo si una condición es cierta.
if( <condición> ) { /* Sentencia o conjunto de sentencias que se ejecutarán si la condición es verdadera */ } Ejemplo 'if' #include<stdio.h> void main() { int edad; printf("Dime tu edad: "); scanf("%d",&edad); if(edad >= 18) { printf("Eres mayor de edad\n"); } } La sentencia "if‐else" • Opcionalmente, podemos añadir a 'if' una parte 'else' que ejecutará otro conjunto de instrucciones cuando la condición sea falsa if( <condición> ) { /* Sentencia o conjunto de sentencias que se ejecutarán si la condición es verdadera */ } else { /* Sentencia o conjunto de sentencias que se ejecutarán si no es verdadera la condición (es falsa)*/ } Ejemplo 'if‐else' #include<stdio.h> void main() { int edad; printf("Dime tu edad: "); scanf("%d",&edad); if(edad >= 18) { printf("Eres mayor de edad\n"); } else { printf("Eres menor de edad\n"); } } Tema 3: Tipos de datos estructurados Tipos de datos elementales: char, short, int, long, float, double...
Datos estructurados: No existen fuera del dominio de nuestro programa,nos permiten representar conceptos asociados al problema concreto que queremos resolver.Se forman a partir de tipos de datos elementales (char, int, float, etc...) y a partir de otros tipos de datos estructurado • Dos tipos – Estructuras – Vectores Estructuras Los structs(estructuras) permiten crear nuevos tipos de datos que agregan varios dato s de otros tipos.
Ejemplo: podríamos crear un nuevo tipo de datos llamado "Asignatura" que incluyera l os siguientes elementos – Código de la asignatura: un número entero – Número de créditos: un número con decimales – Cuatrimestre: un número entero typedef struct { int codigo; float numCreditos; int cuatrimestre; } TAsignatura; // Por convenio, el nombre del tipo estructurado empezará por T Declaración de una variable – Se define fuera de la función "main()" Una variable de un tipo estructurado se define como cualquier otra variable, pero indicando el nuevo tipo definido El nuevo tipo de datos se define fuera de la función principal. Suele ir junto con las definiciones de librerías y constantes.
Las variables de ese nuevo tipo de datos van dentro de la función principal, junto con las otras variables de tipos simples y vectores.
#include<stdio.h> #define CONSTANTE 1234.5f typedef struct { int numero; char letra; } TDNI; void main() { Acceder a elementos de un struct Se accede mediante el nombre de la variable seguida de un punto y el nombre del elemento. Cada elemento se usa como cualquier otra variable.
• Ejemplo: typedef struct { short dia; short mes; short anyo; } TFecha; void main() { TFecha navidad; navidad.dia = 25; navidad.mes = 12; navidad.anyo = 2012; } Ojo!! Error común • No se debe confundir eltipo de dato con una variable typedef struct { short dia; short mes; short anyo; } TFecha; void main() { TFecha.dia = 25; TFecha.mes = 12; TFecha.anyo = 2012; } Operaciones con structs • OJO! Si bien el compilador sabe operar con tipos elementales, él no sabe cómo operar con structs Asignando constantes a structs Cuando queramos asignar un valor constante a una variable de tipo struct, no podemos asignar lo que a los humanos nos parecería obvio • Ejemplo: TFecha navidad = 25/5/2012; TComplejo c = 5 + 7i; • Dos maneras correctas -Cuando se inicializa la variable (en el mismo orden en que han sido definidos en el typedef struct...) TFecha navidad = {25,12,2012}; - Elemento a elemento (durante la ejecución del programa) c.real = 5; c.imaginario = 7; Copiar structs • Los valores de dos structs pueden copiarse directamente con el operador = TComplejo a = {2,3}; TComplejo b; b = a; // correcto •Pero no pueden usarse el resto de los operadores, ni siquiera los de comparación == o != – Ejemplo correcto para comparar dos complejos a y b: if(a.real == b.real && a.imaginario == b.imaginario){ printf("Son iguales"); } else { printf("Son diferentes"); } Vectores • Un vector es una estructura de datos que agrupa un número fijo (N) de elementos, todos del mismo tipo: – Tipos de datos elementales – Estructuras •Podemos acceder a cada uno de esos elementos mediante un índice: un número entre 0 y N‐1 que indica en qué posición está dentro del vector.
Podremos leer o modificar el valor de cada elemento por separado, mediante el nombre del vector más el índice de dicho elemento.
• Se diferencian de las estructuras en: – En los vectores, todos los elementos son del mismo tipo ‐‐> En structs pueden ser de varios tipos, ya sean elementales o estructurados – En los vectores, cada elemento se accede mediante un índice > En structs, los elementos no tienen un índice sino un nombre que nosotros le daremos.
Vectores en C • Definición de un vector <tipo> <nombre>[<tamaño>]; –Lo definimos en el mismo lugar del código donde definimos las otras variables.
–Ejemplos: float peso[31]; //vector de 31 reales int v[10]; //Define un vector de 10 enteros short v2[1000]; //vector de 1000 'shorts' Modificar elemento de un vector <nombre>[<índice>] = <expresión>; • Ejemplos: peso[30] = 74.5; v[0] = 12; v[1] = a * b * (34+c) peso[hoy] = 77; • El índice puede ser una expresión cualquiera.
• OJO!! – El primer elemento de un vector tiene índice 0.
– Para un vector de tamaño N, el índice del último elemento es N‐1.
Leer un elemento de un vector • La forma <nombre>[<índice>] se puede incluir dentro de expresiones.
• Ejemplos: a = v[0]; //asigna a la variable 'a' el valor de v[0] b = a+v[1]*v2[a+1]; /*hace operaciones con elementos de vectores */ printf("%f", peso[0]); /* usa un elemento como parámetro de printf para mostrar su valor por pantalla*/ Inicializar valores de vectores • Cuando definimos un vector (como cualquier variable), el valor inicial de sus elementos es indeterminado.Si el vector es pequeño, podemos inicializar sus valores directamente: int v[5] = { 1, 2, 4, 8, 16 }; Si el vector es grande, deberemos inicializar sus valores de otra manera menos "manual": int i, v[1000]; for(i = 0 ; i < 1000 ; i++) { v[i] = 0; /* en vez de 0, podría ser otro valor o expresión */ } 1 2 4 8 16 Vectores: OJO!! • No confundamos vectores en C con su definición matemática – Matemáticas (vector de N elementos) • Los índices de sus elementos van de 1 a N • Hay operaciones definidas (suma, resta, producto escalar, producto vectorial...) • Conceptualmente, no tiene sentido acceder al elemento 0 o al elemento N+1 del vector – Lenguaje C (vector de N elementos) • Los índices de sus elementos van de 0 a N‐1 •No hay operaciones definidas (no podemos operar con vectores directamente, tendr emos que hacerlo elemento a elemento) •Aunque tampoco tiene sentido, si accedemos a una posición negativa, o más grande que el tamaño del vector, el compilador no nos devolverá error Operaciones con vectores • Ejemplo de operaciones con vectores: sumar vectores a y b, y guardar el resultado en c.
int a[5] = { 2, 3, 4, 2, -1 }; int b[5] = { 12, 32, 3, -5, 4 }; int c[5], i; // C no nos deja hacer c = a+b, así que lo haremos elemento a elemento for(i = 0 ; i < 5 ; i++) { c[i] = a[i] + b[i]; } •Tampoco podemos asignar el valor de un vector a otro, al estilo a = b, ni compararlos con a==b El vector de 'char' • En C, un 'char' puede guardar un solo carácter alfanumérico (números, letras, símbolos...) • Para guardar cadenas de texto, se utilizan vectores de char char mensaje[] = "Hola"; –Observación: El anterior vector no tiene 4 elementos, sino 5 •En cadenas de texto, se añade al final un carácter especial '\0' para indicar el fin de la cadena Cadenas de caracteres:OJO!!! • No es lo mismo 'H' que "H" – 'H' (comillas simples) es una constante del tipo char – "H" (comillas dobles) es una cadena con un solo caràcter (más el 0 de final de cadena) • En la declaración char mensaje[] = "mensaje"; no es lo mismo mensaje que "mensaje" – mensaje es el nombre de una variable del tipo vector de char – "mensaje" representa los datos en memoria que guardan un texto.
• No es lo mismo 2 que '2' que "2" – 2 es un número – '2' es un carácter. Su valor numérico es 50 (según ASCII) – "2" es una cadena de caracteres (de un solo carácter) Combinando tipos de datos estructurados • Un struct puede contener un vector: typedef struct { int edad; char nombre[100]; } TPersona; main() { TPersona p = { 19, "Jose Luis"}; char primeraLetra, segundaLetra; primeraLetra = p.nombre[0]; segundaLetra = p.nombre[1] } • Podemos hacer un vector de structs: typedef struct { int numero; char letra; } TDNI; main() { TDNI vectorDni[10]; vectorDni[0].numero = 123445343; vectorDni[0].letra = 'F'; vectorDni[1].numero = 342342342; vectorDni[1].letra = 'Z'; • Un struct puede estar formado por otros structs typedef struct { int numero; char letra; } TDNI; typedef struct { int dia, mes, anyo; } TFecha; typedef struct { char nombre[100]; TDNI dni; TFecha nacimiento; } TAlumno; main() { TAlumno al = { "Jose", {1234344,'F'},{15,5,1994} }; printf("El alumno nació en el año %d\n", al.nacimiento.anyo); } ...