Está en la página 1de 16

UNIDAD FORMATIVA 1: PROGRAMACIÓN ESTRUCTURADA

1. INTRODUCCIÓN A LA PROGRAMACIÓN .

Programa, conjunto de instrucciones dadas al ordenador en un lenguaje que solo es entendible por él.
Algoritmo, secuencia finita de operaciones que resuelven un problema expuesto. Es una forma de resolver un problema.

CARACTERÍSTICAS DE UN PROGRAMA Un programa debe ser:


Finito (formado por un conjunto limitado de líneas) | Legible | Modificable | Eficiente | Modulable | Estructurado

HERRAMIENTAS PARA REPRESENTAR LOS ALGORITMOS:


- Pseudocódigo: manera de representar distintas sentencias con un
lenguaje cercano al natural (lenguaje que no se puede ejecutar en una
máquina).
CARACTERÍSTICAS DEL PSEUDOCÓDIGO:
​ Comienza con la palabra Algoritmo más su nombre.
​ Le sigue una secuencia de instrucciones.
​ Finaliza con la palabra FinAlgoritmo.
​ No es necesaria la indentación (se recomienda).
​ No diferencia entre mayúsculas y minúsculas.

- Diagrama de flujo: usados para la representación gráfica de las sentencias.


Cada paso del proceso se representa con un símbolo standard (ver cuadro)
CARACTERÍSTICAS DE UN DIAGRAMA DE FLUJO:
​ Deben escribir de arriba abajo o de izquierda a derecha.
​ Evitar el cruce de líneas.
​ Las líneas de flujo deben estar conectadas a algún objeto.
​ El texto escrito debe ser escueto o legible.
​ Todos los símbolos de decisión deben tener más de una línea de salida.

El PROCESO DE PROGRAMACIÓN COMUNICA a un USUARIO CON UNA MÁQUINA, y aparecen varios tipos de lenguajes:
- Alto nivel, están más cerca del lenguaje que habla el usuario.
- Bajo nivel, están más cerca de las estructuras de lenguaje de la máquina.
- Medio nivel, toman características de los dos anteriores.
* Nosotros usaremos lenguaje de Alto nivel, necesitamos un proceso de traducción para convertir el programa
escrito en lenguaje máquina.
CARACTERÍSTICAS DEL LENGUAJE DE ALTO NIVEL:
​ Independiente de la máquina y portable.
​ Muy utilizado en el mundo laboral.
​ Modificaciones y actualizaciones fáciles de realizar.
​ Para la traducción de código necesitamos un compilador y un enlazador con librerías del lenguaje elegido.

LENGUAJES COMPILADOS E INTERPRETADOS


El lenguaje compilado es aquel de alto nivel que utiliza un compilador para traducir al lenguaje
máquina (el de una máquina ficticia llamada máquina virtual).
Un lenguaje interpretado, no genera un programa escrito en una máquina virtual, sino que efectúa
directamente la traducción y ejecución simultáneamente para cada uno de las sentencias.
2. ESTRUCTURA DE UN PROGRAMA INFORMÁTICO .

PROGRAMACIÓN ESTRUCTURADA
En una programación estructurada, las instrucciones deben ejecutarse una detrás de otra, dependiendo de una serie de condiciones que pueden cumplir
o no. En C# podemos tener una aplicación formada por uno o varios ficheros con su código fuente correspondiente, pero solo uno de ellos va a ser el
principal cuya extensión es .cs

BLOQUES DE UN PROGRAMA INFORMÁTICO


PROGRAMA → secuencia de instrucciones separadas por punto y coma que se van a ir agrupando en diferentes bloques mediante llaves.

CLASE → estructura de datos que está compuesta por atributos o variables y métodos o funciones.
* La clase Program es la estructura que Visual Studio nos crea por defecto y el método Main es el método principal. En C# el método Main se puede
declarar con o sin un parámetro string, que contiene los argumentos de línea de comandos.
* Para comentar: una línea → ponemos // al comienzo de la línea | varias líneas → ponemos /* al inicio y */ al final.

ENTRADA Y SALIDA POR PANTALLA → usaremos la clase Console.


Write() → escribe el valor o valores especificados (sin hacer salto de línea)
WriteLine() → escribe el valor o valores especificados (con salto de línea)
ReadLine() → lee el dato introducido por el usuario y devuelve un tipo de dato string
Read() → lee el dato introducido por el usuario y devuelve un tipo de dato int
ReadKey() → lee el carácter presionado por el usuario y se muestra esa tecla por pantalla.
VARIABLES. USO Y TIPOS
Variable → estructura de datos que ocupan un espacio en la memoria y cuyo valor podrá cambiar a lo largo del programa.
DECLARAR O DEFINIR UNA VARIABLE
Declarar una variable es crear/construir la variable → primero establecemos el tipo de dato y después el nombre de la variable. Ej: int edad;
Iniciar una variable es asignar un valor, especificar qué valor almacena. Ej: int edad=29; EN C# NO SE PUEDE USAR UNA VARIABLE QUE NO SE HA INICIADO.
*Convenciones “Buenas prácticas”: - usar letras de A a Z (mayúsculas o minúsculas), números del 0 al 9 y “_” (excepto en el primer carácter del nombre)
- no usar palabras reservadas como nombres de variables. 
- No crear más de una variable que se diferencien por una letra.
- Comenzar el nombre con letra minúscula → camelCase
TIPOS DE VARIABLES
Al definir una variable es importante saber cuánto espacio va a ocupar e
intentar seleccionar el tipo de variable más adecuada.
Las variables tienen como ámbito de trabajo el bloque donde se han definido.
Podemos encontrar dos tipos de variables:
​ Locales → las declaradas dentro de un método o función y solo son
visibles dentro de ese bloque.
​ Global → las declaradas fuera de un método o función y se puede
acceder a ella. ¡¡¡No debemos usar variables globales!!!!
* Las variables locales tienen prioridad sobre las globales si aparecen en el mismo ámbito.

CONSTANTES. TIPOS Y UTILIDADES


Constante → espacio en la memoria del ordenador donde se almacenará un valor que no podrá cambiar durante la ejecución del programa.
Se definen fuera de cualquier función, normalmente al principio del programa.
Sintaxis: const<tipo><nombre_variable>;
const double PI=3,1416;
OPERADORES DEL LENGUAJE DE PROGRAMACIÓN TIPOS DE DATOS: SIMPLES Y COMPUESTOS

TIPOS DE DATOS:
- Simples
Tipos simples predefinidos o primitivos → son indivisibles, tienen existencia propia y permiten operadores relacionales.
NATURAL: NÚMEROS NATURALES (N) sin signo → byte, uint, ushot, ulong.
ENTERO: NÚMEROS ENTEROS (Z) con signo. → sbyte, int, long, short.
REAL, NÚMEROS REALES (R) → decimal, float, double.
LÓGICO, BOOLEANOS (B) → bool (TRUE/FALSE)
CARÁCTER,CARACTERES (C) → char (UTF-16)
Tipos simples definidos por el usuario
TIPOS ENUMERADOS(enum) → Tipo de valor definido por el usuario y
un conjunto de constantes. ofrecen la posibilidad de definir nuevos tipos
simples. Un tipo enumerado se declara utilizando la palabra clave enum.
Las enumeraciones de C # son tipos de datos de valor, es decir, contiene
sus propios valores y no puede heredar o no puede heredar. Ej →
Declarando enum:
La sintaxis general es: enum <enum_name> {enumeration list};
* enum_name especifica el nombre del tipo de enumeración.
* enumeration list es una lista de identificadores separados por comas.

- Compuestos o Estructurados → Se crean mediante la unión de varios tipos (simples o compuestos).


Vectores o Arrays unidimensionales → estructuras de datos donde almacenamos varias variables del mismo tipo.
Un array tiene índices o posiciones y se inician en 0 : int[] vector1 = {1,2,3} → posición 0=1, 1=2 y 2=3.
SINTAXIS DE UN ARRAY: <tipo> [ ] <nombre> = new <tipo> [<tamaño>];
DECLARACIÓN : int [] nombre_array; | INICIACIÓN : nombre_array = new int [4]; (hay 4 valores guardados en el array)

DECLARACIÓN E INICIACIÓN en la misma línea: int[]nombre_array=new int[4];


TIPOS DE ARRAY:
- Array Implícito, almacena datos pero no especificamos el tipo ni cuántos elementos tendrá.
Ej: var datos=new[]{“Juan”,”Díaz”}; en este será de tipo string
var valores=new[]{15, 28, 75.5,30.30}; aquí será tipo double
- Array de objetos
-Array de tipos o clases anónimas, Ej: var personas=new[] {
new{Nombre=”Juan”, Edad=19}
new{Nombre=”María”, Edad=49}
new{Nombre=”Diana”, Edad=35} };
Matrices o Arrays bidimensionales→ unión de varios vectores de cualquier tipo simple (enteros, reales, etc). Necesitamos dos
indicadores de posición para acceder al elemento, La primera posición es (0,0)
SINTAXIS DE UNA MATRIZ: Tipo[ , ] Nombre = new Tipo [filas, columnas]; Ej: int[ , ] matriz= new bool [2,3] → 2 filas y 3 columnas
CONVERSIONES DE TIPOS DE CLASE
- CONVERSIÓN IMPLÍCITA→ para las que no hace falta indicar entre paréntesis la conversión. Conversiones en C# de forma segura.
Son conversiones de tipos integrales más pequeños a más grandes y conversiones de clases derivadas a clases base.
Ej: 1- var b=2; (C# decide el tipo)
2- var n; (C# no permite esto sin asignar valor)
3- double resultado; | int numero1 = 3, numero2 = 9; | resultado = numero1; | numero2 = (int)resultado;

- CONVERSIÓN EXPLÍCITA → se realizan explícitamente por los usuarios que utilizan las funciones predefinidas. Se debe colocar entre paréntesis
el tipo de dato al que queremos convertirlo, y así indicamos al compilador que queremos convertir un tipo de dato a otro diferente. Las conversiones
explícitas requieren un operador de conversión. Se utilizan cuando es posible la perdida de información.
TRUNCANDO DECIMALES Ej: double a = 10,5; | int b; | b=(int)a;
SIN TRUNCAR DECIMALES Ej: int a = 11; | double suma= (double) a/10
PARSE permite convertir caracteres numéricos de tipo string a datos numéricos de tipo int, double,... Ej: int b; | b= int.Parse
CONVERT también puede realizar la conversión de un tipo de dato a otro. Ej: int b; | b=convert.int32
* DIFERENCIA PARSE Y CONVERT - Al recibir un valor null o entrada nula Convert no genera errores de conversión, devuelve un 0 y Parse sí genera un error.
- Si la entrada es una cadena vacía en ambos se genera un error de conversión.
La única diferencia de significado entre las conversiones explícitas e implícitas, tiene que ver con el hecho de si existe riesgo o no de perder en información.

3. PROGRAMACIÓN ESTRUCTURADA .

Es la manera que tenemos de escribir o diseñar un programa de una forma clara y sencilla. Edsger Dykstra comprobó que todo
programa se puede escribir utilizando únicamente tres tipos de instrucciones de control (años setenta).
SECUENCIA DE INSTRUCCIONES | SELECCIÓN DE INSTRUCCIONES O INSTRUCCIÓN CONDICIONAL | ITERACIÓN O BUCLE DE INSTRUCCIONES

FUNDAMENTOS DE PROGRAMACIÓN
Programar → decirle a una máquina qué debe realizar en el menor tiempo posible. El programa se
encarga de transformar la entrada en salida. Es conveniente: especificar la estructura y el
comportamiento de un determinado programa, probar que realiza la tarea que le ha sido asignada de
forma correcta y que ofrece un buen rendimiento.
Algoritmo → la secuencia de los pasos y las distintas operaciones que debe realizar el programa para conseguir resolver un problema.
Algoritmia → conjunto ordenado y finito de operaciones que permite encontrar la solución a un problema cualquiera.
La programación → es una etapa en todo el proceso de desarrollo que existe a la hora de resolver un problema.

CICLO DE VIDA DE UN PROGRAMA INFORMÁTICO


Análisis de requisitos → a partir de las necesidades del usuario o del problema, el objetivo es
eliminar ambigüedades. Se fijan objetivos y requisitos (entrevistas, brainstorms)
Diseño de la arquitectura → se estudian los distintos componentes que van a formar parte del
programa y se genera un diseño (diagramas de clases, de interacción, pseudocódigo)
→ Diseño estructurado o Diseño orientado a objetos
Etapa de implementación o codificación → codificamos las aplicaciones elegidas en el
diseño, empleando el lenguaje de programación. → Obtenemos el código fuente.
Pruebas de integración → realizar ensayos del funcionamiento, combinando todos los
módulos de la aplicación. Haciendo funcionar la aplicación comprobamos que cumple lo establecido.
Pruebas de validación → realizar nuevas pruebas de la aplicación en su conjunto para
cerciorarnos de que se cumple lo establecido en los requisitos.
Fase de mantenimiento, revisar todo el proceso anterior e ir actualizando o modificando los
cambios oportunos en las etapas anteriores.
PRUEBAS DE PROGRAMAS
Una vez compilado el código, comienza la etapa de testing, plan de prueba o prueba de programa.
Se prueba un programa para demostrar la existencia de defectos (algorítmico, sintaxis, sobrecarga, capacidad, sincronización…)
Proceso llevado a cabo de manera automática o manual.
Objetivos: - Comprobar los requisitos funcionales y no funcionales del programa.
- Probar todo tipo de casos para detectar alguna anomalía en su ejecución.
Si hay algún fallo, debemos volver a empezar con el nuevo código modificado.
Tipos de técnicas de pruebas:
- Pruebas de caja blanca o white-box testing (o clear-box, glass-box, transparent-box, and structural testing):
se valida el código y la estructura del sistema.
- Pruebas de caja negra o black-box testing:
se analizan las entradas y salidas del sistema, sin tener en cuenta el funcionamiento interno.

ESTRUCTURAS DE SELECCIÓN (instrucciones condicionales)


Las estructuras de selección son aquellas que permiten ejecutar una parte del código dependiendo de si cumple o no una determinada condición. Los
distintos operadores que se pueden utilizar son los Operadores de comparación y los operadores lógicos.

- CONDICIONAL IF (SI) Sintaxis: if (expresión_booleana){


bloque de código
}
Si la expresión booleana se evalúa como verdadera, se ejecuta el bloque de código
dentro de la instrucción. Si es falsa, se ejecuta el primer conjunto de código después
del final de la instrucción.

CONDICIONAL IF-ELSE
Una instrucción if puede ser seguida por una instrucción else opcional, que se ejecuta
cuando la expresión booleana es falsa. Sintaxis:
if(expresión_booleana){
bloque de código
} else{
bloque de código
}
Si la expresión booleana se evalúa como verdadera, el bloque if ejecuta el código, de lo
contrario el bloque else ejecuta el código.

CONDICIONAL IF> ELSE IF >ELSE


if (expresión_booleana){
bloque de código 1
} else if (expresión_booleana){
bloque de código 2
} else (expresión_booleana){
Bloque de código 3
}
La primera expresión se evalúa, si es true ejecuta el primer bloque, Si la expresión es false se
evalúa la segunda expresión, si es true se ejecuta ese bloque de sentencia 2, si es false se
ejecuta el bloque 3.

CONDICIONAL IF ANIDADO
Siempre se puede anidar declaraciones if-else, lo que significa que se puede usar una declaración if o else if dentro de otra declaración if o
else if.
- SENTENCIA SWITCH
Es una instrucción de selección múltiple que elige una sola acción de una lista de opciones en función de una coincidencia de distintos
patrones con la expresión de coincidencia. Sintaxis:
switch (expresión de control){
case expresión constante:
código a realizar
break;
case expresión constante:
código a realizar
break;
. . .
default:
código a realizar
break;
- Solo se usa switch para evaluar: int, char, string, float y double (estos han de usar la
condición if)
- Los case solo pueden contener expresiones contantes (que han de ser únicas) y todo
case debe llevar su break;

ESTRUCTURAS DE REPETICIÓN (iteración o bucle de instrucciones)


Las estructuras de repetición siempre se ejecutan mediante el uso de bucles.

- WHILE (Mientras), mientras se cumpla una condición, el


código incluido dentro del bucle se repite. La condición se evalúa al
principio, por lo que puede que no llegue a ejecutarse nunca. Cuando la
condición se vuelve falsa, el control del programa pasa a la línea que
sigue inmediatamente al bucle. Sintaxis:
while (condición) {
código
}

- DO…WHILE (Hacer…Mientras), mientras que se cumpla una condición, el código incluido dentro del
bucle se repite. La condición se evalúa al final, por lo que, como mínimo se va a ejecutar una vez. Sintaxis:
do {
código
} while (condición){
código
}

- FOR (para), estructura de control de repetición que permite escribir un bucle que necesita ejecutarse un número específico de veces.
Sintaxis: for ( int i=0; i<=8 ; i++ ){
código de repetición
}
En el ej. mientras i (que es igual a 0) sea menor o igual a 8 se repetirá la ejecución del código, y por cada ejecución i aumentará su valor en 1.

- FOREACH (por cada uno..), utilizamos un bucle for para acceder a cada elemento de
la matriz. También se puede usar una instrucción foreach para recorrer en iteración una matriz.
Se utiliza para arrays implícitos, arrays de objetos y arrays de tipos o anónimos. Sintaxis:
foreach (int j in nombre_array){
código de repetición
}
En el ej. j es el iterador o variable para recorrer el bucle foreach, in palabra clave del bucle foreach y nombre_array es el nombre del array.
ESTRUCTURAS DE SALTO
Son todas aquellas que detienen (de diferentes formas en bucles, ciclos y condicional) la ejecución de alguna de las
sentencias del programa.
BREAK:
o Cuando el break se encuentra dentro de un bucle, el bucle finaliza inmediatamente y el control
del programa se reanuda en la siguiente instrucción que sigue al bucle.
o Se usa para terminar un case en la instrucción switch.
o En bucles anidados, la instrucción break detendrá la ejecución del bucle más interno y
comenzará a ejecutar la siguiente línea de código después del bloque.

CONTINUE:
​ En lugar de forzar la terminación, continue obliga a que tenga lugar la siguiente iteración del bucle,
​ omitiendo cualquier código intermedio.

RETURN:
​ Con return termina la ejecución del método en el que aparece y devuelve el
​ control al método de llamada.

TRATAMIENTO DE CADENAS
Una cadena es un objeto de tipo string y para la representación de cadenas de caracteres se utiliza el tipo de datos string.
El operador new → la palabra new crea un objeto tipo string al que pasamos el parámetro “letras” como una tabla de caracteres.
PRINCIPALES MÉTODOS DE STRING:
​ Length => Obtiene el número de carácter del string → devuelve el tamaño del string contando los espacios en blanco.
Ej: string variable=”Hola”; | Console.Writeline(variable.Length); | Salida=4
​ ToCharArray() => Convierte un string en array de caracteres.
​ SubString() => Recupera una subcadena de la instancia, es decir, extrae parte de una cadena. Este método puede ser sobrecargado
indicando su inicio o su inicio y su fin; .SubString (posInicio) o .SubString(posInicio, tamañoSubcadena)
Ej: string variable=”Hola, como estáis”; | Console.WriteLine(variable.SubString(0,4)); | Salida= Hola

​ CopyTo() => Copia un número de caracteres especificados a una determinada posición del string.
​ CompareTo() => Compara la cadena con otra pasada por parámetro, Devuelve un entero.
Valor Condición
Menor que cero Si el objeto que se esta comparando es menor devolverá -1
Cero Si los dos objetos son iguales devuelve 0.
Mayor que cero Si el objeto que se esta comparando es mayor devolverá 1.
​ Contains() => Comprueba si la cadena que se le pasa por parámetro forma parte del string . Devuelve un booleano TRUE o FALSE.
Ej: string variable=“Hola que tal estáis”; | Console.WriteLine(variable.Contains(“tal”) | Salida= TRUE
​ IndexOf() => Si aparece un carácter especificado en el string, devuelve el índice de la posición de la primera vez que aparece o -1 si
no está en la cadena. Ej: string names=”Robert, Marks, Mary”; | Console.Write(names.IndexOf(M)); | Salida=8
​ Insert() => Inserta una cadena de caracteres en una posición concreta del string.
Ej: string a= “David”; | Console.WriteLine(a.Insert(5,”s”)); | Salida=Davids
​ Trim() => Quita todos los espacios en blanco del principio y el final del string.
Ej: string variable=”Hola David”; | Console.WriteLine (variable.Trim()); | Salida=HolaDavid
​ Replace()=> Sustituye un string o carácter por otro. Ej: string a=“Paco”; | Console.WriteLine(a.Replace(“P”,”T”); | Salida= Taco
​ Remove() => Elimina un número de caracteres especificado. Ej: string a= “Hola!!” | Console.Write(a.Remove(5)); | Salida = Hola!
​ Split() => Separa en varias partes una cadena de caracteres.
Este método devuelve un array de string.
​ ToLower() => Devuelve la copia del string que hace la llamada en minúsculas.
​ ToUpper() => Devuelve la copia del string que hace la llamada en mayúsculas.
Ej: string a = “david”; | Console.WriteLine(a.ToUpper()); | Salida = DAVID
string b = “DAVID”; | Console.WriteLine(b.ToLower()); | Salida = David
DEPURACIÓN DE ERRORES
Llegados a la etapa de depuración de nuestro programa, nuestro objetivo será descubrir todos los errores que existan e intentar
solucionarlos de la mejor forma posible. Podemos encontrar tres tipos de errores diferentes:
• De compilación o sintaxis → errores en el código.
• De tiempo de ejecución: → los que producen un fallo a la hora de ejecutar el programa. Se trata de fragmentos de código que
parecen estar correctos, que no tienen ningún error de sintaxis, pero que no se ejecutan.
• Lógicos → aquellos que aparecen cuando la aplicación está en uso. Se dan resultados erróneos, diferentes a los esperados, a menudo en
respuesta a las acciones del usuario. Son los más difíciles de corregir, ya que no siempre está claro dónde se originan.
TECLAS PARA DEPURAR ERRORES EN Visual Studio:
- F5 → inicia la depuración recorriendo el código completo si no encuentra ningún error.
- F9 → pone un punto de interrupción y ejecuta hasta ahí.
- F10 → paso a paso por procedimientos
- F11 → paso a paso por instrucciones
- Podemos poner un punto de interrupción en una determinada línea de código y pulsar F5→ se ejecutará el código en el
depurador de Visual Studio y se detendrá en el punto de interrupción.

DOCUMENTACIÓN DE PROGRAMAS
- Una vez que finaliza nuestro proceso de compilación y ejecución, debemos elaborar una memoria para que quede registrado todo el desarrollo que
hemos llevado a cabo, los fallos que ha presentado y cómo hemos conseguido solventarlos.
- La etiqueta <summary> se usa para describir un tipo y agregar información adicional .

dentro de nuestro código. <summary>description</summary>


- Podemos utilizar herramientas de documentación como GhostDoc y Sandcastle creen hipervínculos internos a las páginas de
documentación de los elementos de código.

ENTORNOS DE DESARROLLO DE PROGRAMAS


Entorno de desarrollo integrado (IDE o integrated development environment) → entorno de programación que hemos usado para realizar el programa:
editor de código, compilador, depurador e interfaz gráfica (GUI o graphical user interface).
Ejemplos de IDE son: Eclipse, Netbeans, Visual Code, Visual Studio,…
Los IDE son utilizados por distintos lenguajes de programación.
Los IDE deben cumplir con una serie de características para su correcto funcionamiento:
• Son multiplataforma.
• Actúan como soporte para diferentes lenguajes de programación.
• Reconocen sintaxis.
• Están integrados con sistemas de control de diferentes versiones.
• Tienen un depurador.
• Permiten importar y exportar proyectos.
• Manejan diferentes idiomas.
• Facilitan un manual de ayuda para el usuario.
Ventajas:
• Presentan una baja curva de aprendizaje.
• Son de uso óptimo para usuarios no expertos.
• Formatean el código.
• Usan funciones para renombrar funciones y variables.
• Permiten crear proyectos.
• Muestran en pantalla errores y warnings.
UNIDAD FORMATIVA 2: DISEÑO MODULAR
PROGRAMACIÓN MODULAR .

Programación modular → consiste en dividir el problema original en diversos subproblemas, que se pueden resolver por separado,
para después, recomponer los resultados y obtener la solución al problema.
Subproblema o módulo,→ una parte del problema que se puede resolver de manera independiente.
Ventajas: Inconvenientes:
- Facilita el mantenimiento, la modificación y la documentación. - Separación de módulos → ¿cuánto hay que dividir el problema?
- Facilita la escritura y el testing. - Aumenta el uso de memoria y el tiempo de ejecución.
- Reutilización de módulos. - No se dispone de algoritmos formales de modularidad
- Independencia de fallos. (a veces los programadores no tienen claras las ideas de los módulos →experiencia)

ANÁLISIS DESCENDENTE (TOP DOWN)


DISEÑO DESCENDENTE (top down design):
- Técnica que permite diseñar la solución de un problema con base en la modularización o segmentación,
dándole un enfoque de arriba hacia abajo, de lo general a lo específico.
- Se basa en el principio de “divide y vencerás”.
-Representación por niveles: nivel 1 resuelve el problema, el resto de niveles lo depuran.
- Tiene una estructura de árbol.

MODULACIÓN DE PROGRAMAS → SUBPROGRAMAS


Modularización → es el proceso de descomposición de un problema en módulos. Los módulos permiten que podamos centrarnos sólo en una de sus
partes y que podamos utilizar las soluciones obtenidas en otras partes del programa. Y estos módulos se diseñan con subprogramas o métodos (que
pueden ser procedimientos y funciones). OJO! → en C# función/procedimiento = método = subprograma

Procedimientos y funciones → son unidades de programas diseñados para ejecutar una tarea específica.
• Los procedimientos (subrutinas = métodos no tipados) no retornan valor,sólo realizan tareas específicas. Usan la palabra reservada void.
- Suelen utilizarse para reducir la duplicación de códigos en un programa. Pueden recibir parámetros.
- Su visibilidad viene determinada por la declaración private, public o internal, (por defecto un procedimiento en C# es public???)

• Las funciones (métodos tipados) devuelven un sólo valor al programa que invoca a la función. Usa la palabra reservada return.
* La FUNCIÓN o MÉTODO MAIN→ Un caso especial es la función Main (que es función pero usa la palabra void y no return). Todos los programas desarrollados en C# tienen una función principal
denominada main() es el punto de entrada, donde se crean objetos y se invocan a otros métodos. Ej: class NombreClase { static void Main(string[] args){...} }
- Se referencia o invoca utilizando su nombre en una expresión.
- Función→ conjunto de instrucciones (delimitadas por llaves) que tienen un nombre y son de un tipo específico.
- Puede recibir o no parámetros (si no necesita recibir parámetros se deja sin poner nada entre los paréntesis)
- Partes de la función:
● Modificadores de acceso: conjunto de palabras reservadas que modifican o aplican propiedades a la función.
o Public: el acceso no está restringido. ¡¡¡ Si no se indica, por defecto una función en C# es internal !!!
o Private: el acceso está limitado a la misma clase.
o Protected: el acceso está limitado a la clase contenedora o a los tipos derivados de la clase contenedora.
o Internal: el acceso no está restringido (dentro del mismo ensamblado o entorno actual).
● Tipo: las funciones también poseen un tipo → el tipo del dato que devuelven.
● Nombre de la función: el identificador de la función, se usa para referenciarla.
● Parámetros de entrada: las variables que recibe la función en el momento de su llamada.
o Parámetro real o actual → aquel que pasamos a la función.
o Parámetro formal → el que usamos dentro de la función (las variables que usamos dentro de la función).
● Return: es obligatorio que devuelva un parámetro del tipo adecuado usando la palabra return.
PASO DE PARÁMETROS .

Mediante el uso de parámetros, se permite la comunicación de las diferentes funciones con el código.
Paso de parámetros por valor o copia
Al ejecutar la función se crea una copia del parámetro pasado. Las
modificaciones se realizan sobre la copia y el original no se modifica, ni se altera su
valor en la función. (En el ej. la salida de numero sigue siendo 1)
(*Si queremos ver lo de dentro tenemos que hacer un Write desde dentro de la función)

- Para pasar por valor un array usamos la palabra params.

. Podemos pasarle un array ya iniciado o los elementos del array directamente.


Ej. int[] myIntArray = { 5, 6, 7, 8, 9 }; | UsoParamsInt(myIntArray);
o UsoParamsInt(1, 2, 3, 4);

. El tipo de dato del array debe ser el mismo que el de la función.


Ej. object[] myObjArray = { 2, 'b', "test", "again" }; → UsoParamsObj(myObjArray);
( no UsoParamsInt(myObjArray); )

Paso de parámetros por referencia

- Al indicar ref trabajamos con los originales y sobreescribimos el


valor del resultado sobre la variable original. Las modificaciones que se realizan en
la función afectan a los parámetros. (En el ej. la salida sería 6)
(* Podemos hacer el write dentro o fuera de la función para ver el resultado pues hemos cambiado el valor de las variables.)

- También podemos pasar por referencia usando las palabras in y out:

➢ Cuando usamos in las variables son readonly → deben inicializarse antes


de pasarlas en la llamada y no podrá modificarse dentro del método (aunque sí
operar con ellas).

➢ Cuando usamos out las variables no necesitan inicializarse antes de pasarlas


en la llamada y podrán modificarse dentro del método.

ÁMBITO EN LAS LLAMADAS A FUNCIONES .

Cuando hablamos del ámbito nos referimos a la visibilidad que tendrán las variables con respecto al programa que estamos creando.
- Variables globales: las creadas fuera del Main y de cualquier método. Podemos acceder a ellas desde cualquier parte del programa.
- Variables locales: las declaradas dentro de un método o función y que sólo son visibles en ese fragmento de código.
* En términos generales, NO USAR VARIABLES GLOBALES , USAR VARIABLES LOCALES para que cada parte del programa trabaje con sus propios datos, evitando que un error en un trozo de
programa pueda afectar al resto. PASAR LOS DATOS A TRAVÉS DE PARÁMETROS.

PRUEBA, DEPURACIÓN Y COMENTARIOS .

PROBAR: Una vez terminado el programa, debemos probarlo para comprobar que no tiene fallos y que su funcionamiento es el correcto.
COMENTAR: Es conveniente comentar lo importante que realiza el programa.
DEPURAR: (ver apartado Depuración de errores)
Cuando ejecutamos un programa, podemos dividir el proceso en:
• Compilación: Al escribir código, el entorno de desarrollo va haciendo comprobaciones y expone los errores de compilación subrayados.
Una vez corregidos esos errores, el programa se va a compilar y va a pasar a ejecutarse.
• Vinculación: Todos los programas usan bibliotecas y algunos usan clases diseñadas por el programador. Las clases se vinculan cuando el programa comienza a ejecutarse.
• Ejecución: Llegar a la fase de ejecución significa que nuestro programa ya no tiene errores, pero puede que el resultado no sea el esperado.
Los errores lógicos son los más complicados de detectar. Debemos depurar comprobando, paso a paso, cómo va funcionando hasta dar con el error.
LIBRERÍAS .

Librerías: conjunto de métodos relacionados con el mismo objetivo para poder ser reutilizados. Son archivos que nos permiten realizar tareas sin
necesidad de saber cómo están desarrolladas, sólo entender cómo utilizarlas. Además, nos permiten hacer programas más modulares y reutilizables, con
funcionalidades bastante complejas. Una biblioteca de clases define los tipos y los métodos que se llaman desde una aplicación.

- Al compilar nuestro programa, sólo se comprueba que se ha llamado de manera


correcta a las funciones que pertenecen a las diferentes librerías, pero el código de estas
funciones todavía no se ha insertado en el programa.
- El enlazador o linkador es el encargado de realizar la tarea de inserción y de
completar el código máquina para obtener el programa ejecutable.

El lenguaje C# permite la interoperación con otros lenguajes, siempre que estos tengan:
• Acceso a las diferentes librerías a través de COM+ y servicios .NET.
• Soporte XML (a nivel de documentación).
• Simplificación en administración y componentes gracias a un mecanismo muy cuidado de versiones.
Podemos CREAR NUESTRAS PROPIAS LIBRERÍAS en C# con VS 2019:
1. Creamos un proyecto nuevo como aplicación de consola. * DLL (Dynamic Link Library): librerías de enlace dinámico.
2. Agregamos a nuestra solución una biblioteca de clases (ir a la ventana del explorador de soluciones, botón derecho y agregar).
3. Creamos nuestra dll, realizando un módulo (ej: ‘Multiplicar’). Allí crearemos una función que realizará una tarea (ej: la multiplicación de dos números).
4. A mi proyecto, agregaremos como referencia (botón derecho -> referencia) mi dll con el nombre que habíamos puesto con anterioridad (‘Operaciones’).
5. Ahora ya podemos llamar desde nuestro programa a nuestra referencia.

USO DE LIBRERÍAS: ej: podemos usar la librería Random para generar números aleatorios y las librerías Math para operaciones matemáticas.
Random → generar números aleatorios con la clase Random: Math → operaciones matemáticas:
RECURSIVIDAD .

Recursividad: la llamada de una función a sí misma hasta que cumpla una determinada condición de salida. Reemplaza estructuras repetitivas.

Estructura:
• caso base = condición de salida → que permite la finalización del programa.
Si no hay el método recursivo terminará llamándose a sí mismo interminablemente
y provocará un desbordamiento en la memoria (“Stack Overflow”)
• Casos recursivos → que son los que se encargan de que la función vuelva a ejecutarse, pero acercándose cada vez más al caso base.

Tipos de recursividad:
• Directa: cuando la función hace la llamada a sí misma desde un punto específico de su código.
• Indirecta: cuando la función hace la llamada a otra función y es esta la que llama a la primera.

¿Para qué sirve?:


• Para resolver problemas y situaciones que surgen en programación de una forma elegante y eficiente.

Ejemplos: Cuenta atrás desde un número: | El factorial de un número:


UNIDAD FORMATIVA 3: GESTIÓN DE FICHEROS

Para que los datos persistan después de la ejecución de un programa podemos almacenarlos en un fichero. Cada vez que se ejecute la aplicación que
trabaja con esos datos, podrá leer del fichero los que necesite y manipularlos.
* La BCL (Base Class Library) reserva un espacio de nombres denominados System.IO, destinado a trabajar con ficheros.

FICHEROS .

FICHERO →parte de un dispositivo no volátil (los que no pierden la info al apagar el pc) a la que se le asigna un nombre y que puede
contener una cantidad de datos limitada (o por la cantidad de espacio del dispositivo o por las características del sistema operativo).
- Se almacenan en directorios o carpetas y cada directorio puede contener otros directorios diferentes (estructura jerárquica). Debe
existir un directorio raíz que contenga a todos los demás.
- Son una secuencia de bits, bytes, líneas o registros que se almacenan en un dispositivo de almacenamiento secundario,
por lo que la información va a permanecer a pesar de que se cierre la aplicación que los utilice.
- Son conjuntos de bytes con una misma estructura.
- Pueden almacenar gran cantidad de información.
- Independencia de la información: la información que contiene existe aunque el programa no se esté ejecutando.
- Al trabajar con ficheros hay que tener en cuenta:
•Para manipular un fichero realizamos tres operaciones: Abrir el fichero | Escribir o leer registros del fichero | Cerrar el fichero.
•La información es binaria.
•Al agrupar los bits, se forman bytes o palabras. Y los tipos de datos van a estar formados por un conjunto de bytes o palabras.
•Al agrupar los campos, se crean los registros de información.
•Una función de los directorios es agrupar distintos ficheros siguiendo las condiciones determinadas por el SO o el programador.

- UTILIDADES DE LOS FICHEROS:


•Permiten organizar más fácilmente el sistema de archivos.
•Evitan conflictos con sus nombres, ya que cada programa instala sus ficheros en directorios diferentes.
•La relación entre ficheros y directorio es muy cercana (en C# se establece entre tipos y espacio de nombres.

- RUTAS DE FICHEROS Y DIRECTORIOS: * Ruta →camino que nos lleva hasta localizar o identificar la ubicación del fichero:
• Ruta absoluta o completa: se le indica el camino del directorio desde el comienzo (en Windows →empieza por la unidad, ej: c:\... | en Linux →por / )
• Ruta relativa: se le indica el camino del directorio desde la posición actual. La ruta no empezaría con la letra de la unidad.

- TIPOS DE FICHEROS:
• Según su acceso y la forma de organizar la información:

- Secuencial: los registros se almacenan consecutivamente y cada vez que queremos acceder a ellos tenemos que
recorrerlos de uno en uno desde el principio. Solo se puede realizar una operación de lectura o escritura a la vez.

- Aleatorio o directo: podemos acceder a un registro concreto indicando su posición. Los registros están organizados pero
pueden ser leídos o escritos en cualquier orden, basta con colocar el puntero justo antes de éste.

- Secuencial indexado: Permiten el acceso secuencial y aleatorio a un fichero porque los ficheros indexados poseen un
campo clave para ser identificados: 1º) busca de forma secuencial el campo clave
2º) accede al fichero directamente con la posición indicada por el campo clave.

• Según su estructura:
- Ficheros de texto: textos planos. (.txt)
- Ficheros binarios: los datos se encriptan y almacenan en binario, su almacenamiento es más eficiente (.bin, .jpg, .mp3,...)
DISEÑO Y MODULACIÓN DE LAS OPERACIONES SOBRE FICHEROS .

* Algunas de las clases que nos proporciona el espacio de nombres System.IO y que se utilizan para realizar operaciones con archivos (ej: crear, eliminar,
leer, escribir, cerrar …) son:

FUNDAMENTOS DE LOS FLUJOS:


Los flujos o stream de datos son las estructuras o pasarelas que tenemos para acceder a los datos de un fichero, de una forma consistente y fiable,
desde un código fuente en cualquier lenguaje de programación.
Hay dos tipos de flujos: De sentido unidireccional →DE ENTRADA DE DATOS (lectura) o DE SALIDA DE DATOS (escritura)
De sentido bidireccional → DE ENTRADA Y SALIDA (lectura y escritura)
- La clase Stream nos permite abstraer de una secuencia de bytes (ej:un archivo) un dispositivo de e/s, una canalización de comunicación entre procesos o un socket.
- La clase FileStream deriva de la clase Stream y nos proporciona los siguientes métodos:
FileStream (string nombre, FileMode modo)
FileStream (string nombre, FileMode modo, FileAccess acceso)
ej:

➢ nombre → ruta donde está guardado o se guardará el fichero.


Ej: * La ventaja de utilizar la @ es que las secuencias de
escape (ej: \n) no se procesan.

➢ modo → cómo se debe abrir un archivo:

➢ acceso → tipo de acceso:


CLASES DE FLUJOS:

Se pueden distinguir:
• Flujos base: los que operan más a nivel máquina (ej: porción de memoria, espacio de disco o conexión de red)
• Flujos intermedios: los que trabajan por encima de los anteriores. Se pueden combinar
con el flujo base y verse beneficiados por las funcionalidades que ofrezca el flujo base.

* El flujo base envía bytes de un lugar a otro mientras que el flujo intermedio procesa la info.

OPERACIONES SOBRE FICHEROS SECUENCIALES .

Las tres operaciones básicas son:


➢ APERTURA:
Cuando abrimos el fichero, estamos relacionando un objeto de nuestro programa con un archivo. Los modos en los que se puede abrir un fichero son:
• Open: abrir el fichero. Si el fichero no existe se lanza una excepción (FileNotFoundException).
• Create: creamos un fichero nuevo. Si el archivo ya existe, se sobrescribe.
• CreateNew: creamos un fichero nuevo. Si el fichero ya existe, se lanza una excepción (IOException).
• Truncate: abrimos un archivo existente y truncamos su tamaño a 0 bytes. Al intentar leer uno abierto en Truncate, se lanza una excepción (ArgumentException).
• OpenOrCreate: se abre un archivo si existe. Si no existe, se crea uno nuevo.
• Append: se abre un archivo, si existe, para añadir datos al final del mismo. Si el archivo no existe, crea uno nuevo.

➢ LECTURA/ESCRITURA:
Tenemos que leer o escribir la información del fichero prestando atención: > en ficheros secuenciales → al fin de fichero
> en ficheros aleatorios → a la posición del puntero

➢ CIERRE:
Cuando cerramos el fichero, este queda liberado y termina el proceso de almacenamiento de información.
LA CLASE FILESTREAM
Lectura de un fichero de texto

Escritura de un fichero de texto

Lectura de ficheros binarios


Para poder leer ficheros binarios debemos:
- crear un fichero FileStream (FileStream fichero = new FileStream(“C:/fichero/pelota.jpg”, FileMode.Open, FileAccess.Read);
- crear un byte (Byte[] buffer= new byte [fichero.Length];)
- leer el bloque de bytes usando → .Read(Byte[], int offset, int count) →
- y escribir los datos en el buffer usando un for.

Escritura de ficheros binarios ??????

CONTROL DE EXCEPCIONES .

Para saber si el fichero está donde esperamos podemos usar el método Exists. Si se prevé otra excepción podemos usar Try/catch para localizar y solventar el problema :

También podría gustarte