0% encontró este documento útil (0 votos)
92 vistas119 páginas

Programacion

Cargado por

Angel Gutierrez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
92 vistas119 páginas

Programacion

Cargado por

Angel Gutierrez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

PROGRAMACIÓN

Desarrollo de aplicaciones web

Ilerna

ILERNA, centro autorizado con código 25002775 (Lleida) y 28077294 (Madrid) [Link]
© Ilerna Online S.L., 2021

Maquetado e impreso por Ilerna Online S.L.

© Imágenes: Shutterstock

Impreso en España - Printed in Spain

Reservado todos los derechos. No se permite la reproducción total o parcial de esta obra, ni su incorporación a un
sistema informático, ni su transmisión en cualquier forma o por cualquier medio (electrónico, mecánico, fotoco-
pia, grabación u otros) sin autorización previa y por escrito de los titulares del copyright. La infracción de dichos
derechos puede constituir un delito contra la propiedad intelectual.

Ilerna Online S.L. ha puesto todos los recursos necesarios para reconocer los derechos de terceros en esta obra
y se excusa con antelación por posibles errores u omisiones y queda a disposición de corregirlos en posteriores
ediciones.

1.a edición: enero 2021


ÍNDICE
Programación

1. Introducción a la programación........................................................ 6

2. Estructura de un programa informático.......................................... 16


2.1. Bloques de un programa informático......................................... 19
2.2. Variables. Usos y tipos ................................................................ 25
2.3. Constantes y literales. Tipos y utilidades.................................... 28
2.4. Operadores del lenguaje de programación................................ 30
2.5. Conversiones de tipos de clase................................................... 34
2.6. Comentarios al código................................................................. 37

3. Programación estructurada............................................................ 40
3.1. Fundamentos de programación.................................................. 42
3.2. Introducción a la algoritmia y herramientas de diseño............. 43
3.3. Ciclo de vida de un proyecto software....................................... 43
3.4. Prueba de programas................................................................... 45
3.5. Tipos de datos: simples y compuestos....................................... 46
3.6. Estructuras de selección (instrucciones condicionales)............ 50
3.7. Estructuras de repetición ............................................................ 54
3.8. Estructuras de salto..................................................................... 57
3.9. Tratamiento de cadenas.............................................................. 58
3.10. Depuración de errores................................................................. 61
3.11. Documentación de programas.................................................... 63
3.12. Entornos de desarrollo de programas......................................... 65

4. Programación modular.................................................................... 66
4.1. Concepto...................................................................................... 67
4.2. Ventajas e inconvenientes........................................................... 67
4.3. Análisis descendente (top down)................................................ 68
4.4. Modulación de programas. Subprogramas................................ 69
4.5. Llamadas a funciones (métodos). Tipos y funcionamiento....... 71
4.6. Ámbito de las llamadas a funciones........................................... 79
4.7. Prueba, depuración y comentarios de programas..................... 83
4.8. Concepto de librerías................................................................... 86
4.9. Uso de librerías............................................................................. 89
4.10. Introducción al concepto de recursividad.................................. 91
5. Gestión de ficheros.......................................................................... 96
5.1. Concepto y tipos de ficheros....................................................... 97
5.2. Diseño y modulación de las operaciones sobre ficheros......... 103
5.3. Operaciones sobre ficheros secuenciales................................. 106
5.4. Control de excepciones.............................................................. 115

Bibliografía / webgrafía.....................................................................116

Solucionario .......................................................................................117
1
INTRODUCCIÓN A LA PROGRAMACIÓN
Programación

Un programa es un conjunto de instrucciones dadas al or-


denador en un lenguaje que solo es entendible por él para
comunicarle lo que queremos que haga. Un algoritmo es
una secuencia finita de operaciones que resuelven un de-
terminado problema.

Un algoritmo es más parecido a una idea, una forma de


resolver un problema, mientras que un programa está más
relacionado con la realización de una o más tareas por
parte de un ordenador.

Un programa debe cumplir una serie de características:

• Deber ser finito: formado por un conjunto limitado de


sentencias.
• Debe ser legible: es importante crear códigos limpios y
fáciles de leer con tabulaciones y espacios que diferen-
cien las partes del programa.
• Debe ser modificable: debe ser sencillo el proceso de ac-
tualización o modificación ante nuevas necesidades.
• Debe ser eficiente: debemos crear programas que ocu-
pen poco espacio en memoria y se ejecuten rápidamente.
• Debe ser modulable: debemos realizar algoritmos que se
dividan a su vez en subalgoritmos de forma que se dis-
ponga de un grupo principal desde el que llamaremos al
resto. Así, incitamos a la reutilización de código.
• Debe ser estructurado: engloba a las características an-
teriores, ya que un programa estructurado será fácil de
leer y modificar, y estará compuesto de subprogramas
que permitirán la reutilización de código.

7
Tema 1: Introducción a la programación

Representaciones gráficas

Para representar un algoritmo, podemos utilizar dos


herramientas gráficas: los diagramas de flujo y el pseu-
docódigo.

Un diagrama de flujo es una representación gráfica de un


proceso. Cada paso del proceso se representa con un sím-
bolo diferente que contiene una breve descripción.

Debemos usar una serie de símbolos estándar:

Indican inicio o fin de programa.

Representan una instrucción, un paso a dar o un proceso. Por


ejemplo: cont= cont+1.

Operaciones de entrada/salida de datos. Por ejemplo: visuali-


za en pantalla suma.

Usaremos este símbolo si nos encontramos en un punto en el


que se realizará una u otra acción en función de una decisión.

Por ejemplo, si miVariable= 0, hacemos la instrucción 1. Si no,


hacemos la instrucción 2.

Conector. Permite unir diferentes zonas del diagrama de


forma que se redefine el flujo de ejecución hacia otra parte
del diagrama.

Representa un método o subprograma.

Flechas para indicar la dirección de flujo.

8
Programación

Características de los diagramas de flujo:

• Deben escribirse de arriba abajo o de izquierda a derecha.


• Debemos evitar el cruce de líneas, para eso se define la
forma de conector. El uso de conectores debe producirse
cuando no exista otra opción.
• Todas las líneas de flujo deben estar conectadas a algún
objeto.
• El texto que se escribe en las formas debe ser escueto y
legible.
• Todos los símbolos de decisión deben tener más de una
línea de salida, es decir, deben indicar qué camino seguir
en función de la decisión tomada.

EJEMPLO

Se representa el siguiente diagrama de flujo, que


muestra todos los números pares del 0 al 98:

INICIO

i <-0

F
i<100

i <- i+2

FIN

9
Tema 1: Introducción a la programación

La otra herramienta para representar los algoritmos es el


pseudocódigo.

Es la manera de representar las distintas sentencias que


va a realizar nuestro algoritmo con un lenguaje cercano al
natural. Por tanto, es un lenguaje que no se puede ejecutar
en una máquina.

Características del pseudocódigo

• Comienza con la palabra algoritmo seguido de su nombre.


• A continuación, tenemos la secuencia de instrucciones
de este algoritmo.
• Finaliza con la estructura FinAlgoritmo.
• No es necesaria la indentación (sangrado), aunque es re-
comendable.
• No se diferencia entre mayúsculas ni minúsculas.

Algoritmo triángulo
Definir área, altura, base de tipo números reales;
Escribir “Introduce la altura del triángulo:”;
Leer altura;
Escribir “Introduce la base del triángulo:”;
Leer base;
Área <- (a*b)/2;
Escribir “El área del triángulo es:”, área;
FinAlgoritmo

Comunicación de un sistema informático

En el proceso de programación se comunica a un usuario


con una máquina. Para que se pueda realizar dicha comu-
nicación, debemos tener:

• Los dos agentes principales, usuario y máquina.


• El canal. Para continuar con el ejemplo con el que esta-
mos explicando el proceso de programación, podemos
decir que el canal por el que se comunica nuestro usuario
será el teclado.
• El lenguaje. Tanto el receptor como el emisor hablan un
lenguaje completamente diferente. Para que la comunica-
ción sea fluida, debemos acercar los lenguajes, tanto de la
máquina como del usuario, y así lograr el entendimiento.

10
Programación

Ahora bien, para solventar el problema de la comunicación,


tenemos lenguajes de programación de tres tipos: alto
nivel, nivel medio y bajo nivel. Los lenguajes de alto nivel
están más cerca del lenguaje que habla el usuario, mien-
tras que los lenguajes de bajo nivel se acercan más a las
estructuras del lenguaje de la máquina. Por su parte, los
lenguajes de nivel medio toman características de ambos,
como por ejemplo el lenguaje C.

11
Tema 1: Introducción a la programación

Para facilitar el trabajo, implementaremos nuestro código


con lenguajes de alto nivel, de modo que necesitaremos
un proceso de traducción para convertir el programa escri-
to en lenguaje máquina.

Características del lenguaje de alto nivel

• Es totalmente independiente de la máquina y, por tanto,


muy portable.
• Muy utilizado en el mercado laboral informático.
• Tanto las modificaciones como las actualizaciones son
muy fáciles de realizar.
• Para la tarea de traducción de código necesitamos un
compilador y un enlazador con librerías del propio len-
guaje de programación elegido.
Algunos ejemplos de lenguajes de alto nivel son java, php,
c#, [Link], Python…

Características del lenguaje de bajo nivel

• Está relacionado con las características del hardware.


• Es fácilmente traducible al lenguaje máquina.
• Es totalmente dependiente de la máquina.
Un ejemplo de lenguaje de bajo nivel es Ensamblador. Este
lenguaje trabaja con registros a más bajo nivel.

12
Programación

A lo largo de esta unidad formativa hablaremos de la es-


tructura de un programa informático y de sus elementos
principales, como son las variables, las constantes y los
distintos operadores que podemos usar a la hora de imple-
mentar un código fuente.

Lenguajes compilados e interpretados

Aquellos lenguajes de alto nivel que utilizan un compilador


para poder traducirlo al lenguaje máquina se denominan
lenguajes compilados.

En nuestro caso, un programa escrito en C# necesita un


compilador de C#. En este supuesto, el lenguaje máquina
no corresponde al del ordenador, sino al de una máquina
ficticia llamada máquina virtual. En C#, la máquina virtual
se denomina CLR (Common Language Runtime).

Esta máquina no existe físicamente, sino que es simulada


por un ordenador. Podemos instalarla en nuestro ordena-
dor copiando ese programa en nuestro disco duro.

Gracias a esa máquina, podemos ejecutar nuestro progra-


ma en cualquier ordenador del mundo.

Un lenguaje interpretado no genera un programa escrito


en una máquina virtual. Efectúa directamente la traduc-
ción y ejecución simultáneamente para cada una de las
sentencias.

13
Tema 1: Introducción a la programación

Un intérprete verifica cada línea del programa cuando se


escribe. La ejecución es más lenta debido a esta traducción
simultánea.

En esta asignatura vamos a centrarnos en el lenguaje de


programación C#. Otro lenguaje muy utilizado actualmen-
te es el lenguaje Java. En la siguiente tabla mostramos las
características de ambos:

C# Java

Es un lenguaje orientado a objetos. Es un lenguaje orientado a objetos.

Contiene dos categorías generales de Los argumentos son siempre pasados


tipos de datos integrados: tipos de por valor independientemente del tipo
valor y tipos de referencia. de variable.

La migración de C# a Java es sencilla La migración de Java a C# es sencilla


porque mantiene una sintaxis muy porque mantiene una sintaxis muy
similar. similar.

C# está incluido en la plataforma .NET Gracias al recolector de basura, se


que tiene a su disposición el recolector elimina la necesidad de la liberación
de basura del CLR (Common Language explícita de memoria.
Runtime o entorno en tiempo de
ejecución).

En C# todos los tipos derivan de una Java soporta sincronización de múlti-


superclase común llamada System. ples hilos de ejecución (multithreading)
Object. A diferencia de Java, esta a nivel de lenguaje.
característica también se aplica para los
tipos básicos.

C# es un lenguaje compilado. Java es compilado, en la medida en


que su código fuente se transforma en
un código máquina muy parecido al
lenguaje ensamblador.

Se genera un código intermedio Java es interpretado, ya que ese


llamado MSIL (Microsoft Intermediate código máquina se puede ejecutar
Language) y luego ese código se vuelve directamente sobre cualquier máquina
a compilar para obtener el formato la cual tenga el intérprete y el sistema
nativo en la máquina en la que se va a de ejecución en tiempo real.
ejecutar.

14
Programación

ponte a prueba

¿Cómo debe ser un programa informático?


a) Legible.
b) Modificable.
c) Eficiente.
d) Todas las opciones anteriores son correctas.

¿Cuál de las siguientes opciones sobre el


siguiente diagrama de flujo es correcta?

INICIO

“Escribe el valor de N”

i <- 1
Result <-0

no

i<=N

si

Result <-2*i-1
FIN
i<-i+1

“Escribe el valor de result”

a) Muestra los n primeros números impares.


b) Realiza un producto de dos números.
c) Muestra los n primeros múltiplos.
d) Realiza la suma de dos números.

C# tiene dos categorías tipos de datos inte-


grados: por valor y por referencia.
a) Verdadero.
b) Falso.

15
2
ESTRUCTURA DE UN PROGRAMA INFORMÁTICO
Programación

El lenguaje de programación C# es un lenguaje de alto nivel


que pertenece al conjunto de lenguajes de .NET. C# es una
evolución de C++ y mucha de la sintaxis está heredada de
este lenguaje.

Con C#, podemos crear aplicaciones con una interfaz de


texto, que denominamos aplicaciones de consola.

Una de las ventajas de aprender este lenguaje es que es


independiente de la plataforma donde lo ejecutemos (sea
Intel o AMD).

Para desarrollar nuestros programas ne C#, utilizaremos


un IDE. Un entorno de desarrollo integrado (IDE) es un
software diseñado para el desarrollo de aplicaciones con
un conjunto de herramientas integradas en una interfaz
gráfica de usuario (GUI).

Sus características son:

• Editor de código fuente: ayuda al programador a es-


cribir el código, resaltando la sintaxis de forma visual y
rellenando de forma automática las distintas opciones
que nos proporciona el lenguaje.
• Depurador: ayuda al programador a localizar sus errores
de código.
• Compilación del código fuente: un código binario en-
tendible por la máquina.

Para plataformas Windows, podemos desarrollar con IDE


Visual Studio. El proyecto que implementa el desarrollo de
.NET en GNU/Linux es el proyecto Mono, concretamente el
entorno de desarrollo MonoDevelop.

Con estos programas, vamos a ir generando los diferentes


proyectos. Cada vez que creemos un proyecto nuevo, el
programa va a generar solo un fichero de código fuente,
que es el que va a dar lugar al ejecutable que necesita la
aplicación.

Este fichero que se genera debe tener la extensión cs, ya


que es la extensión utilizada por los ficheros en C#.

17
Tema 2: Estructura de un programa informático

Instalación de Visual Studio

Para instalar nuestro Visual Studio, vamos a la página oficial


de Microsoft, donde, en la parte de downloads, tendremos
varias opciones.

Así, descargamos Visual Studio Community, que es la


versión gratuita:

BUSCA EN LA WEB

[Link]/es/downloads/

Una vez descargado, procedemos a la instalación.

Durante la instalación, nos dará a elegir entre una serie de


paquetes instalables.

Nosotros, para realizar nuestras aplicaciones de consola,


añadiremos el siguiente paquete:

18
Programación

Instalación de MonoDevelop

Para la instalación de este IDE en plataformas como Ubun-


tu o Debian, podemos seguir las indicaciones de la página
oficial:

BUSCA EN LA WEB

[Link]/download/#fndtn-
download-lin

2.1.  Bloques de un programa


informático

Estructura de un programa
[Link]/MTJoNPqXT1E

Podemos definir un programa como una secuencia de ins-


trucciones separadas por un punto y coma que se van a ir
agrupando en diferentes bloques mediante llaves.

Para crear un proyecto, abrimos nuestro Visual Studio y


seleccionamos la opción de Crear un proyecto.

19
Tema 2: Estructura de un programa informático

Posteriormente, elegiremos la opción de Crear un aplicati-


vo de consola.

Nombramos nuestra aplicación con el nombre que quera-


mos y seleccionamos la ruta donde lo guardaremos.

Cuando hayamos configurado estos parámetros, se nos


abrirá la interfaz de nuestro IDE, que estará formado por
tres partes principales:

20
Programación

• La primera parte será nuestro editor de código. El desa-


rrollador implementará todas las instrucciones necesarias
para completar su programa.
• La segunda es el explorador de soluciones. En esta parte
de nuestro IDE, veremos los archivos generados de nues-
tro aplicativo.
• La tercera parte es la salida. Nos proporcionará el resulta-
do de si la compilación ha sido correcta o, por el contrario,
si ha habido un error, así como también el porqué de ese
error.

Cuando creamos el proyecto, se crea la siguiente estructura:

using System;

namespace MiAplicación
{
class Program
{
static void Main(string[] args)
{

}
}
}

La estructura que Visual Studio nos crea por defecto es la


clase program. Una clase es una estructura de datos que
está compuesta por atributos o variables (de las que ha-
blaremos más adelante) y métodos o funciones. El método
principal se denomina Main.

21
Tema 2: Estructura de un programa informático

De hecho, siempre que ejecutemos un programa, el primer


método que se ejecutará será el Main. Este método tiene
una serie de argumentos. Estos argumentos son cade-
nas de caracteres que podemos pasar línea de comandos
(CMD):

Nosotros trabajaremos con la Consola de nuestro entorno


de desarrollo.

Entrada y salida por pantalla

Para establecer la comunicación entre el usuario y el pro-


grama, emplearemos la clase Console.

• Para la salida por pantalla, podemos utilizar los métodos


de esta clase, Write y Writeline:
– El método Write() escribe un valor o valores especifica-
do(s) en el flujo de salida estándar, que generalmente
será nuestra pantalla.
– El método WriteLine() escribe un valor o valores
especificado(s) en el flujo de salida estándar, que gene-
ralmente será nuestra pantalla, y se realiza un salto de
línea en nuestra consola.

22
Programación

using System;

namespace MiAplicación
{
class Program
{
static void Main(string[] args)
{
[Link](“Hello World!”);
[Link](“Programming...”);
}
}
}

La salida será:

Para la entrada de datos de usuario, utilizaremos el méto-


do ReadLine(). Este método leerá el dato introducido por
el usuario y devolverá un dato de tipo cadena (string).

using System;

namespace MiAplicación
{
class Program
{
static void Main(string[] args)
{
[Link](“Introduce un dato”);
string dato = ReadLine();
}
}
}

Otra forma para recoger los datos de entrada de usuario es


el método Read(). Este método leerá el dato introducido
por el usuario y devolverá un dato de tipo entero (int).

Asimismo, otro método utilizado por la clase Console es


el método ReadKey(). En este caso, se obtiene el carácter
presionado por el usuario y se muestra esta tecla por la
pantalla.

23
Tema 2: Estructura de un programa informático

Se pueden consultar más métodos de esta clase en el sigui-


ente enlace:

BUSCA EN LA WEB

[Link]
console?view=netframework-4.8

ponte a prueba

¿Qué es un IDE?
a) El lenguaje C# es considerado como un IDE.
b) El lenguaje java es considerado como un IDE.
c) Es un software diseñado para el desarrollo de
aplicaciones.
d) Ninguna de las respuestas es correcta.

Siempre que ejecutemos un programa, el


primer método que se ejecutará será el Main.
a) Verdadero.
b) Falso.

¿Qué realiza el siguiente código?

static void Main(string[] args)


{
[Link](“Hello World!”);
}

a) Muestra por pantalla args.


b) Muestra por pantalla “Hello World!”.
c) Muestra por pantalla Hello World!
d) Realiza una lectura de datos de args.

24
Programación

2.2.  Variables. Usos y tipos


Una variable es una estructura de datos que ocupan un es-
pacio en memoria y pueden variar a lo largo de un programa.

Cuando declaramos una variable, establecemos el tipo de


dato (entero, cadena, carácter, etc.) y su identificador.

class Program
{
static void Main(string[] args)
{
int numero;
numero = 10;
char letra = ‘a’;
string cadena = “Esta es una cadena”;
}
}

Tipos de datos en C#:

Tipo simple Descripción

Sbyte, short, int, long Enteros con signo

Byte, unshort, unit, Enteros sin signo


ulong

Float, double Punto flotante

Char Uno o varios caracteres

Decimal Decimal de alta precisión

Bool Booleano

• Tipo String: son cadenas de caracteres. Por ejemplo:


string cadena = “Hola mundo”;
• Tipo de dato enumerado: enum días_semana {lunes,
martes, miercoles};
• Tipos matriz:
– Unidimensionales:
int[] array = new int[5];
int[] array2 = new int[] { 1, 3, 5, 7, 9 };
int[] array3 = { 1, 2, 3, 4, 5, 6 };
– Multidimensionales:
int[,] multiDimensionalArray1 = new int[2, 3];
int[,] multiDimensionalArray2 = { { ‘a’, ‘b’, ‘c’ }, { ‘d’, ‘e’, ‘f’ } };

25
Tema 2: Estructura de un programa informático

Para definir una variable, necesitamos conocer primero el


tipo de datos que va a almacenar y, a continuación, el nombre
que le vamos a asignar. Es recomendable que este nombre
tenga relación con el ejercicio que estemos desarrollando.

Para identificar a una variable, y que tenga un identifica-


dor válido por el compilador, debemos seguir una serie de
normas:

• Debe comenzar por un carácter (letra o “_”).


• Debe estar formada por caracteres del alfabeto (no pode-
mos usar “ñ”) o por dígitos (del 0 al 9). Se puede utilizar
el subrayado (“_”).
• No debe comenzar con un dígito.
• Distingue entre mayúsculas y minúsculas.
• No puede llevar espacios en blanco.
• No se pueden utilizar palabras reservadas. Por ejemplo,
string es una palabra reservada como tipo de dato cadena.
A continuación, encontraréis una lista de las palabras claves
(o identificadores) predefinidos por el compilador:

BUSCA EN LA WEB

[Link]
language-reference/keywords/

Para declarar una variable:

<tipo> <nombre_variable>;

Y en C# lo pondríamos de la siguiente forma:

int num;

En este caso, estamos definiendo una variable de tipo en-


tero denominada num.

A las variables también se les puede asignar un valor:

int num=5;

Definimos una variable de tipo entero, denominada num y


le asignamos el valor de 5.

Debemos utilizar un tipo u otro de variable, dependiendo


del tipo de dato que queremos tratar.

26
Programación

A grandes rasgos, podemos dividir las variables en dos


grandes bloques, dependiendo del ámbito en el que se
encuentren:
• Variables locales: aquellas declaradas dentro de un mé-
todo o función.
• Variables globales: aquellas declaradas fuera de un mé-
todo o función. Podemos acceder a ellas desde cualquier
punto del programa.

Más adelante definiremos el concepto de ámbito de va-


riables, cuando hablemos del concepto de programación
modular.

No es buena práctica utilizar variables globales.

AVISO
El problema de las variables globales es que crean depen-
dencias ocultas. Cuando se trata de una aplicación grande,
el programador no conoce los objetos que tiene ni sus
relaciones.

27
Tema 2: Estructura de un programa informático

ponte a prueba

¿Cuál de las siguientes opciones es una


característica de una variable?
a) Ocupa espacio en memoria.
b) P
 uede variar su contenido a lo largo del
programa.
c) Es de un tipo de dato.
d) Todas las respuestas son correctas.

¿Qué tipo de dato es un char?


a) Carácter.
b) Entero.
c) String.
d) Decimal.

Las variables globales son aquellas que están


declaradas dentro de un método o función.
a) Verdadero.
b) Falso.

2.3.  Constantes y literales.


Tipos y utilidades
Constantes

En el apartado anterior hemos hablado de las variables


como espacio de memoria donde se almacenan datos que
pueden variar a lo largo del programa. Ahora trabajaremos
con los espacios de memoria cuyo contenido no se puede
alterar a lo largo del programa: las constantes.

El valor se establece en tiempo de compilación y no se


puede cambiar su contenido.

const <tipo> <nombre_variable>;

Por ejemplo:

const int num;

28
Programación

Después, declaramos una constante de tipo entero que


denominamos num.

A continuación, exponemos una constante llamada días


semana, con el valor 7, ya que todas las semanas tienen 7
días:

class Calendar1
{
public const int dias_semanas = 7;
}

Las constantes se definen fuera del cuerpo de cualquier


función, normalmente al principio del programa.

• Literales
Mediante un literal podemos representar de forma explí-
cita todos los valores que pueden tomar los tipos básicos
del lenguaje.
Seguidamente, vamos a explicar los diferentes tipos de
literales que podemos encontrarnos en C#.

• Literales enteros:
– Decimales: sin ningún prefijo. Por ejemplo: int dLiteral
= 10;
– Hexadecimales: con el prefijo de 0x o 0X. Por ejemplo:
int hLiteral= 0x3F;

• Literales reales:
– El literal sin sufijo o con el sufijo d o D es del tipo double.
– Por ejemplo: double num = 3.4d;
– Double num2= 3.4;
– El literal con el sufijo f o F es del tipo float.
– Por ejemplo: float variable = 4.5F;
– El literal con el sufijo m o M es del tipo decimal.
– Por ejemplo: decimal numero = 3.2m;

• Literales de lógicos: representados por los valores lógi-


cos true (verdadero) y false (falso).

• Literales de carácter: cualquier carácter en C# podemos


representarlo con comillas simples. Por ejemplo, ‘a’ co-
rrespondería al carácter a.

29
Tema 2: Estructura de un programa informático

Existen caracteres especiales que pueden representarse de


la siguiente forma:

Carácter Representación
ponte a prueba
Comilla simple \’

¿Con qué palabra reservada se Comilla doble \”


define una constante?
a) Const Carácter nulo \0
b) Enum
Retroceso \b
c) Array
d) N
 inguna de las opciones es Salto de página \f
correcta
Nueva línea \n
¿Qué representa el literal \n?
a) U
 na nueva línea Retorno de carro \r
b) Un carácter nulo Tabulación horizontal \t
c) Un salto de página
d) Una tabulación vertical Tabulación vertical \v

2.4.  Operadores del lenguaje de


programación

Operadores aritméticos

Operadores aritméticos

+ Suma aritmética de dos valores.

++ Incremento en 1 del operando.

- Resta aritmética de dos valores.

-- Decremento en 1 del operando.

* Multiplicación aritmética de dos valores.

/ División aritmética de dos valores.

% Obtiene el resto de la división entera.

El operador de incremento ++ puede ser aplicado como


prefijo o sufijo de una variable.

30
Programación

El resultado de num++ es el valor de num antes de la ope-


ración:

int num = 100;


[Link](num); // salida por pantalla: 100
[Link](num++); // salida por pantalla: 100
[Link](num); // salida por pantalla: 101

El resultado de ++num es el valor de num después de la


operación:

double num = 10.4;


[Link](num); // salida por pantalla: 10.4
[Link](++num); // salida por pantalla: 11.4
[Link](num); // salida por pantalla: 11.4

Asimismo, sucede lo mismo con el operador decremento - -.

La prioridad de los operadores (de mayor a menor prio-


ridad) es:
1. Operadores de incremento x++ y decremento x-- sufijos.
2. Operadores de incremento ++x y decremento --x prefijos.
3. Operadores de multiplicación, división y resta *, / y %.
4. Operadores de suma y resta + y -.

Operadores booleanos

Operadores booleanos

& AND lógico. Evalúa ambos operandos.

&& AND lógico. Evalúa el operando derecho solo


si es necesario.

| OR lógico. Evalúa ambos operandos.

|| OR lógico. Evalúa el operando derecho solo si


es necesario.

^ XOR lógico.

! Negación lógica.

El operador AND lógico & calcula el AND lógico de sus


operandos. El resultado de a & b es true si a y b se evalúan
como true. Si no, el resultado es false.

31
Tema 2: Estructura de un programa informático

El operador AND lógico condicional && también evalúa


el operador AND lógico de sus operandos, pero no evalúa
el operando derecho si el izquierdo se evalúa como false.

El operador | calcula el operador OR lógico de sus


operandos. El resultado de a | b es true si a o b se evalúan
como true. Si no, el resultado es false.

El operador OR lógico condicional || también evalúa el


operador OR lógico de sus operandos, pero no evalúa el
operando derecho si el izquierdo se evalúa como true.

El operador ^ es el operador OR exclusivo o XOR. La tabla


de la verdad (tabla que muestra el resultado de una combi-
nación de valores) es la siguiente:

a b a^b

T T F

T F T

F T T

F F F

El operador ! calcula la negación lógica de su operando, es


decir, si el operando es true, devolverá el valor false. Si el
operando es false, devolverá el valor true.

Operadores de comparación e igualdad

Operadores de comparación

> Mayor.

< Menor.

>= Mayor o igual.

<= Menor o igual.

== Igual.

!= Desigualdad.

= Asignación.

El operador < devuelve true si el operando izquierdo es


menor que el derecho.

El operador > devuelve true si el operando izquierdo es


mayor que el derecho.

32
Programación

El operador <= devuelve true si el operando izquierdo es


menor o igual que el derecho.

El operador >= devuelve true si el operando izquierdo es


mayor o igual que el derecho.

El operador de igualdad == devuelve true si sus operandos


son iguales.

El operador de desigualdad != devuelve true si sus


operandos son distintos.

ponte a prueba

¿Cuál es el resultado del siguiente código?

int x = 1;
num++;
[Link](num);

a) 1.
b) 2.
c) 0.
d) Ninguna de las repuestas es correcta.

¿Cuál de las siguientes opciones sobre el


operador ! es correcta?
a) Calcula la negación lógica de nuestro
operando.
b) Incrementa en 1 nuestro operando.
c) Decrementa en 1 nuestro operando.
d) Compara dos operandos.

33
Tema 2: Estructura de un programa informático

2.5.  Conversiones de tipos de


clase
Como hemos visto anteriormente, en C#, cuando declara-
mos una variable, no se puede volver a declarar, ni asignar
un valor de otro tipo.

Por tanto, si tenemos una variable de tipo entero, no pode-


mos asignar un valor de tipo string.

Este fragmento de código daría un error:

int numero=10;
numero = “a”; // No se puede convertir
implícitamente el tipo ‘string’ en ‘int’

Sin embargo, en ocasiones, podemos convertir el valor de


una variable de un tipo de dato a otro tipo. A estas conver-
siones se les denomina conversiones de tipos.

Podemos tener diferentes clases de conversiones:

• Conversiones implícitas: son aquellas que se producen


cuando el valor que se va a almacenar se puede almace-
nar en la variable sin truncarse ni redondearse.
Por ejemplo, una variable de tipo long puede almacenar
datos de hasta 64 bits. Por tanto, puede almacenar cual-
quier dato de tipo int (32 bits).

int a = 300;
long numero=a;

• Conversiones explícitas: cuando no hay posibilidad de


realizar una conversión implícita es cuando debemos
indicar al compilador que se pretende realizar una con-
versión que pueda producir una pérdida de datos.

double num = 100.85;


int b;
b = (int)num;
[Link](b);

// La salida por pantalla será 100

Parse y TryParse

Con los métodos Parse y TryParse, podemos convertir una


cadena en varios tipos numéricos: int, decimal, double…

El método Parse devuelve el número convertido. El método


TryParse devuelve un valor booleano indicando si la

34
Programación

conversión se realizó correctamente o no, y devuelve el


número convertido.

int numValido = [Link](“-100”);


[Link](numValido);

// La salida por pantalla será -100

While ([Link](“50”, out int miNumero))


// El argumento miNumero, se pasa por referencia. Lo veremos más
adelante en el apartado 4.5. Llamadas a funciones. Tipos y funcionamento.

[Link](miNumero);

// La salida por pantalla será 50

Convert

Es una clase que convierte un tipo de datos en otro. Algu-


nos métodos son:

Método Descripción

ToBoolean Convierte un valor especificado en un valor booleano.

ToChar Convierte un valor especificado en un carácter.

ToDecimal Convierte un valor especificado en un número decimal.

ToDouble Convierte un valor especificado en un número de punto flotante.

ToInt16 Convierte un valor especificado en un entero de 16 bits.

ToInt32 Convierte un valor especificado en un entero de 32 bits.

ToInt64 Convierte un valor especificado en un entero de 64 bits.

ToString Convierte un valor especificado en su representación de cadena.

double numero = 30.5;


string cadena = [Link](numero);

// Mostraría por pantalla la cadena “30.5”

35
Tema 2: Estructura de un programa informático

EJEMPLO

Ejemplo

Según el siguiente código:

Int a=10, b=3, c=1, d, e;

Float x,y;

x=a/b;

c=a<b && c;

d= a + b++;

e= ++a - b;

y= (float)a / b;

// habría un error en la sentencia c=a<b &&


c, porque estamos evaluando una condición
booleana, mientras que la variable c es una
variable de tipo entero.

36
Programación

ponte a prueba

Las conversiones implícitas son ¿Qué convierte el método ToString?


aquellas que se producen cuando
a) Un valor especificado en un entero
el valor que se va a almacenar se
de 64 bits.
puede almacenar en la variable sin
pérdida de información. b) U
 n valor especificado en un
carácter.
a) Verdadero.
c) Un valor especificado en un valor
b) Falso. booleano.
d) E
 l valor especificado en su repre-
sentación de cadena.

2.6.  Comentarios al código


Hasta ahora nos hemos introducido en la creación por
parte de un programador de código fuente con una fina-
lidad concreta. No debemos pasar por alto que, además
de realizar programas, lo debemos hacer de la forma más
optimizada y ordenada posible.

En el ámbito de la organización entra en escena el concepto


de los comentarios. Es una herramienta disponible en el
compilador para que el programador pueda hacer anota-
ciones en el código sin que sea procesado por el compilador.
Estas anotaciones deben de esclarecer el propio código y
ayudar a entender las sentencias del programa. Así, futuros
programadores podrán conocer su funcionamiento.

En el lenguaje de programación C# está permitido hacer


dos tipos de comentarios:

• Comentarios de una línea: son frases cortas y, por tan-


to, solo pueden ocupar una línea del código. Debemos de
escribir “//” antes de comenzar con dichas anotaciones.
• Comentarios multiline o multilíneas: son comentarios
de varias líneas, que se utilizan para hacer una explicación
mucho más detallada del código en cuestión. También
podemos hacer uso de este tipo de comentarios cuando
deseamos que una parte del código no sea procesada por
el compilador. En este caso, debemos de englobar el tex-
to entre los caracteres “/*” y “*/”.

37
Tema 2: Estructura de un programa informático

El uso de los comentarios es muy útil y, por tanto, se acon-


seja a los programadores que implementen programas con
tantos comentarios como sea posible para documentar el
código.

/*Programa que muestra por


pantalla la frase
Buenas tardes*/

// Está compuesto por la clase Hello1 y el método Main()

public class Hello1


{
public static void Main()
{
[Link]("Buenas tardes");
}
}

ponte a prueba

Según el siguiente código, ¿qué saldrá por


pantalla?

static void Main(string[] args)


{
/* [Link] (“HOLA MUNDO”);
Int i=10;
[Link] (i);
*/
}

a) HOLA MUNDO
b) HOLA MUNDO10
c) HOLA MUNDO
10
d) Nada, porque el código está comentado

Para hacer comentarios de una sola línea,


debemos utilizar el operado /.
a) Verdadero
b) Falso

38
Programación

39
3
PROGRAMACIÓN ESTRUCTURADA
Programación

La programación estructurada es un procedimiento que


consiste en diseñar e implementar programas de forma
clara y sencilla para que puedan ser mantenidos con fa-
cilidad.

La idea de la programación estructurada fue expuesta por


E.W. Dijkstra1 en 1965 y su base teórica se apoyó en los
trabajos de Böhm y Jacopini2.

El estudio concluyó que, con la combinación de tres tipos


de instrucciones, podemos crear un programa estructurado:

Secuencia de instrucciones

x y

Selección de instrucciones

x
ro
ade
rd
ve
condición
fal
so
y

Iteración o bucle de instrucciones

x
verdadero

falso
condición
iteración

1 Serna, M. E. (2009). Edsger Wybe Dijkstra. Revista Digital


Lámpsakos, no. 2, pp. 107-11.
2 Corrado Böhm, Giuseppe Jacopini. (1966). Flow diagrams, turing
machines and languages with only two formation rules. 2020, de
ACM Digital Library, Association for Computing Machinery. Sitio
web: [Link]

41
Tema 3: Programación estructurada

3.1.  Fundamentos de
programación
Los fundamentos de la programación se basan en un
conjunto de técnicas que persiguen desarrollar algo-
ritmos que sean sencillos de escribir, leer, modificar y
testear.
El orden en que se ejecutan las sentencias de un programa
es secuencial. Este flujo significa que las sentencias se eje-
cutan en secuencia, una después de otra, y en el orden en
que se encuentran dentro del programa.

Teorema de Böhm y Jacopini

Un programa debe de cumplir las siguientes características:

• Debe tener un único punto de entrada y uno de salida.


• Toda acción del algoritmo debe ser accesible. Tiene que
haber al menos un camino que va desde el inicio hasta el
fin del algoritmo.
• No deben existir, por tanto, bucles infinitos.

El programa se encarga de transformar la entrada en salida:

ENTRADA PROGRAMA SALIDA

Por lo tanto, la programación es un proceso de desarrollo


que nos ayuda a resolver un determinado problema.

ponte a prueba

Dijkstra concluyó que la combi- Según Böhm y Jacopini, ¿cuál de


nación de varios tipos de instruc- las siguientes opciones sobre un
ciones, podemos crear un programa programa es cierta?
estructurado. ¿Cuáles son?
a) Tiene un único punto de entrada y
a) Secuencia de instrucciones. uno de salida.
b) Selección de instrucciones. b) Toda acción del algoritmo debe ser
c) Iteración de instrucciones. accesible.
d) Todas las opciones son correctas. c) No deben existir bucles infinitos.
d) Todas las respuestas son correctas.

42
Programación

3.2.  Introducción a la
algoritmia y herramientas de
diseño
Un algoritmo es una secuencia de los pasos y las distintas
operaciones que debe realizar el programa para conseguir
resolver un problema planteado.

En cambio, la algoritmia es un conjunto ordenado y finito


de operaciones que permite encontrar la solución a un pro-
blema cualquiera.

La algoritmia utiliza un conjunto de herramientas lógicas,


matemáticas e informáticas con el objetivo de diseñar y
presentar un algoritmo. Anteriormente, ya hemos hablado
de dos herramientas para la construcción de algoritmos: el
pseudocódigo y los diagramas de flujo. Este conjunto de
herramientas es utilizado en las etapas de Ingeniería del
Software que veremos a continuación.

3.3.  Ciclo de vida de un proyecto


software
La imagen representa el ciclo de vida de un programa
informático, de manera que las flechas indican el orden de
realización de cada etapa.

43
Tema 3: Programación estructurada

• Análisis de requisitos: a partir de las necesidades del


usuario o del programa planteado, se decide qué es lo
que hay que hacer para llegar a conseguir una solución
óptima, y se genera un documento de requisitos. Se trata
de la etapa más importante del ciclo de vida.
Existen varias técnicas para obtener los requisitos del
usuario:
– Entrevistas
– Brainstrorming
– Prototipos
– Casos de uso
– JAD (entrevistas en grupos o talleres)
• Diseño de la arquitectura: se hace un estudio para ver
los distintos componentes que van a formar parte de
nuestro programa (módulos, subsistemas, etc.) y se ge-
nera un documento de diseño. Esta fase se va a revisar
todas las veces que sea necesario hasta que estemos se-
guros de cuál va a ser la mejor solución.
– Diseño estructurado: tenemos varias notaciones como
los diagramas de flujo o el pseudocódigo.
– Diseño orientado a objetos: trabajaremos con repre-
sentaciones en UML (diagramas de clases, diagramas
de secuencia, etc.).
• Etapa de implementación o codificación: en esta eta-
pa vamos a pasar a codificar las aplicaciones que hemos
elegido en la etapa anterior, empleando el lenguaje de
programación con el que estemos trabajando. El resulta-
do que vamos a obtener va a ser el código fuente.
• Pruebas de integración: hay que realizar ensayos del
funcionamiento, combinando todos los módulos de la
aplicación. Así, haciendo funcionar la aplicación comple-
ta, comprobamos que cumple lo establecido en el diseño.

44
Programación

• Pruebas de validación: el último paso de la integración


se basa en realizar nuevas pruebas de la aplicación en su
conjunto. El objetivo es cerciorarse de que se cumple lo
establecido en el documento de requisitos y que cubre las
necesidades de los usuarios que ya habíamos previsto.
• Fase de mantenimiento: revisar todo el proceso anterior
e ir actualizando o modificando los cambios oportunos
en las etapas anteriores.

ponte a prueba

En la etapa de diseño, tomamos los requi-


sitos de los clientes.
a) Verdadero
b) Falso

Después de la fase de pruebas, ¿qué etapa se


lleva a cabo?
a) Análisis
b) Implementación
c) Mantenimiento
d) Ninguna de las opciones es correcta

3.4.  Prueba de programas


Una vez implementado y compilado el código de nuestro
algoritmo, debemos ponerlo en marcha y comenzar la
etapa de testing, plan de prueba o prueba de programa.

En ella, se prueba un programa para demostrar la existencia


de defectos: algorítmicos, de sintaxis, de documentación,
de sobrecarga, de capacidad, de rendimiento, de sincro-
nización, de recuperación, de hardware y software y de
estándares.

Este proceso de prueba del programa se lleva a cabo de


manera automática o manual y persigue los siguientes
objetivos:

• Comprobar los requisitos funcionales y no funcionales del


programa.
• Probar todo tipo de casos para detectar alguna anomalía
en su ejecución.

45
Tema 3: Programación estructurada

Tenemos dos tipos de técnicas de pruebas:

• Pruebas de caja blanca: donde se valida la estructura


del sistema.
• Pruebas de caja negra: donde se analizan las entradas y
salidas del sistema sin tener en cuenta el funcionamiento
interno.
CAJA BLANCA

Entrada(s) Salida(s)

CAJA NEGRA

Entrada(s) Salida(s)

El plan de prueba consta de varias etapas, ya que, después


de implementar el código, si existiera algún tipo de fallo
en el programa, tendríamos que volver a empezar con el
nuevo código modificado.

3.5.  Tipos de datos: simples y


compuestos
C# es un lenguaje de programación en el que cada variable,
constante, atributo o valor que devuelve una función se en-
cuentra establecido en un rango de elementos ya definidos.

Podemos diferenciar entre:

Tipos simples

A la hora de seleccionar un determinado tipo, debemos


considerar el rango de valores que puede tomar, las ope-
raciones a realizar y el espacio necesario para almacenar
datos.

Debemos tener en cuenta que el tipo de datos simple no


está compuesto por otros tipos, y que contiene un valor
único.

• Tipos simples predefinidos: entre sus propiedades más


importantes podemos destacar que son indivisibles, tie-
nen existencia propia y permiten operadores relacionales.

46
Programación

Se utilizan sin necesidad de ser definidos previamente:


– Natural: números naturales (N): byte, uint, ushort,
ulong.
– Entero: números enteros (Z): sbyte, int, long, short.
– Real: números reales (R): decimal, float, double.
– Carácter: caracteres (C): char.
– Lógico: booleanos (B): bool.
• Tipos simples definidos por el usuario
– Tipos enumerados: es un tipo de valor definido por el
usuario, así como un conjunto de constantes. Para defi-
nir un tipo de enumeración, utilizamos la palabra clave
enum y especificamos los nombres de componentes de
la enumeración:

public class EnumTest


{
enum dias {Domingo,Lunes,Martes,Miercoles,Jueves,Viernes,Sabado};

static void Main()


{
int x = (int)[Link];
int y = (int)[Link];
[Link](«Domingo = {0}», x);
[Link](«viernes = {0}», y);
}
}
/* Salida:
Domingo = 0
Viernes = 5
*/

47
Tema 3: Programación estructurada

Tipos compuestos o estructurados

Se crean mediante la unión de varios tipos (simples o com-


puestos).

• Vectores: estructura donde almacenamos varias varia-


bles del mismo tipo. Se puede declarar una matriz si se
especifica el tipo de sus elementos. También son llama-
dos array unidimensional, es decir, de una dimensión.
Con esto, nos damos cuenta de la cantidad de indica-
dores de posición que necesitamos para acceder a un
elemento de la tabla.
Sintaxis:

<tipo> [] <nombre> = new <tipo> [<tamaño>];

Por ejemplo:

int [] v = new int [10];


int[] array1 = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
int[] array2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

Con el anterior código, estamos declarando 10 números


enteros en un vector al que hemos llamado v.

A continuación, veremos la manera de acceder a cada uno


de ellos. Cabe recordar que la primera posición de todo
array es el 0:

v[0]  Primer número entero del vector.

v[1]  Segundo número entero del vector.

v[2]  Tercer número entero del vector.

v[3]  Cuarto número entero del vector.

v[9]  Último número entero del vector

Veamos el siguiente ejemplo:

char[] miArray = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’};


for (int x=0; x<5; x++) {
miArray [1]=’z’;
}
[Link](miArray[1]);
// Guardamos en la posición 1, el carácter z. Por lo que, por panta-
lla, mostrará ese carácter en esa posición. Ahora el vector estaría
formado por {‘a’, ‘z’, ‘c’, ‘d’, ‘e’}

• Matrices: unión de varios vectores de cualquier tipo


simple (enteros, reales, etcétera). También la podemos

48
Programación

ver como un array bidimensional, por tanto, esos datos


nos indican que necesitamos dos indicadores de posición
para acceder al elemento. La primera posición de una
matriz es (0,0).
Sintaxis:

Tipo [,] Nombre= new Tipo [filas, columnas];

Por ejemplo:

int [,] matriz = new bool[2,3];


int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
int[,] miMatriz = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };

En este caso:

int [,] matriz = new bool[2,3];


estamos declarando una matriz denominada matriz, de
tipo entero, que consta de 2 filas y 3 columnas.
Accedemos a cada uno de sus elementos de la forma que
se indica a continuación:
matriz[0,0]  Elemento correspondiente a la primera
fila, primera columna.
matriz[0,1]  Elemento correspondiente a la primera
fila, segunda columna.
matriz[0,2]  Elemento correspondiente a la primera
fila, tercera columna.
matriz[1,0]  Elemento correspondiente a la segunda
fila, primera columna.
matriz[1,1]  Elemento correspondiente a la segunda
fila, segunda columna.
matriz[1,2]  Elemento correspondiente a la segunda
fila, tercera columna.
Matriz de 6 elementos (2 filas por 3 columnas):

49
Tema 3: Programación estructurada

ponte a prueba

¿Qué tipo de datos es el tipo ¿Cuántas columnas contendrá la


enumerado? siguiente matriz?
int [,] matriz = new bool[2,3];
a) Compuesto
b) Simple a) 2
b) 3
¿Cómo puedo acceder al dato 2 si c) 6
tenemos el siguiente array?
d) N
 inguna de las respuestas es
int[] a = new int[] {1, 2, 3};
correcta
a) a[1]
b) a[0]
c) a[2]
d) Ninguna de las opciones es
correcta

3.6.  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.

Instrucción simple (IF): su estructura sería de la siguiente


forma:

Instrucción simple (IF)

SI CONDICIÓN ENTONCES:
INSTRUCCIONES_1 no
FIN SI; CONDICIÓN

si

INSTRUCCIONES 1

FIN

50
Programación

Instrucción doble (IF-ELSE)

SI CONDICIÓN ENTONCES:
INSTRUCCIONES_1; Si No
SI NO: CONDICIÓN

INSTRUCCIONES_2; Si
FIN SI;
INSTRUCCIONES 1

INSTRUCCIONES 2

FIN

En este caso, si CONDICIÓN ES CIERTA, ejecutaremos lo que


hay en INSTRUCCIONES_1 y saltaremos hasta el FIN SI.

Sin embargo, si CONDICIÓN ES FALSA, ejecutaremos lo que


hay en INSTRUCCIONES_2.

CONCEPTO

En las estructuras dobles, por cada IF, debe


haber un ELSE.

Operadores lógicos

&& AND: ambas condiciones deben cumplirse


para entrar en el bloque IF.
No evalúa el operando derecho si el izquierdo
es false.

|| OR: es suficiente con que una de las condi-


ciones se cumpla para entrar en el bloque IF.
El resultado de x || y es true si x o y es true.

^ XOR: El resultado se evalúa como true si una


condición se evalúa como false y otra como
true.
Si ambas condiciones se evalúan como false
o como true, el resultado será false.

51
Tema 3: Programación estructurada

Ejemplo AND lógico condicional &&:

SI CONDICIÓN_1 && CONDICIÓN_2 ENTONCES:

FIN SI;

Si condición_1 y condición_2 son true, el resultado se eva-


lúa como true. Si alguna condición es false, el resultado se
evalúa como false.

Ejemplo OR lógico condicional ||:

SI CONDICIÓN_1 || CONDICIÓN_2 ENTONCES:

FIN SI;

Si condición_1 es true o condición_2 es true, el resultado


se evalúa como true.

Ejemplo XOR exclusivo:

SI CONDICIÓN_1 ^ CONDICIÓN_2 ENTONCES:

FIN SI:

CONDICIÓN_1 CONDICIÓN_2 RESULTADO

false false False

false true True

True false true

true true false

Sentencia Switch (o de selección múltiple)

Es una instrucción de selección que elige una sola acción


de una lista de opciones en función de una coincidencia de
distintos patrones con la expresión.

52
Programación

using System;

public class Example


{
public static void Main()
{
int var = 1;

switch (var)
{
case 1:
[Link]("Caso 1");
break;
case 2:
[Link]("Caso 2");
break;
default:
[Link]("Otro caso");
break;
}
}
}
// La salida mostrada será Caso 1 porque nuestra variable ‘var’
contiene el valor 1.

La cláusula default es optativa en esta estructura.

ponte a prueba

Según el siguiente código, ¿cuándo imprimimos la cadena “Hola a todos”?

If (a && b) {[Link](“Hola a todos”);}

a) Cuando la condición a se cumpla.


b) Cuando la condición b se cumpla.
c) Cuando se cumpla la condición a y b.
d) Cuando se cumpla a, pero no b.

Según el siguiente código, ¿qué sucede?

int a=1;
if (a>0) {[Link](“Estamos en el if”);}
else{
[Link](“Estamos en el else”);}
}

a) Escribimos por pantalla “Estamos en el if”.


b) Escribimos por pantalla “Estamos en el else”.
c) No se ejecuta ni el if ni el else.
d) La variable a no está correctamente declarada.
53
Tema 3: Programación estructurada

3.7.  Estructuras de repetición


Las estructuras de repetición siempre se ejecutan median-
te el uso de bucles. Estos son los que permiten que una o
varias líneas de código se ejecuten de forma repetida. Se
van a ir repitiendo mientras que se cumpla una determina-
da condición de salida.

Existen diferentes estructuras de repetición:

Mientras (While)

Mientras que se cumpla una condición, el código incluido


dentro del bucle se repite. La condición se evalúa al prin-
cipio, por lo que puede que no llegue a ejecutarse nunca.

Mientras CONDICIÓN Hacer


CONDICIÓN
Instrucción_1;
Instrucción_2; verdadero
…;
INSTRUCCIONES
Instrucción_N;
ModificarCondición; falso
FinMientras;
RESTO DEL
PROGRAMA

Hacer… mientras (Do… while)

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.

Hacer
INSTRUCCIONES
Instrucción_1;
Instrucción_2; verdadero
…;
CONDICIÓN
Instrucción_N;
ModificarCondición; falso
Mientras CONDICIÓN;
RESTO DEL
PROGRAMA

Para

Mientras que se cumpla una condición, el código incluido


dentro del bucle se repite tantas veces como indique el
contador, que se irá modificando en cada sentencia. La
condición se evalúa al principio, por lo que puede que no
llegue a ejecutarse nunca.

54
Programación

Para CONDICIÓN

Instrucción1;
K=1
Instrucción2;


falso
k>N
InstrucciónN;

ModificarCondición; verdadero

Índice = v (k)

Instrucciones

K = k+1

Foreach

Ejecuta una instrucción o bloque de instrucciones para


cada elemento de ciertas estructuras de datos como arrays
o listas.
EJEMPLO 1

int [] diasMes = {1, 21, 30};


foreach (int dias in diasMes) {
[Link](“Dias del mes: {0}”, dias);
// creamos una variable días de tipo entero que nos servirá para recorrer cada elemento del
array diasMes
}

EJEMPLO 2

List‹string› ListaColores = new List‹string›(); //creamos una lista de tipo string


//añadimos un color a la lista
[Link] (“Azul”);
[Link] (“Rojo”);
[Link] (“Verde”);
[Link] (“Amarillo”);
[Link] (“Morado”);

foreach (string color in ListaColores)


{
// recorremos la lista mediante la variable string color
[Link] ( color );
}

55
Tema 3: Programación estructurada

ponte a prueba

Según el siguiente código, ¿ejecutaríamos el código de la salida por


pantalla?

int a=0; int b=0;


while (a>0 || b==0) {[Link](“Hola Ilerna”); b = b
- 1;}

a) Sí, con que se cumpla una condición es suficiente.


b) No, porque se deben cumplir ambas condiciones.
c) No, porque no se cumple la condición a>0.
d) Ninguna de las respuestas es correcta.

¿Cuántas veces ejecutaríamos un bucle do-while?


a) Depende de la condición.
b) Mínimo, una vez.
c) Cero o más veces.
d) Mínimo, dos veces.

¿Es correcto el siguiente código?

int [] array = {1,2,3};


for (i = 0; i < [Link]; i++) { [Link](“HOLA
MUNDO!!!”); }

a) Sí. Entra en el bucle for y muestra los datos 1,2 y 3.


b) No. La variable i no está declarada.
c) Sí. Entra en el bucle y muestra por pantalla HOLA MUNDO!!!
d) Ninguna de las respuestas es correcta.

56
Programación

3.8.  Estructuras de salto


Las estructuras de salto son todas aquellas que detienen
(de diferentes formas) la ejecución de alguna de las sen-
tencias de control de nuestro programa.

break Se encuentra al final de la sentencia switch. Interrumpe el bucle indi-


cando que debe continuar a partir de la siguiente sentencia después del
bloque del ciclo.

El control se devuelve a la instrucción que haya a continuación de la


instrucción finalizada.

continue Se utiliza en sentencias repetitivas con bucles for, foreach, while y do…
while. Transfiere el control a la siguiente iteración.

for (int i = 1; i <= 10; i++)


{
if (i < 9)
{
continue;
}
[Link](i);
}

[Link]();
// Mostraría por pantalla 9 y 10

return Esta estructura de salto obliga a que finalice la ejecución de una deter-
minada función. Normalmente se utiliza para devolver el control a la
función de llamada.

static double CalculaArea(int radio)


{
double area = radio * radio * [Link];
return area;
}
//Devuelve la variable local área como un valor de tipo
entero

57
Tema 3: Programación estructurada

ponte a prueba

Según el siguiente código, ¿qué saldrá por pantalla?

int caseSwitch = 1;
switch (caseSwitch)
{
case 1:
[Link](“Case 1”);
break;
case 2:
[Link](“Case 2”);
break;
default:
[Link](“Default case”);
break;
}

a) Case 1
b) Case 2
c) Default case
d) caseSwitch

3.9.  Tratamiento de cadenas


Una cadena es un objeto de tipo string. Para la repre-
sentación de cadenas de caracteres se utiliza la palabra
reservada string.

En C#, la representación del tipo de datos sería de la si-


guiente forma:

string frase = "buenos días";


[Link]("El caracter de la posición 5, es {0}", frase [5]);
// La salida por pantalla sería el carácter ‘s’ que está en la posición 5

Siempre que queramos escribir combinaciones alfanumé-


ricas, en nuestro código, irán entre comillas dobles (“”), ya
que el compilador las va a tomar como un tipo string. Estas
variables string se pueden inicializar a partir de una tabla
de caracteres creada previamente.

58
Programación

char []letras = {‘h’, ‘o’, ‘l’, ‘a’};


string frase = new string(letras);
char caracter = frase [0];
/* Creamos un array de caracteres llamado letras.
A continuación, vamos a crear un objeto de tipo string con la palabra reservada new.
Con esta palabra reservada, creamos una nueva instancia de tipo string (frase).
Por último, asignamos el primer valor de nuestro string a la variable carácter.
En este caso, el valor será ‘h’ */

new

El operador new crea una nueva instancia de un tipo.

La palabra new crea un objeto tipo string al que pasamos el


parámetro letras como una tabla de caracteres.

A continuación, vamos a ver los principales métodos de


los que dispone string:

Length Devuelve el número de caracteres.

ToCharArray() Convierte un string en array de caracteres.

SubString() Extrae parte de una cadena. Método que puede ser sobrecargado
indicando su inicio y su fin: SubString (int inicio) o SubString (int
inicio, int tamaño).

CopyTo() Copia un número de caracteres especificados a una determinada


posición del string.

CompareTo() Compara la cadena que contiene el string con otra pasada por
parámetro.
Devuelve un entero que indica si la posición de esta instancia es
anterior, posterior o igual que la posición del string.

Contains() Si la cadena que se le pasa por parámetro forma parte del string,
devuelve un booleano.

IndexOf() Si aparece un carácter especificado en el string, devuelve el índice de


la posición de la primera vez que aparece. Devuelve -1 si el carácter
no se encuentra en la cadena.

Insert() Inserta una cadena de caracteres en una posición concreta del string.

Trim() Quita todos los espacios en blanco del principio y el final de la cadena
de caracteres.

59
Tema 3: Programación estructurada

Replace() Devuelve una cadena, donde se ha sustituido un carácter por otro.

Remove() Devuelve una cadena donde se ha eliminado un número de caracte-


res especificado.

Split() Ofrece la posibilidad de separar en varias partes una cadena de


caracteres.

ToLower() Devuelve una cadena convertida en mayúsculas.

ToUpper() Devuelve una cadena convertida en mayúsculas.

En el siguiente link, se puede consultar la información


de los métodos string:

BUSCA EN LA WEB

[Link]
[Link]?view=netcore-3.1#methods

ponte a prueba

¿Qué mostrará por pantalla el siguiente


código?

int[] array = { 1, 2, 3 };
[Link]([Link]);

a) 3
b) 1,2,3
c) 1
d) 2

La función Trim() elimina cualquier carácter


del principio y el final de la cadena.
a) Verdadero
b) Falso

60
Programación

3.10.  Depuración de errores


Una vez que llegamos a la etapa de depuración de nues-
tro 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 y que no tienen
ningún error de sintaxis, pero que no se ejecutarán. Por
ejemplo, se podría escribir correctamente una línea de
código para abrir un archivo, pero si el archivo no existe,
la aplicación no puede llevar a cabo la apertura de ese
archivo, por lo que se detendrá la ejecución.
• Lógicos: son aquellos errores que dan resultados erróneos,
diferentes a los esperados o no deseados, 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.
Cuando queramos depurar errores, tenemos la opción,
en cualquier momento de nuestro programa, de poner un
punto de interrupción en una determinada línea de código.
Para ello, presionamos F9.

Si queremos ejecutar la aplicación en el depurador de Visual


Studio, podemos hacerlo presionando F5. La aplicación se
detiene en la línea y podremos examinar cuánto valen las
variables para ir realizando su seguimiento, o podemos
comprobar cuándo finalizan los bucles, entre otras cosas.
Para depurar el código, teclearemos F10 (paso a paso).

• Errores de compilación: estos errores impiden la eje-


cución de un programa. Inicialmente se compila el
programa, y, si el compilador encuentra cualquier cosa
que no entiende, lanza un error de compilación. Casi to-
dos los errores que ocasiona el compilador se producen
mientras escribimos el código.

61
Tema 3: Programación estructurada

• Errores en tiempo de ejecución: aparecen mientras se


ejecuta el programa, normalmente cuando se pretende
realizar una operación que no lleva a ninguna solución,
como, por ejemplo, cuando se pretende dividir por cero.

• Errores lógicos: impiden que se lleve a cabo lo que se


había previsto. El código se puede compilar y ejecutar sin
problema, pero, en el caso de que se compile, devuelve
algo que no era la solución que se esperaba. El programa
no da error cuando se ejecuta en el inicio, por lo que su
corrección es más difícil. Tenemos que encontrar el error
en un programa que sí funciona, pero que funciona de
forma diferente a la que debería.

ponte a prueba

¿Qué errores podemos encontrar El programador está realizando un


en la etapa de la depuración de un programa en el cual quiere introducir
programa? dos datos enteros. Uno, que sea la
base y otro que sea el exponente para
a) Errores lógicos
realizar la operación potencia. Intro-
b) Errores de compilación duce como base el número 5 y como
c) Errores en tiempo de ejecución exponente 2. El resultado es 10. ¿Qué
tipo de error le está dando a nuestro
d) Todas las respuestas son correctas
programador?
a) De compilación
b) Lógico
c) De ejecución
d) N
 o hay errores. El programa es
correcto

62
Programación

3.11.  Documentación de
programas
Una vez que finaliza nuestro proceso de compilación y eje-
cució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.

Los ficheros que entreguemos que formen parte del


proyecto deben estar testeados y tener un correcto fun-
cionamiento. Habrá que solventar los errores descritos
anteriormente.

summary

La etiqueta <summary> debe usarse para describir un tipo


y para agregar información adicional dentro de nuestro
código. Gracias a herramientas de documentación como
GhostDoc y Sandcastle, creamos hipervínculos internos a
las páginas de documentación de los elementos de código:

BUSCA EN LA WEB

[Link]
programming-guide/xmldoc/cref-attribute

<summary>description</summary>

63
Tema 3: Programación estructurada

namespace ConsoleApp33
{
// Implementamos los métodos a utilizar
class Program
{
/// <summary>
///
/// Main es el método principal de nuestra clase
///
/// </summary>

static void Main(string [] args)


{
// Voy a realizar un programa y a documentarlo
char []letras = { ‘h’, ‘o’, ‘l’, ‘a’};

string frase = new string(letras);


char caracter = frase [0];
//salida por pantalla
[Link](caracter);

[Link]();
}
}
}

<?xml version=”1.0”?>
<doc>
<assembly>
<name>ConsoleApp33</name>
</assembly>
<members>
<member name=”M:[Link]([Link][])”>
<summary>

Main es el método principal de nuestra clase.

</summary>
</member>
</members>
</doc>

64
Programación

3.12.  Entornos de
desarrollo de programas
Una vez que diseñamos un programa, podemos
denominar entorno de desarrollo integrado
(IDE o integrated development environment)
al entorno de programación que hemos uti-
lizado para su realización: editor de código,
compilador, depurador e interfaz gráfica (GUI
o graphical user interface).

Los IDE son utilizados por distintos lenguajes


de programación como C++, PHP, Python,
Java, C#, Visual Basic, etcétera.

A modo de ejemplo, podemos señalar algunos


entornos integrados de desarrollo como
Eclipse, Netbeans, Visual Code o Visual Studio,
entre otros.

Los IDE deben cumplir con una serie de carac-


terísticas para su correcto funcionamiento,
como, por ejemplo:

• Son multiplataforma.
• Actúan como soporte para diferentes len-
guajes 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.

Las diferentes ventajas que ofrecen los IDE ponte a prueba


son:

• Presentan una baja curva de aprendizaje. ¿Qué ventajas nos ofrecen los
IDE?
• Son de uso óptimo para usuarios que no son
expertos. a) Una baja curva de aprendizaje.
b) Crear un proyecto desde cero.
• Formatean el código.
c) Un intelligence que nos marca
• Usan funciones para renombrar funciones y qué funciones podemos utilizar.
variables. d) Todas las opciones son correctas.
• Permiten crear proyectos.
• Muestran en pantalla errores y warnings.

65
4
PROGRAMACIÓN MODULAR
Programación

Hasta ahora hemos estudiado el desarrollo de un programa


como una unidad compuesta por líneas que se ejecutan
de forma secuencial, sin embargo, un acercamiento más
próximo a la realidad sería el paradigma conocido como
programación modular.
Introducción a la
programación modular
[Link]/tj9NOGBWRSQ
4.1.  Concepto
La 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.

Un subproblema se denomina módulo, y es una parte del


problema que se puede resolver de manera independiente.

4.2.  Ventajas e inconvenientes


Enumeramos las ventajas e inconvenientes más relevantes
en el trabajo de diseño modular:

• Ventajas:
– Facilita el mantenimiento, la modificación y la docu-
mentación.
– Escritura y testing.
– Reutilización de módulos.
– Independencia de fallos.
• Inconvenientes:
– ¿Cuánto hay que dividir nuestro problema?
– Aumenta el uso de memoria y el tiempo de ejecución.

ponte a prueba

¿Qué ventajas nos proporciona la programa-


ción modular?
a) Facilita el mantenimiento.
b) Facilita el testing.
c) Podemos reutilizar los módulos.
d) Todas las opciones son correctas.

67
Tema 4: Programación modular

4.3.  Análisis descendente (top


down)
El diseño descendente es una técnica que permite diseñar
la solución de un problema con base en la modulari-
zación o segmentación, dándole un enfoque de arriba
hacia abajo (top down). Esta solución se divide en módu-
los que se estructuran e integran jerárquicamente.

Este diseño se basa en el principio divide y vencerás:

• Va de lo más general a lo más específico.


• Se basa en una representación por niveles: el primer nivel
resuelve el problema, y los sucesivos van depurando el
primero.
• El programa, por tanto, tendrá una estructura de árbol.

PROBLEMAS

MÓDULO 1 MÓDULO 2 MÓDULO 3

ponte a prueba

¿En qué consiste el diseño top down?


a) Empezar desde los módulos más pequeños
hasta el módulo mayor.
b) Dividir un gran problema en subproblemas.
c) Inventar el código.
d) Ninguna de las opciones es la correcta.

68
Programación

4.4.  Modulación de programas.


Subprogramas
Podemos denominar los módulos como subprogramas, y
estos como las diferentes partes del problema que puede
resolverse de forma independiente. Los módulos, al ser
independientes unos de otros, permiten que podamos cen-
trarnos en una de sus partes (sin tener en cuenta el resto).
También ofrecen la posibilidad de que se puedan utilizar
las soluciones obtenidas en otras partes del programa.

Cada módulo codificado dentro del programa como sub-


programa se puede definir como una parte del código
independiente, que realiza una tarea asignada.

A continuación, vamos a ver a modo de ejemplo un progra-


ma que devuelva la nota media de un alumno:

//Declaramos el array de enteros que almacenará las notas del alumno


int [] notas = new int [ 5 ];
/*Mediante un bucle for recorremos el array almacenando
en su interior notas que le pedimos al usuario por teclado
*/
for ( int i = 0 ; i < notas . Length ; i ++) {
Console . Write ( “Introduce la nota en la posición “ + ( i + 1 )+ “:
“ );
notas [ i ]= Convert . ToInt32 ( Console . ReadLine ());
}

//Declaramos la variable en la que almacenaremos la media


int notaMedia = 0;
/* Mediante una nueva estructura for, vamos recorriendo el
array y vamos acumulando las notas
*/
for ( int i = 0 ; i < notas . Length ; i ++)
{
notaMedia += notas [ i ];
}
//Finalmente, dividimos el sumatorio por el número de notas
notaMedia /= notas . Length;
//Mostramos por pantalla la media obtenida
Console . WriteLine ( “Su nota media es “ + notaMedia );
Console . ReadKey ();

Si observamos bien el código, podemos comprobar que


existen dos partes bien diferenciadas: por un lado, tenemos
la lectura de las notas que el alumno debe introducir, y, por
otro lado, el cálculo de la media.

69
Tema 4: Programación modular

PROBLEMAS

LECTURA NOTAS CÁLCULO MEDIA

Se puede comprobar perfectamente que nuestro programa


podría estar formado por dos módulos independientes de
la siguiente manera:

• Función Main
Todos los programas desarrollados en C# tienen una
función principal denominada main() que se ejecuta al
iniciar el programa. Esta función se encarga de gestionar
el flujo de ejecución, llamando a los diferentes módulos
si es necesario.
En esta parte, el usuario va introduciendo las notas de los
alumnos. Mostraremos por pantalla la nota media.

static void Main ( string [] args)


{
int [] notas = new int [ 5 ];
for ( int i = 0 ; i < notas . Length ; i ++) {
Console . Write ( “Introduce la nota en la posición “ + ( i + 1 )+ “:
“ );
notas [ i ]= Convert . ToInt32 ( Console . ReadLine ());
}
Console . WriteLine ( «Su nota media es « + calcularMedia ( notas ));
Console . ReadKey ();
}

• Función calcularMedia().
Creamos esta función en la división de nuestro problema.
Esta función recibe las notas introducidas por los alum-
nos y devuelve la nota media de las mismas.

public int calcularMedia ( int [] newarray ){


int notaMedia = 0;
for ( int i = 0 ; i < newarray . Length ; i ++){
notaMedia += newarray [ i ];
}
notaMedia /= newarray . Length;
return notaMedia;
}

70
Programación

Podemos comprobar que en C# los programas se dividen


en subprogramas, denominados funciones o métodos.
Estas funcionan de forma similar a una caja negra, es decir,
el programa principal solo debe conocerlas para llamarlas
por su nombre, los parámetros que reciben (las variables
que debemos enviar) y lo que devuelven como resultado.
Por ejemplo, nuestra función calcularMedia recibe un
array de notas y devuelve un entero con la media.

4.5.  Llamadas a funciones


(métodos). Tipos y funcionamiento
Funciones en C#

Los métodos con los que trabajamos en C# se denominan


funciones.

De hecho, cuando nos referimos a una función, un método


o un subprograma en C#, nos estamos refiriendo al mismo
concepto.

Las funciones se pueden definir como un conjunto de ins-


trucciones, delimitadas por llaves, que tienen un nombre y
son de un tipo específico.

Sintaxis:

Modificadores Tipo NombreFuncion (Parámetros de entrada ){


Código de la función
Return expresión;
}

Veamos paso a paso el significado de cada parte de la


función:

• Modificadores: conjunto de palabras reservadas que


modifican o aplican propiedades a la función. Los más
comunes son los modificadores de acceso: Public, Priva-
te, Protected, Internal:
– Public: el acceso no está restringido.
– Private: el acceso está limitado a la misma clase.
– Protected: el acceso está limitado a la clase contene-
dora o a los tipos derivados de la clase contenedora.
– Internal: el acceso no está restringido, siempre y cuan-
do sea dentro del mismo ensamblado. Un ensamblado
es un conjunto de tipos que se compilan para obtener
una misma solución. Si no indicamos un modificador,
por defecto, nuestros métodos tendrán un nivel de ac-
cesibilidad internal.

71
Tema 4: Programación modular

• Tipo: las funciones, al igual que ocurría con las variables,


poseen un tipo, es decir, el dato que devuelven es de un
tipo determinado.
• Nombre de la función: es el identificador de la función,
lo usaremos para referenciarla, del mismo modo que
usábamos los nombres de las variables.
• Parámetros de entrada: una lista de las variables que re-
cibirá la función en el momento de su llamada. Es posible
que una función no requiera parámetros.
• Return: si nuestro método está tipado, es obligatorio que
devuelvan un valor del tipo adecuado. Utiliza la palabra
reservada return.

Veamos cómo quedaría utilizando el mismo ejemplo que


propusimos en el apartado anterior:

PARÁMETROS
TIPO
DE ENTRADA

Nombre
MODIFICADOR
Función

public int calcularMedia ( int [] newarray ){


int notaMedia = 0;
for ( int i = 0 ; i < newarray . Length ; i ++){
notaMedia += newarray [ i ];
}
CÓDIGO notaMedia /= newarray . Length;
FUNCIÓN
return notaMedia;
} VALOR DE
RETORNO

Mediante el uso de parámetros, se permite la comunica-


ción de las diferentes funciones con el código.

Métodos no tipados. Void

Los métodos no tipados son aquellos que realizan una


tarea específica y que pueden recibir parámetros, pero no
necesitan devolver un valor.

Para referenciar que ese método no nos devuelve un valor,


utilizamos la sentencia void.

Modificadores void NombreProcedimiento (Parámetros de entrada ){


//Código del procedimiento
}

72
Programación

CÓDIGO EJEMPLO:

static void Par (int b)


{
int x;
x = (b % 2);
if (x == 0)
{
[Link](«\nEs par»);
} else
{
[Link](«\nEs impar»);
}
}

EJERCICIO 1

Realice un programa modular donde se calcule la suma de los dígitos de un número


que el usuario introduzca por pantalla.

Por ejemplo, si el usuario introduce el número 369, el resultado sería: 3+6+9=18

Solución

public static int Calcular( int a )


{
string cad = [Link](a);
// Convertimos el parámetro a en string
int sum = 0;
for (int i = 0; i < [Link]; i++)
// recorremos el número y vamos tomando las subcadenas (dígitos) del mismo
con la función Substring almacenándolo en una variable entera para ir haciendo la
suma de cada uno de sus dígitos
sum += Convert.ToInt32([Link](i,1));
return sum;
}
public static void Main()
{
int numero;
[Link](“Introduzca el número: “);
numero = Convert.ToInt32( [Link]() );
[Link](Calcular(numero));
}

73
Tema 4: Programación modular

EJERCICIO 2

Realice un programa modular donde el usuario introduzca dos números enteros y se


intercambien de posición.

5 10

10
5

10
5

5 10

Solución

public static void intercambio(ref int numero1, ref int numero2)


{
int aux; // creamos una variable auxiliar para guardar temporalmente en número
1

aux = numero1;
numero1 = numero2;
numero2 = aux;
}
public static void Main()
{
int numero1,numero2;

[Link](“Introduzca el primer número”);


numero1= Convert.ToInt32([Link]());

[Link](“Introduzca el Segundo número “);


numero2= Convert.ToInt32([Link]());

// pasamos los parámetros por referencia con la palabra reservada ref (veremos el
paso de parámetros en la siguiente sección)
intercambio( ref numero1, ref numero2 );
[Link](numero1, numero2 );
}

74
Programación

Paso de parámetros. Paso por valor y paso por referencia

En C#, podemos distinguir dos tipos de paso de paráme-


tros diferentes:

• Por valor o copia.


• Por referencia.

Paso de parámetros por valor

Cuando ejecutamos una función que tiene parámetros pas-


ados por valor, se realiza una copia del parámetro que se ha
pasado, es decir, que todas las modificaciones y/o cambios
que se realicen se están haciendo en esta copia que se ha
creado. El original no se modifica, de manera que no se
altera su valor en la función.

MEMORIA

variable

número

75
Tema 4: Programación modular

Paso de parámetros por referencia

Sin embargo, cuando ejecutamos una función que tiene


parámetros pasados por referencia, todas aquellas modi-
ficaciones que se realicen en la función van a afectar a sus
parámetros, ya que se trabaja con los originales.

MEMORIA

número

CÓDIGO EJEMPLO:

static void Main(string[] args)


{
int a = 0;
metodo(ref a);
/* cuando pasamos por valor la variable ‘a’ al método,
tanto la variable ‘a’ como la variable ‘numero’ ocupan
el mismo espacio de memoria, pero lo que el valor se so-
breescribirá.
En este caso, inicialmente, tenemos el valor 0, pero al
asignar a ‘numero’ el valor 1, éste sobreescribe al 0 */
[Link](a);
}
static void metodo(ref int numero) {
numero = 1;
}

params, in y out

Cuando trabajamos con la palabra clave ‘params’ estamos


especificando un paso por valor. En este caso, el tipo de
parámetro debe ser una matriz unidimensional (array).

76
Programación

No se permiten pasar más parámetros después de la pal-


abra clave ‘params’ en una declaración de método. Si el
tipo declarado del parámetro ‘params’ no es un vector, se
produciría un error (Error del compilador CS0225).

CÓDIGO EJEMPLO:

public static void miMetodo(params int[] list)


{
for (int i = 0; i < [Link]; i++)
{
[Link](list[i] + “ “);
}
[Link]();
}
static void Main()
{

int[] miArrayInt = { 5, 6, 7, 8, 9 };
miMetodo(miArrayInt);
}

La palabra clave ‘in’ sirve para pasar parámetros por refe-


rencia. Las variables que se han pasado como argumentos
con la palabra clave ‘in’ deben inicializarse antes de pasarse
en una llamada de método o función. Si pasamos un pa-
rámetro con ‘in’, este no puede ser modificado dentro del
método.

CÓDIGO EJEMPLO:

0 referencias
static void Main()
{
int soloLectura = 44;
ejemplo(soloLectura);
[Link](soloLectura); // el valor es 44

1 referencia
static void ejemplo(in int number)
{
// error CS8331
number = 19;
}
[ ] (parámetro) in int number

No se puede asignar a variable “in int” porque es una variable readonly.

77
Tema 4: Programación modular

La palabra clave ‘out’ también sirve para pasar parámetros


por referencia. No es necesario iniciar la variable antes de
pasarla al método.

CÓDIGO EJEMPLO:

static void Main()


{
int entera;
OutEjemplo(out entera);
[Link](entera); // la salida por pantalla
será 40

static void OutEjemplo(out int numero)


{
numero = 40;
}

ponte a prueba

Las funciones deben tener un tipo asociado.


a) Verdadero
b) Falso

¿Cuál es la salida del siguiente código?

static void Main(string[] args)


{
int a = 10;
int b = 5;
[Link](suma(a,b));
}
static int suma(int x,int y) { return x + y; }

a) 15
b) 10
c) 5
d) La función no está bien construida

Cuando realizamos un paso por valor de una variable, creamos dos posi-
ciones de memoria distintas.
a) Verdadero
b) Falso

78
Programación

4.6.  Ámbito de las llamadas a


funciones
Hasta ahora, hemos trabajado tanto con variables dentro
de nuestro Main, con variables creadas dentro de nuestros
métodos y con el paso de parámetros. Veamos cuál es el
ámbito o el alcance de estas variables.

Variables globales

Una variable global es creada fuera de nuestro Main y fuera


de cualquier método. Podemos acceder a ella en cualquier
momento de nuestro programa.

class Program
{
static int n = 10; // Variable global
public static void CambiaValorN()
{
n++;
}
public static void Main()
{
[Link]("n vale {0}", n); // el valor de n es 10
CambiaValorN();
[Link]("Ahora n vale {0}", n); // el valor de n es 11
}
}

En términos generales, debemos intentar construir nues-


tros programas con variables locales. Así hacemos que
cada parte del programa trabaje con sus propios datos, y
ayudamos a evitar que un error en un trozo de programa
pueda afectar al resto. Si modificamos una variable global
en cualquier punto del programa, podemos perdernos en
su flujo.

La forma correcta de pasar datos entre distintos métodos


no es a través de variables globales, sino usando los pa-
rámetros de cada función y los valores devueltos (como
hemos visto en ejemplos anteriores con el paso de pará-
metros por valor y por referencia).

Variables locales

Las variables que se declaran dentro de un método (o de


una función), y que, por tanto, solo este fragmento de có-
digo las conocerá, son las llamadas variables locales. No se
podrán usar desde ningún otro método del programa.

79
Tema 4: Programación modular

public static int Potencia(int nBase, int nExponente)


{
int temporal = 1; // Valor local de mi método Potencia
for (int i = 1; i <= nExponente; i++) // Multiplico “n” veces
temporal *= nBase; // Para aumentar el valor temporal
return temporal; // Al final, obtengo el valor que buscaba
}

public static void Main()


{
int num1, num2; // variables locales de mi método Main
[Link](“Introduzca la base: “);
num1 = Convert.ToInt32([Link]());
[Link](“Introduzca el exponente: “);
num2 = Convert.ToInt32([Link]());
[Link](“{0} elevado a {1} vale {2}”, num1, num2,
Potencia(num1, num2));
}

En este caso, las variables temporal e i son locales a la


función potencia. Para Main no existen. Si en Main intentá-
ramos hacer i=10, obtendríamos un mensaje de error.

Lo mismo ocurre con las variables, num1 y num2, que son


locales para Main. Desde la función potencia no podemos
acceder a su valor (ni para leerlo ni para modificarlo).

En este ejemplo, no encontramos ninguna variable global.

Conflictos de nombres en las variables

¿Qué ocurre si trabajamos con la misma variable global en


dos métodos diferentes?

static int n = 7;

public static void CambiaN()


{

n++;

public static void Main()


{
[Link](“n vale {0}”, n); // el valor será 7
CambiaN();
[Link](“Ahora n vale {0}”, n); // el valor cambiará a 8
}

80
Programación

En este ejemplo, vemos que tanto en el método CambiaN


como en el método Main estamos trabajando con una va-
riable global.

Ahora veamos otro ejemplo:

static int n = 7;

public static void CambiaN()


{
int n = 10;
n++;
[Link](“Ahora n vale {0} dentro del método CambiaN”, n);

public static void Main()


{
[Link](“n vale {0}”, n);
CambiaN();
[Link](“Ahora n vale {0}”, n); // el valor que estamos
sacando de n es el de la variable global
}

En el siguiente ejemplo, estamos trabajando con dos varia-


bles ‘n’ distintas. Hemos creado una variable local ‘n’ dentro
del método CambiaN, en el cual modificamos su valor asig-
nando 10 e incrementando después.

En Main, estamos trabajando con la variable global creada


al inicio, por lo que el valor no varía siendo 7.

En este último ejemplo, vemos que podemos llegar a tener


conflicto de variables a la hora de trabajar con variables
globales (el ejemplo son pocas líneas de código. Si traba-
járamos con un proyecto de cientos de líneas, la confusión
podría ser mayor). Por ello, se recomienda trabajar con
variables locales y paso de parámetros entre métodos.

81
Tema 4: Programación modular

ponte a prueba

Una variable local puede ser accedida desde cualquier función o método.
a) Verdadero.
b) Falso.

¿Qué muestra por pantalla el siguiente código?

public static string miVar=””;


static void Main(string[] args)
{
int a = 10;
int b = 5;
[Link](suma(a,b));
[Link](miVar);
}
static int suma(int x,int y) { miVar = “HOLA ILERNA”; re-
turn x + y; }

a) 15.
b) HOLA ILERNA.
c) 15
HOLA ILERNA.
d) El paso de parámetros a la función no es correcto.

Según el siguiente código, ¿qué ocurrirá con la función?

public static float Mayor (float num1, float num2)


{
if (num1 > num2)
return num1;
else
return num2;
}

a) La función nos devolverá dos valores: num1 y num2.


b) Es incorrecto porque hay dos return.
c) La función nos devolverá num1 si es mayor que num2 o num2 si es mayor
que num1.
d) Ninguna de las opciones es correcta.

82
Programación

4.7.  Prueba, depuración y


comentarios de programas
Una vez tenemos terminado nuestro programa con su
código ya implementado, es momento de probarlo para
comprobar que no tiene fallos y, sobre todo, que su funcio-
namiento es correcto. En muchos casos no existen errores,
pero el programa no realiza la tarea que debería cuando se
ejecuta.

Por esto es muy conveniente que nuestro programa tenga


comentarios, al menos, en todo lo importante que realiza.
De esta manera, nos será más fácil manejarnos con él.

Podemos encontrarnos errores en nuestro código, tanto


sintácticos como semánticos, que pueden ir apareciendo
sin esperarlo. La mayoría de los lenguajes de programación
disponen de una serie de herramientas que nos van a servir
para tratar estos errores y conseguir solucionarlos.

83
Tema 4: Programación modular

Por ejemplo, el programa Visual Studio cuenta con un menú


Depurar que permite acceder a las herramientas que dis-
pone el depurador. El C#, además, nos facilita unas técnicas
propias para controlar diferentes situaciones en las que se
produzcan errores en tiempo de ejecución.

Cuando ponemos una aplicación en modo depuración, Visual


Studio tiene la posibilidad de visualizar, línea a línea (F11),
nuestro código para analizarlo de forma más detallada.

Cuando ejecutamos un programa, podemos dividir el pro-


ceso en varias partes:
• Compilación
• Vinculación
• Ejecución

84
Programación

Veamos cómo funcionan cada una de estas etapas:

• Compilación
Mientras vamos escribiendo un determinado programa,
el entorno de desarrollo de C# va haciendo comproba-
ciones exhaustivas para exponer los errores que podrían
persistir en el código. Estos errores aparecen subrayados
conforme escribimos las distintas instrucciones, y son
denominados errores de compilación. Algunos ejem-
plos serían la falta de un punto y coma, una variable no
declarada, etcétera.
Una vez que estos errores se corrigen, podríamos decir
que el programa se va a compilar y va a pasar a ejecutar-
se, aunque no sabemos todavía si va a realizar la función
exacta para la que ha sido diseñado.
• Vinculación
Debemos señalar que todos los programas hacen uso de
bibliotecas y, además, algunos utilizan clases diseñadas
por el programador. Las clases se vinculan cuando el pro-
grama comienza a ejecutarse, aunque son los IDE los que
comprueban el programa a medida que se va escribiendo
para intentar garantizar que todos los métodos que se in-
voquen existan, y que coincidan con su tipo y parámetros.
• Ejecución
Si hemos conseguido llegar a la fase de ejecución signifi-
ca que nuestro programa ya no tiene errores, pero todavía
no sabemos si el resultado es el correcto. Los errores ló-
gicos son los más complicados de detectar. Estos pueden
producir cambios inesperados, por lo que debemos co-
menzar con un proceso de depuración en el que vamos a ir
comprobando, paso a paso, cómo va a funcionar nuestro
programa. Así, nos proporcionará el resultado deseado.

ponte a prueba

Podemos poner un punto de interrupción en


nuestros programas y depurar línea a línea.
a) Verdadero
b) Falso

85
Tema 4: Programación modular

4.8.  Concepto de librerías


Cuando hablamos de librerías nos referimos a archivos
que nos permiten llevar a cabo diferentes acciones y tareas
sin necesidad de que el programador se preocupe de cómo
están desarrolladas, solo debe entender cómo utilizarlas.

Las librerías en C# permiten hacer nuestros programas más


modulares y reutilizables, facilitando además crear progra-
mas con funcionalidades bastante complejas.

Cuando compilamos nuestro programa, solamente se


comprueba que se ha llamado de manera correcta a las
funciones que pertenecen a las diferentes librerías que nos
ofrece el compilador, aunque el código de estas funciones
todavía no se ha insertado en el programa. Va a ser el enla-
zador o linkador el que realice esta inserción y, por tanto,
será el encargado de completar el código máquina con la
finalidad de obtener el programa ejecutable.

.obj

.obj

Enlazador .exe

.obj

.lib

Una vez que hemos obtenido el código fuente, debemos


comprobar que no se producen errores en tiempo de
ejecución. Si los hubiera, debemos depurar el programa.
Encontrar cuál es la causa que produce un error en tiempo
de ejecución es, a veces, una tarea complicada, por lo que
los IDE nos proporcionan una herramienta denominada
“Depurador” que nos facilita la tarea.

Uno de los motivos por lo que es recomendable utilizar el


lenguaje de programación C# es que permite la interope-
ración con otros lenguajes, siempre que estos tengan:

86
Programación

• Acceso a las diferentes librerías a través de COM+ y ser-


vicios .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 VS2019.


Veámoslo paso a paso:
1. Creamos un proyecto nuevo como aplicación de consola.

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 de ‘Mul-


tiplicar’. Allí crearemos una función que realizará la
multiplicación de dos números.

87
Tema 4: Programación modular

4. A mi proyecto, agregaremos como referencia (botón


derecho -> referencia) mi dll con el nombre que había-
mos puesto con anterioridad ‘Operaciones’.

5. Ahora ya podemos llamar desde nuestro programa a


nuestra referencia.

88
Programación

4.9.  Uso de librerías


Una librería es un conjunto de métodos relacionados con
el mismo objetivo para poder ser reutilizado cada vez que
el programador lo desee. Para la realización de este módu-
lo, en los ejercicios prácticos, vamos a utilizar las librerías
Math para cualquier operación matemática y la librería
Random.

Vamos a explicar algunos ejemplos:

A. En este primer ejemplo vamos a calcular la potencia de


base 10 y exponente 2. Para ello debemos mirar cuáles son
los métodos que están implementados en la librería Math
y podemos comprobar que existe un método llamado Pow
que realiza las operaciones exponenciales.

Using System; //Para la utilización de dicha librería debemos de importar System


double calculo = [Link](10, 2); 

89
Tema 4: Programación modular

B. Para el siguiente ejercicio vamos a poder comprobar el


funcionamiento de varios ejemplos de Random con distin-
tos intervalos.

using System;

public class Example


{
public static void Main()
{
Random rnd = new Random();
// Declaración e inicialización de la variable aleatoria
[Link](“\n20 random integers from -100 to 100:”);
for (int ctr = 1; ctr <= 20; ctr++)
{
[Link](“{0,6}”, [Link](-100, 101));
/* El método Next calcula el número aleatorio que está dentro de un intervalo
especificado devolviendo un número menor que el valor máximo de ese intervalo.
Mostraremos los números dejando una separación de 6 unidades entre ellos */

if (ctr % 5 == 0) [Link]();
}

[Link](“\n20 random integers from 1000 to 10000:”);


for (int ctr = 1; ctr <= 20; ctr++)
{
[Link](“{0,8}”, [Link](1000, 10001));
if (ctr % 5 == 0) [Link]();
}
[Link](“\n20 random integers from 1 to 10:”);
for (int ctr = 1; ctr <= 20; ctr++)
{
[Link](“{0,6}”, [Link](1, 11));
if (ctr % 5 == 0) [Link]();
}
}
}
// Un ejemplo de salida de números enteros de -100 a 100
// 5 -5 - 20 94 -86
// -3 -16 -45 -19 47
// -67 -93 40 82 68
// -60 -55 67 -51 -11
// Un ejemplo de salida de números enteros de 1000 a 10000
// 4857 9897 4405 6606 1277
// 9238 9113 5151 8710 1187
// 2728 9746 1719 3837 3736
// 8191 6819 4923 2416 3028
// Un ejemplo de salida de números enteros de 1 a 10
// 4 4 5 9 9
// 5 1 2 3 5
// 5 4 5 10 5
// 7 7 7 10 5

90
Programación

ponte a prueba

Gracias a la librería de matemáticas, el IDE nos proporciona métodos ya


implementados. Según esto, ¿qué realiza el siguiente código?

double grados =90;


double angulo = [Link] * grados / 180.0;
double result = [Link](angulo);
[Link](result);

a) Saca por pantalla el coseno de un ángulo


b) Saca por pantalla el seno de un ángulo
c) El código no es correcto
d) Ninguna de las opciones es correcta

4.10.  Introducción al concepto


de recursividad
Cuando trabajamos con funciones, podemos definir la re-
cursividad como la llamada de una función a sí misma
hasta que cumpla una determinada condición de salida.

Sintaxis:

modificador tipo_devuelto nombre_funcion(tipo par1, tipo par2, …, tipo parn)


{
nombre_funcion(var1, …, var2)

}

Podemos definir la recursividad de la siguiente manera:

• Un caso base que permita la finalización del programa


(sería nuestra condición de salida).
• Casos recursivos, que son los que se van a encargar de
que la función vuelva a ejecutarse, pero acercándose
cada vez más al caso base.
Vamos a ver un ejemplo para poner en práctica todos estos
conceptos:

91
Tema 4: Programación modular

Factorial de un número

El factorial de un número n se calcula:

n! = n*(n-1)*(n-2)*(n-3)*…*1

Debemos saber qué es el factorial de un número. Por


ejemplo:

3!=3*2*1
4!=4*3*2*1
5!=5*4*3*2*1”

Si queremos realizar en C# una función que calcule el fac-


torial de un número, podríamos definirla de la siguiente
forma:

int factorial(int n)

¿Cuál podría ser el caso base?

Debemos encontrar uno que finalice el programa. En este


supuesto, siempre tenemos que buscar el caso más peque-
ño que existe. En nuestro ejemplo, el “1!=1”.

factorial(1)=1;

Pensemos ahora en el caso recursivo

Debemos encontrar uno que sirva para todos los números.


Debe ir haciéndose cada vez más pequeño hasta que con-
siga llegar al caso base, que es el factorial de 1.

Si nos fijamos en el ejemplo que hemos puesto:

3!=3*2*1
4!=4*3*2*1
5!=5*4*3*2*1”

Podemos apreciar lo siguiente:

3!=3*2*1
4!=4*3!
5!=5*4!
….

92
Programación

Vemos que en todos los casos sucede lo mismo, se multi-


plica el número por el número restando una unidad. Por lo
que ya tenemos el caso recursivo:

factorial(n)=n*factorial(n-1)

De modo que nos quedaría de la siguiente forma:

Caso base  Si n=1, factorial(1) devuelve 1.

Caso genérico  Si n>1, factorial(n) = n*factorial(n-1).

Si hacemos una función llamada “factorial” (entero n) re-


torna entero:

{
si n>1 entonces
// Caso recursivo
devuelve n*factorial(n-1);
Si no
// Caso base
devuelve 1;
Fin Si;
}

Si lo traducimos al lenguaje de programación C#:

static int factorial(int n)

93
Tema 4: Programación modular

{
if (n>1)
return n*factorial(n-1);
else
return 1;
}

A continuación, analizaremos otro ejemplo recursivo. En


este caso, vamos a imprimir por pantalla n números natu-
rales. Será el usuario quién decida qué números naturales
querrá imprimir. Por ejemplo, si el usuario introduce el
número 6, se imprimirá por pantalla la siguiente secuencia:

123456

• Caso base: el usuario introduce valores que no son nú-


meros naturales (es decir, menores que uno), el programa
devolverá siempre 1.
• Caso recursivo: vamos a llamar a la función con dos
parámetros. Así, uno de ellos controlará la salida e irá
incrementando en 1, y el otro irá decrementando hasta
llegar al caso base.

int salida = 1;
{
si n>1 entonces
// Caso recursivo
n- -;
Escribimos salida
devuelve naturales (salida +1, n)
Si no
// Caso base
devuelve salida;
Fin Si;
}

El código en C# quedaría de la siguiente forma:

static int naturales (int salida, int n)


{
if (n > 1)
{
n--;
[Link](“ {0} “, salida);
return printNatural (salida + 1, n);

} else
return salida
}

94
Programación

ponte a prueba

¿A qué se refiere el concepto de recursividad?


a) Un tipo de método.
b) La visibilidad de una función.
c) Llamada de una función a sí misma.
d) Una librería.

La recursividad necesita un caso base que permita la finalización del


programa.
a) Verdadero.
b) Falso.

¿Qué realiza el siguiente código?

static int printNatural(int ctr, int stval) {


if (ctr < 1) {return stval; }
[Link](“ {0} “, ctr);
ctr--;
return printNatural(ctr, stval);
}

static void Main() {


[Link](“ ¿Cuántos números quieres imprimir? : “);
int ctr = Convert.ToInt32([Link]());
printNatural(ctr, 1);
}

a) Muestra por pantalla los n primeros números naturales.


b) Muestra por pantalla los números de n a 1.
c) Muestra la resta de dos números naturales.
d) Muestra la suma de dos números naturales.

95
5
GESTIÓN DE FICHEROS
Programación

Hasta aquí, hemos visto el uso de variables y las estructu-


ras de datos y hemos trabajado con información que, una
vez que finaliza la ejecución del programa, desaparece de
la memoria, ya que ha estado almacenada en la memoria
principal el tiempo que dura la ejecución del software.

La solución para que los datos persistan después de la eje-


cución es almacenarlos en un fichero. Entonces, cada vez
que ejecutemos una aplicación que trabaja con esos datos
podrá leer del fichero aquellos que sean necesarios.

5.1.  Concepto y tipos de ficheros


Un fichero es una parte de un dispositivo no volátil a la que
se le asigna un nombre y que puede contener una cantidad
de datos que va a estar limitada, o por la cantidad de espa-
cio del que disponga el dispositivo, o por las características
del sistema operativo. Entendemos por dispositivos no vo-
látiles aquellos que no pierden la información que poseen
cuando apagamos nuestro ordenador.

Debido a la importancia que tienen los ficheros al actuar


de almacenes no volátiles de la información, la BCL (Base
Class Library) reserva un espacio de nombres denominados
[Link], destinado a trabajar con ellos.

El espacio de nombres [Link] contiene tipos que per-


miten leer y escribir en los archivos. Además, ese espacio
de nombres nos proporciona compatibilidad entre archivos
y directorios.

Algunas de las clases que nos proporciona son:

CLASE DESCRIPCIÓN

BinaryReader Lee tipos de datos primitivos como valores binarios.

BinaryWriter Escribe tipos primitivos en formato binario en una secuencia y admite


la escritura de cadenas.

File Proporciona métodos estáticos para crear, copiar, eliminar, mover y


abrir un solo archivo. Contribuye a la creación de objetos FileStream.

BufferedStream Almacena en un búfer los datos necesarios para las operaciones de


lectura y escritura en otra secuencia. No se puede heredar esta clase.

FileStream Proporciona un Stream para un archivo, lo que permite operaciones


de lectura y escritura sincrónica y asincrónica.

97
Tema 5: Gestión de ficheros

StreamReader Implementa un TextReader que lee los caracteres de una secuencia


de bytes.

StreamWriter Implementa TextWriter para escribir los caracteres de una secuencia.

TextReader Representa un lector que puede leer una serie secuencial de caracteres.

TextWriter Representa un escritor que puede escribir una serie secuencial de


caracteres.

Para obtener más información de las clases que del espacio


de nombres de [Link], podemos acceder a la documen-
tación de Microsoft:

BUSCA EN LA WEB

[Link]
[Link]?view=netcore-3.1

Los ficheros se almacenan en directorios o carpetas. Cada


directorio puede contener, a su vez, otros directorios dife-
rentes, y esto hace que el sistema de archivos vaya creando
una estructura jerárquica en la que cada fichero o directorio
tiene como padre el directorio que lo contiene.

Como es lógico, y para que esta estructura sea finita, debe


existir un directorio raíz, que va a ser el que contenga a
todos los demás y no tenga dependencia de ningún otro.

En resumen

Los ficheros o archivos 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.

Esto permite más independencia sobre la información, ya


que no necesitamos que el programa se esté ejecutando
para que la información que contiene exista. Cuando se di-
seña un programa y se quiere guardar información en algún
fichero, el programador es el encargado de indicar cómo
manejar esas estructuras (creación de ficheros, añadir in-
formación en un fichero ya existente…).

98
Programación

Por tanto, para manipular un fichero, que lo identificamos


por un nombre, realizaremos tres operaciones:
• Abrir el fichero.
• Escribir o leer registros del fichero.
• Cerrar el fichero.

A la hora de trabajar con ficheros, debemos tener en


cuenta:
• La información es binaria (conjunto de ceros y unos).
• Al agrupar los bits, se forman bytes o palabras.
• Los tipos de datos van a estar formados por un conjunto
de bytes o palabras.
• Al agrupar los campos, se crean los registros de infor-
mación.
• Un fichero es un conjunto de bytes con una misma es-
tructura.
• Los directorios tienen la función de agrupar distintos fi-
cheros siguiendo unas condiciones determinadas dadas
por el sistema operativo o por 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. Por tanto,
en una misma máquina pueden existir dos ficheros iden-
tificados por el mismo nombre, ya que, como van a tener
distinta ruta, los vamos a poder diferenciar.
• La relación entre ficheros y directorio es muy cercana, en
C# se establece entre tipos y espacio de nombres.

99
Tema 5: Gestión de ficheros

Rutas de ficheros y directorios


En el apartado anterior hemos visto la relación entre fiche-
ro y directorio. Para la identificación inequívoca de este
fichero, habrá que nombrar el camino que nos lleva hasta
él. A este camino lo denominamos ruta.

Dependiendo de cómo empecemos la ruta de directorio


para nombrar el archivo, podemos tener dos tipos de rutas
bien diferenciados:

• Ruta absoluta o completa: se indica el camino del direc-


torio desde el comienzo. En el sistema operativo Linux,
empieza por “/”. En el sistema operativo Windows o MS-
DOS, cada partición posee un directorio raíz (por ejemplo,
C:\). No existe un directorio raíz común que los contenga
a todos ellos como en Linux.
• Ruta relativa: se le indica el camino del directorio desde
la posición actual. Por tanto, la ruta no empezaría desde
el directorio raíz.

Tipos de ficheros
• Según su acceso: según la forma de organizar la infor-
mación, podemos distinguir entre tres tipos diferentes de
ficheros:
– Secuencial: en los ficheros secuenciales, los registros
se van almacenando en posiciones consecutivas de
manera que cada vez que queramos acceder a ellos
tendremos que empezar desde el primero e ir reco-
rriéndolos de uno en uno.

100
Programación

• Aleatorio o directo: en los ficheros aleatorios, podemos


acceder a un registro concreto indicando una posición
perteneciente a un conjunto de posiciones posibles. De-
bido a que los registros están organizados, estos pueden
ser leídos o escritos en cualquier orden, ya que se acce-
de a cada uno a través de su posición. Cuando queremos
realizar una operación, basta con colocar el puntero que
maneja el fichero justo antes de este.

Registro 1 Registro 2 Registro 3 Registro 4 … Registro N

Posición lectura/escritura

Para leer el Registro 4, colocamos el puntero de lectura/


escritura justo antes de su posición.
– Secuencial indexado: los ficheros indexados poseen
un campo clave (índice) para ser identificados. Permi-
ten el acceso secuencial y aleatorio a un fichero de la
siguiente forma:
1. Primero busca de forma secuencial el campo clave
o índice.
2. Una vez que lo encuentra, el acceso al fichero es
directo, ya que solo tenemos que acceder a la posi-
ción indicada por el campo clave.
Para que este proceso funcione de manera correcta, los
índices se encuentran ordenados, permitiendo de esta
forma un acceso más rápido.

Campo clave o índice Archivo de datos

1 1510
77

2 77

3 3680
1510

3680

101
Tema 5: Gestión de ficheros

• Según su estructura:
– Ficheros de texto: formados por texto plano sin forma-
to legible por el usuario.
– Ficheros binarios: los datos se almacenan de forma bi-
naria (como su nombre indica) y, por tanto, de la misma
forma que se guarda en memoria. Los datos se encrip-
tan (codifican) en ceros y unos, de manera que se hace
mucho más eficiente su almacenamiento.

ponte a prueba

¿En qué tipo de dispositivo de almace-


namiento se guarda el contenido de los
ficheros?
a) Primario.
b) Secundario.
c) Terciario.
d) Ninguna de las opciones es correcta.

¿Cuál de las siguientes afirmaciones sobre un


fichero secuencial indexado es correcta?
a) Está compuesto por un índice secuencial.
b) E
 stá formado por un puntero que nos indica
el campo que queremos acceder.
c) No podemos programar en C# este tipo de
ficheros.
d) A y B son correctas.

¿Qué tipo de ruta es esta: ./carpeta/fichero.


dat?
a) Es una ruta relativa.
b) Es una ruta absoluta.
c) Es una ruta secuencial.
d) Ninguna respuesta es correcta.

102
Programación

5.2.  Diseño y modulación de las


operaciones sobre ficheros

5.2.1.  Fundamentos de los flujos


Los flujos (también llamados stream) de datos son las es-
tructuras 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.

La clase Stream nos permite abstraer de una secuencia


de bytes como, por ejemplo, un archivo, un dispositivo de
entrada/salida, una canalización de comunicación entre
procesos o un socket.

La clase FileStrem deriva de la clase Stream y nos propor-


ciona los siguientes métodos:

FileStream (string nombre, FileMode modo)


FileStream (string nombre, FileMode modo, FileAccess
acceso)

El primer método abre un flujo de entrada y salida que se


vincula al fichero especificado en el nombre, mientras que
el segundo método realiza lo mismo y añade el tipo de ac-
ceso: lectura, escritura o lectura/escritura.

El parámetro nombre es una cadena de caracteres que in-


dica la ruta donde está guardado o donde se guardará el
fichero.

103
Tema 5: Gestión de ficheros

Puede escribirse:

c:\\users\\AppData\\[Link]
@c:\users\AppData\[Link]

La ventaja de utilizar la @ es que las secuencias de escape


no se procesan. Una secuencia de escape son combina-
ciones de caracteres que consisten en una barra diagonal
inversa (\) seguida de una letra como, por ejemplo, \n que
representa una nueva línea.

FileMode nos indica cómo se debe abrir un archivo. Los


campos pueden tomar los siguientes valores:

CreateNew Crea un nuevo fichero. Si existe, lanzará un error.

Truncate Abre un fichero existente. El fichero será truncado a cero bytes de


longitud.

Create Crea un nuevo fichero. Si el fichero existe, será sobrescrito.

Open Abre un fichero existente. Si el fichero no existe, lanzará un error.

OpenOrCreate Abre un fichero si existe; si no, se crea un fichero nuevo.

Append Abre un fichero para añadir datos al final del mismo si existe, o
crea un fichero nuevo si no existe.

El parámetro acceso puede tomar los siguientes valores:

Read Permite acceder al fichero para realizar operaciones de lectura.

ReadWrite Permite acceder al fichero para realizar operaciones de lectura y


escritura.

Write Permite acceder al fichero para realizar operaciones de escritura.

En el flujo de entrada de datos (lectura), solo podemos rea-


lizar la operación de lectura de un fichero, es decir, existe
una comunicación unilateral desde el fichero al programa.

El flujo de salida (escritura) también es en sentido unidi-


reccional, ya que solo podemos realizar la operación de
escritura en el fichero.

104
Programación

En el flujo o stream de entrada/salida es cuando podemos


tanto leer como escribir en el fichero. El tipo de stream lo
vamos a definir al iniciar el trabajo con ficheros, y no se
podrá cambiar una vez abierto.

ponte a prueba

¿Qué es FileStream? ¿Qué hace la directiva Open?


a) Es un tipo de variable de ficheros. a) Abre un fichero si existe. Si no
b) Es un tipo de visibilidad de existe, se crea un fichero nuevo.
métodos en el manejo de ficheros. b) A
 bre un fichero existente. Si el
c) Es una clase que permite opera- fichero no existe, lanzará un error.
ciones de lectura y escritura. c) Crea un nuevo fichero. Si existe,
d) Todas las opciones son correctas. lanzará un error.
d) Abre un fichero para añadir datos
al final de este.

5.2.2.  Clases de flujos

System Object

MarshalByRefObject BinaryReader BinaryWriter

Stream TextReader TextWriter

BufferedStream

StringReader StringReader

MemoryStream

StreamReader StringWriter

FileStream

Flujos intermedio
Flujos base

105
Tema 5: Gestión de ficheros

En este apartado utilizaremos las clases de C# pertenecien-


tes a los dos tipos de ficheros: binarios y de textos.

Se pueden distinguir dos tipos de flujos:

• Flujos base: son aquellos que operan más a nivel máqui-


na, como, por ejemplo, porción de memoria, espacio de
disco o conexión de red.
• Flujos intermedios: son aquellos flujos que trabajan por
encima de los anteriores. Se pueden combinar con el flu-
jo base de manera que este pueda verse beneficiado por
todas las funcionalidades que ofrezca el flujo base.
• Podríamos decir que el flujo intermedio procesa la in-
formación, mientras que el base realiza la función de
envío de bytes de un lugar a otro.

5.3.  Operaciones sobre ficheros


secuenciales
Las tres operaciones básicas que tenemos cuando traba-
jamos con ficheros son:

1. Apertura

Lo primero que debemos hacer siempre es abrir el fichero


para la operación que vayamos a realizar sobre él. Cuan-
do abrimos el fichero, estamos relacionando un objeto de
nuestro programa con un archivo.

Los diferentes modos en los que se puede abrir un fichero


son los siguientes:

• Open: realizamos la apertura de un fichero. Recordemos


que se desencadena una excepción si el fichero no existe
(FileNotFoundException).
• Create: creamos un fichero nuevo. Si el archivo ya existe,
se sobrescribirá. Es equivalente a solicitar que se utilice
CreateNew si no existe el archivo, y que se utilice Truncate
en caso contrario.
• CreateNew: creamos un fichero nuevo. Si el fichero ya
existe, lanzará una excepción (IOException).

106
Programación

• Truncate: abrimos un archivo que ya existe. Cuando se


abra, se debe truncar su tamaño a cero bytes. Al intentar
leer un abierto en este modo, se producirá una excepción
(ArgumentException).
• OpenOrCreate: se abre un archivo si ya existe. En caso
contrario, se crea uno nuevo.
• Append: se abre el archivo si existe y realiza una búsque-
da hasta el final. Si el archivo no existe, crea uno nuevo.

2. Lectura/escritura

Tenemos que leer o escribir la información del fichero


prestando atención tanto al fin de fichero en ficheros
secuenciales como a la posición del puntero en ficheros
aleatorios.

Las operaciones de lectura/escritura se pueden hacer de


dos formas diferentes: para ficheros secuenciales o para
ficheros aleatorios. Vamos a verlo detenidamente con el
siguiente ejemplo:

Lectura secuencial

// PSEUDOCÓDIGO
// Declaración de la variable del fichero
fichero f1;
// Abrimos el fichero para leerlo
[Link](lectura);

Mientras no final de fichero Hacer


[Link](registro);
operaciones con registro leído;
FinMientras

// Cerramos el fichero
[Link]();

Escritura secuencial

// PSEUDOCÓDIGO
// Declaración de la variable del fichero
fichero f1;

// Abrimos el fichero para leerlo


[Link](escritura);

Mientras existan datos a escribir


[Link](registro);
FinMientras

// Cerramos el fichero
[Link]();

107
Tema 5: Gestión de ficheros

Lectura aleatoria

// PSEUDOCÓDIGO
// Declaración de la variable del fichero
fichero f1;

// Abrimos el fichero para leerlo


[Link](lectura);

Situar el puntero del fichero justo antes del


registro requerido
[Link](registro);
Otras operaciones con registro leído;

// Cerramos el fichero
[Link]();

Escritura aleatoria

// Declaración de la variable del fichero


fichero f1;

// Abrimos el fichero para leerlo


[Link](escritura);

Mientras se deseen escribir datos Hacer


Posicionar el puntero del fichero en la posición deseada
[Link](registro);
otras operaciones con registro leído;
finMientras

//Cerramos el fichero
[Link]();

108
Programación

3. Cierre

Cuando cerramos el fichero, este queda liberado y termina


el proceso de almacenamiento de información.

ponte a prueba

¿Qué realiza el siguiente código?

FileStream fichero = new FileStream(“C:/fichero/ejercicio1.


txt”, [Link], [Link]);
StreamReader fs = new StreamReader(fichero);
string linea = “”;
while ((linea = [Link]()) != null)
[Link](linea);
[Link]();
[Link]();

a) Muestra por pantalla una cadena vacía.


b) Muestra por pantalla el contenido del fichero “[Link]”.
c) Escribe línea en el fichero “[Link]”.
d) Ninguna de las opciones es correcta.

La programación en C# de los ficheros secuenciales y aleatorios se realiza


teniendo en cuenta la posición del puntero.
a) Verdadero.
b) Falso.

5.3.1.  Clase FileStream


En el apartado 5.2.1 vimos los tipos de métodos que nos
proporciona esta clase y los diferentes valores que pueden
tomar el parámetro modo y acceso.

FileStream (string nombre, FileMode modo)


FileStream (string nombre, FileMode modo, FileAccess
acceso)

Vamos a trabajar con estos métodos para ficheros de texto


y ficheros binarios.

109
Tema 5: Gestión de ficheros

Ficheros de texto
Los datos pueden ser escritos o leídos de un fichero utilizan-
do los flujos de las clases StreamWriter y StreamReader:

• StreamReader implementa un TextReader que lee los ca-


racteres de una secuencia de bytes.
• StreamWriter implementa un TextWriter para escribir los
caracteres de una secuencia.

Lectura de un fichero de texto en C#:

using [Link]; // Importación de la clase [Link]


// Creamos la variable fichero con la clase FileStream pasando la ruta
del fichero, el modo de apertura (Open) y cómo vamos a acceder a él
(lectura)
FileStream fichero = new FileStream(“C:/fichero/[Link]”, File-
[Link], [Link]);
// Abrimos el flujo de lectura
// Proporciona una vista genérica de una secuencia de bytes
StreamReader fs = new StreamReader(fichero);
string linea = “”;
while ((linea = [Link]()) != null) // Mientras no lleguemos a fi-
nal de fichero
[Link](linea); //sacamos por pantalla lo
que contenga el fichero
[Link](); // cerramos el flujo
[Link](); // cerramos el fichero
}
}

110
Programación

Escritura de un fichero de texto en C#

using [Link]; // Importación de la clase [Link]

// Creamos la variable fichero con la clase FileStream pasando la ruta


del fichero, el modo de apertura (en este caso, vamos a añadir datos al
final del fichero -> Append) y cómo vamos a acceder a él (escritura)

FileStream fichero = new FileStream(“C:/fichero/[Link]”, File-


[Link], [Link]);

// abrimos el flujo de escritura

StreamWriter fs = new StreamWriter(fichero);

//pedimos al usuario una cadena de texto la escribiremos en el fichero

[Link](“Introduce una frase: “);

string frase = [Link]();

[Link](frase);

// cerramos el flujo y el fichero

[Link]();

[Link]();

Ficheros binarios

Generalmente, los usuarios trabajamos con ficheros de


texto, pero también es frecuente encontrarnos con infor-
mación que esté organizada como una secuencia de bytes.
Nos referimos a ficheros de imágenes, ficheros de sonido,
ficheros de video, etc.

Lo primero que vamos a analizar es cómo abrir un fichero


de forma que podamos leer los bytes que contiene.

Comenzaremos por utilizar la clase FileStream, diseñada


para acceder a un byte o a bloques de byte. Así, esta clase,
proporciona un método para el acceso:

• Read (Byte[], int offset, int count) lee un bloque de bytes


de la secuencia y escribe los datos en un búffer dado.
Los parámetros:
– array Byte []: contiene la matriz de bytes especificada
con los valores de offset y reemplazados por los bytes
leídos desde el origen actual.
– offset: se colocarán los bytes leídos.
– Count: el número máximo de bytes que se deben leer.

111
Tema 5: Gestión de ficheros

Por ejemplo:

byte[] buffer = new byte[[Link]];


// creamos un array unidimensional con la cantidad de bytes que se
compone el fichero
[Link](buffer, 0, [Link]);
// Vamos a leer el buffer donde todavía no hemos consumido ningún byte
y el número máximo que vamos a leer es lo que contiene el buffer

Ejemplo de lectura en ficheros binarios

using [Link];

// Vamos a trabajar con un fichero imagen, de tal forma que lo abrire-


mos de modo lectura

FileStream fichero = new FileStream(“C:/fichero/[Link]”, FileMode.


Open, [Link]);

// Creamos un buffer de tipo byte para poder trabajar con los datos del
fichero

Byte [] buffer = new byte[[Link]]; //un entero de 8 bits sin


signo.

// Abrimos el fichero para la lectura y vamos a ir consumiendo todos


los bytes del fichero y mostrándolos por pantalla

[Link](buffer, 0, [Link]);

for (int i = 0; i < [Link]; i++)

[Link](buffer[i]);

//[Link]();

112
Programación

Ejemplo de escritura en ficheros binarios

using [Link];

// Vamos a trabajar con un fichero imagen, de tal forma que lo abrire-


mos de modo lectura

FileStream fichero = new FileStream(“C:/fichero/[Link]”, FileMode.


Open, [Link]);

// Creamos un buffer de tipo byte para poder trabajar con los datos del
fichero

Byte [] buffer = new byte[[Link]]; //un entero de 8 bits sin


signo.

// Abrimos el fichero para la lectura y vamos a ir consumiendo todos


los bytes del fichero y mostrándolos por pantalla

[Link](buffer, 0, [Link]);

for (int i = 0; i < [Link]; i++)

[Link](buffer[i]);

//[Link]();

113
Tema 5: Gestión de ficheros

ponte a prueba

¿Qué realiza el siguiente código?

FileStream fichero = new FileS-


tream(“C:/fichero/[Link]”,
[Link], [Link]);
StreamWriter fs = new StreamWriter(-
fichero);

[Link](“Introduce una
frase: “);
string frase = [Link]();

[Link](frase);
[Link]();
[Link]();

a) Escribirá la frase introducida por el usuario en


un fichero binario.
b) E
 scribirá la frase introducida por el usuario
en un fichero de texto.
c) Escribirá la frase introducida por el usuario en
un fichero de datos.
d) El código contiene errores porque falta cerrar
el flujo de datos.

La clase StreamReader es utilizada para leer


texto de un archivo.
a) Verdadero.
b) Falso.

¿Cuál es el objetivo de utilizar un buffer de


lectura para ficheros de datos?
a) Para almacenar el conjunto de bytes formado
por el fichero de datos.
b) Para guardar línea a línea el fichero de texto.
c) Para controlar el fin de fichero.
d) Ninguna opción es correcta.

114
Programación

5.4.  Control de excepciones


Hasta ahora, hemos trabajado con ficheros para realizar su
lectura y escritura. El problema es que no hemos compro-
bado si ese fichero realmente existe o no, lo que puede
suponer que nuestro programa falle en caso de que el
fichero no se encuentre donde esperamos.

Una primera solución es usar el método exists para


comprobar si está, antes de intentar abrirlo.

• Exists (string path): le pasamos la ruta del fichero y de-


volverá un booleano. Si no existe, devolverá un false. Si la
ruta no existe o es incorrecta, también devolverá un false.

using [Link];
if ([Link](@”D:\[Link]”)) {
[Link](“El fichero existe...”);
} else {
[Link](“El fichero no existe en el directorio D…”);
}

• Try/catch: el bloque try contiene el código protegido que


puede producir la excepción.
Los mensajes de error y/o acciones para corregir el error
estarán en el bloque catch.

using [Link];
string linea;

try
{
FileStream fichero = new FileStream(“C:/fichero/ejercicio1.
txt”, [Link], [Link]);
StreamReader fs = new StreamReader(fichero);
if ((linea= [Link]())!= null)
[Link](linea);
[Link]()
[Link]();
}
catch (Exception exp)
{
[Link](“Ha habido un error: {0}”, [Link]);
}

115
BIBLIOGRAFÍA / WEBGRAFÍA
” Ceballos, F. J. (2011). Microsoft C#. Curso de programación. 2ªEdición. RA-MA Editorial.
” Nacho Cabanes. Introducción a C#. 2020. Sitio web: [Link]
csharp/curso2015/[Link]
” Pildorasinformaticas. Canal de Youtube. Sitio web: [Link]
pildorasinformaticas
” Serna, M. E. (2009). Edsger Wybe Dijkstra. Revista Digital Lámpsakos, no. 2, pp. 107-11.
” Corrado Böhm, Giuseppe Jacopini. (1966). Flow diagrams, turing machines and
languages with only two formation rules. 2020, de ACM Digital Library, Association for
Computing Machinery. Sitio web: [Link]
solucionario
1. Introducción a la programación ¿Cuál de las siguientes opciones sobre el
operador ! es correcta?
¿Cómo debe ser un programa informático?
a) Calcula la negación lógica de nuestro
d) Todas las opciones anteriores son correctas.
operando.
¿Cuál de las siguientes opciones sobre el
siguiente diagrama de flujo es correcta? 2.4. Conversiones de tipos de clase
a) Muestra los n primeros números impares.
Las conversiones implícitas son aquellas que se
C# tiene dos categorías tipos de datos producen cuando el valor que se va a almacenar
integrados: por valor y por referencia. se puede almacenar en la variable sin pérdida
a) Verdadero. de información.
a) Verdadero.
2. Estructura de un programa informático ¿Qué convierte el método ToString?
¿Qué es un IDE? d) E
 l valor especificado en su representación de
cadena.
c) Es un software diseñado para el desarrollo de
aplicaciones.
2.5. Comentarios
Siempre que ejecutemos un programa, el
primer método que se ejecutará será el Main. Según el siguiente código, ¿qué saldrá por
a) Verdadero. pantalla?
d) Nada, porque el código está comentado.
¿Qué realiza el siguiente código?
c) Muestra por pantalla Hello World! Para hacer comentarios de una sola línea,
debemos utilizar el operado /.
b) Falso.
2.1. Variables. Usos y tipos
Hay que utilizar la doble barra //.
¿Cuál de las siguientes opciones es una
característica de una variable?
3. Programación estructurada
d) Todas las respuestas son correctas.
Dijkstra concluyó que la combinación de varios
¿Qué tipo de dato es un char? tipos de instrucciones, podemos crear un
a) Carácter. programa estructurado. ¿Cuáles son?
d)Todas las opciones son correctas.
Las variables globales son aquellas que están
declaradas dentro de un método o función
b) Falso. 3.1. Fundamentos de la programación
Las variables globales son aquellas declaradas Según Böhm y Jacopini, ¿cuál de las siguientes
fuera de un método o función. opciones sobre un programa es cierta?
d) Todas las respuestas son correctas.
2.2. Constantes y literales. Tipos y utilidades
¿Con qué palabra reservada se define una 3.3. Diseño de algortimos
constante? En la etapa de diseño, tomamos los requisitos
a) Const. de los clientes.
b) Falso.
¿Qué representa el literal \n?
Es en la etapa de análisis donde tomamos los
a) Una nueva línea.
requisitos.

2.3. Operadores del lenguaje de Después de la fase de pruebas, ¿qué etapa se


programación lleva a cabo?
c) Mantenimiento.
¿Cuál es el resultado del siguiente código?
b) 2.
solucionario
3.5. Tipos de datos: simples y compuestos 3.10. Depuración de errores
¿Qué tipo de datos es el tipo enumerado? ¿Qué errores podemos encontrar en la etapa de
a) Compuesto. la depuración de un programa?
d) Todas las respuestas son correctas.
¿Cómo puedo acceder al dato 2 si tenemos el
siguiente array? int[] a = new int[] {1, 2, 3}; El programador está realizando un programa en
a) a[1]. el cual quiere introducir dos datos enteros. Uno,
que sea la base y otro que sea el exponente
¿Cuántas columnas contendrá la siguiente para realizar la operación potencia. Introduce
matriz? int [,] matriz = new bool[2,3]; como base el número 5 y como exponente 2.
b) 3. El resultado es 10. ¿Qué tipo de error le está
dando a nuestro programador?
b) Lógico.
3.6. Estructuras de selección
Según el siguiente código, ¿cuándo imprimimos 3.12. Entornos de desarrollo de programas
la cadena “Hola a todos”?
c) Cuando se cumpla la condición a y b. ¿Qué ventajas nos ofrecen los IDE?
d) Todas las opciones son correctas.
Según el siguiente código:
a) Escribimos por pantalla “Estamos en el if”.
4.2. Ventajas e inconvenientes
¿Qué ventajas nos proporciona la programación
3.7. Estructuras de repetición modular?
Según el siguiente código, ¿ejecutaríamos el d) Todas las opciones son correctas.
código de la salida por pantalla?
a) Sí, con que se cumpla una condición es
4.3. Análisis descendente (top down)
suficiente.
¿En qué consiste el diseño top down?
¿Cuántas veces ejecutaríamos un bucle do-
while? b) Dividir un gran problema en subproblemas.
b) Mínimo, una vez.
4.5. Llamadas a funciones. Tipos y
¿Es correcto el siguiente código? funcionamiento
b) No. La variable i no está declarada.
Las funciones deben tener un tipo asociado.
a) Verdadero.
3.8. Estructuras de salto
¿Cuál es la salida del siguiente código?
Según el siguiente código, ¿qué saldrá por
pantalla? a) 15.
a) Case 1. Cuando realizamos un paso por valor de una
variable, creamos dos posiciones de memoria
distintas.
3.9. Tratamiento de cadenas
a) Verdadero.
¿Qué mostrará por pantalla el siguiente código?
a) 3.
4.6. Ámbito de las llamadas a funciones
La función Trim() elimina cualquier carácter del Una variable local puede ser accedida desde
principio y el final de la cadena. cualquier función o método.
b) Falso. b) Falso.
Si no se pasa argumentos a la función Trim, eli- Solo se pueden acceder a variables locales des-
mina todos los caracteres de espacio en blanco de el método donde están creadas.
del principio y el final de la cadena.
solucionario
¿Qué muestra por pantalla el siguiente código? ¿Qué hace la directiva Open?
c) 15 b) Abre un fichero existente. Si el fichero no
HOLA ILERNA. existe, lanzará un error.

Según el siguiente código, ¿qué ocurrirá con la


función? 5.3. Operaciones sobre ficheros secuenciales
c) La función nos devolverá num1 si es mayor ¿Qué realiza el siguiente código?
que num2 o num2 si es mayor que num1. b) Muestra por pantalla el contenido del fichero
“[Link]”.
4.7. Prueba, depuración y comentarios de
La programación en C# de los ficheros
programas secuenciales y aleatorios se realiza teniendo en
Podemos poner un punto de interrupción en cuenta la posición del puntero.
nuestros programas y depurar línea a línea. b) Falso.
a) Verdadero. Solo hay que controlar el puntero en los ficheros
aleatorios.
4.9. Uso de librerías
Gracias a la librería de matemáticas, el IDE nos 5.3.1. Clase FileStream
proporciona métodos ya implementados. ¿Qué realiza el siguiente código?
Según lo comentado, ¿qué realiza el siguiente b) Escribirá la frase introducida por el usuario en
código? un fichero de texto.
a) Saca por pantalla el coseno de un ángulo.
La clase StreamReader es utilizada para leer
texto de un archivo.
4.10. Recursividad a) Verdadero.
¿A qué se refiere el concepto de recursividad? ¿Cuál es el objetivo de utilizar un buffer de
b) La visibilidad de una función. lectura para ficheros de datos?
a) Para almacenar el conjunto de bytes formado
La recursividad necesita un caso base que por el fichero de datos.
permita la finalización del programa.
a) Verdadero.

¿Qué realiza el siguiente código?


b) Muestra por pantalla los números de n a 1.

5.1. Concepto y tipos de ficheros


¿En qué tipo de dispositivo de almacenamiento
se guarda el contenido de los ficheros?
b) Secundario.

¿Cuál de las siguientes afirmaciones sobre un


fichero secuencial indexado es correcta?
d) A y B son correctas.

¿Qué tipo de ruta es esta: ./carpeta/[Link]?


a) Es una ruta relativa.

5.2.1. Fundamentos de los flujos


¿Qué es FileStream?
c) Es una clase que permite operaciones de
lectura y escritura.

ILERNA, centro autorizado con código 25002775 (Lleida) y 28077294 (Madrid)
Desarrollo de aplicaciones web
PROGRAMACIÓN
Ilerna
© Ilerna Online S.L., 2021
Maquetado e impreso por Ilerna Online S.L.
© Imágenes: Shutterstock
Impreso en España - Printed in
1.	 u0007Introducción a la programación........................................................6
2.	 u0007Estructura de un programa i
5.	 u0007Gestión de ficheros..........................................................................96
5.1.	
Concepto y tipos d
1	
u0007INTRODUCCIÓN A LA PROGRAMACIÓN
Programación
7
Un programa es un conjunto de instrucciones dadas al or-
denador en un lenguaje que solo es entendible por él
Tema 1: Introducción a la programación
8
Representaciones gráficas
Para representar un algoritmo, podemos utilizar dos 
herra
Programación
9
Características de los diagramas de flujo:
•	 Deben escribirse de arriba abajo o de izquierda a derecha.
•	 D
Tema 1: Introducción a la programación
10
La otra herramienta para representar los algoritmos es el 
pseudocódigo.
Es la mane

También podría gustarte