jueves, 28 de julio de 2011

Diseño de base de datos y consultas


Hemos estado trabajando un poco con Access para familiarizarnos con las bases de datos y el lenguaje de consultas SQL. A continuación voy a mostrar mi solución al problema planteado en este apartado del curso.
En primer lugar, se debe diseñar la estructura de tablas más adecuada a las necesidades de nuestro proyecto.
A continuación, se crean las consultas necesarias sobre la estructura de tablas creada previamente para obtener los datos requeridos por los usuarios.
BÚSQUEDAS:
1.- Cliente por nombre comercial, nombre fiscal, CIF/NIF, población, provincia, tipo de IVA, código postal y teléfono
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE NombreComercial LIKE “*”&[Nombre]&”*”
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE NombreFiscal LIKE “*”&[Nombre]&”*”
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE CIF_NIF = [:Nombre]
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE Poblacion=[:Nombre]
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE Provincia= [:Nombre]
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE CIF_NIF=[:CIF_NIF]
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE tipo_recargo_fk=[:TipoIVA]
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE codigo_postal=[:CodigoPostal]
-SELECT NombreFiscal, NombreComercial FROM CLIENTE WHERE Id IN (SELECT id_cliente_fk FROM TELEFONOS_CLIENTE WHERE teléfono=[:Telefono])

2.- Proveedor por nombre comercial, nombre fiscal, CIF/NIF, población, provincia, código postal y teléfono
-SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE NombreComercial LIKE “*”&[Nombre]&”*”
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE NombreFiscal LIKE “*”&[Nombre]&”*”
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE CIF_NIF =[:Nombre]
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE Poblacion==[:Nombre]
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE Provincia= =[:Nombre]
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE CIF_NIF=[:CIF_NIF]
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE codigo_postal=[:CodigoPostal]
SELECT NombreFiscal, NombreComercial FROM PROVEEDOR WHERE Id IN (SELECT id_proveedor_fk FROM TELEFONOS_ PROVEEDOR WHERE teléfono=[:Telefono])

3.- Artículos por código y descripción
SELECT * FROM ARTICULO WHERE id=[:Código]
SELECT * FROM ARTICULO WHERE descripcion LIKE “*”&[descripción]&”*”

LISTADOS:
a)Clientes que han realizado compras de artículos de un proveedor.
SELECT DISTINCT C.nombre_comercial FROM ((CLIENTE C INNER JOIN FACTURA_VENTA FV ON C.Id=FV.id_cliente_fk) INNER JOIN DETALLE_FACTURA_VENTA DFV ON FV.Id=DFV.id_factura_venta_fk) INNER JOIN ARTICULO A ON DFV.id_articulo_fk=A.Id WHERE A.id_proveedor_fk = [:IdProveedor]
b)Clientes a los que se les ha vendido un artículo.
SELECT DISTINCT C.nombre_comercial FROM (CLIENTE C INNER JOIN FACTURA_VENTA FV ON C.Id=FV.id_cliente_fk) INNER JOIN DETALLE_FACTURA_VENTA DFV ON FV.Id=DFV.id_factura_venta_fk WHERE DFV.id_articulo_fk= [:IdArticulo]
c)Proveedores de una factura de venta.
SELECT DISTINCT P.nombre_comercial AS NombreProveedor FROM ((FACTURA_VENTA FV INNER JOIN DETALLE_FACTURA_VENTA DFV ON FV.Id=DFV.id_factura_venta_fk) INNER JOIN ARTICULO A ON DFV.id_articulo_fk=A.Id) INNER JOIN PROVEEDOR P ON A.id_proveedor_fk=P.Id WHERE FV.Id = [:IdFacturaVenta]
d)Listado de facturas (total, por cliente, conteniendo un artículo).
-SELECT Id AS NumeroFactura, id_cliente_fk AS CodigoCliente, fecha FROM FACTURA_VENTA
-SELECT Id AS NumeroFactura, id_cliente_fk AS CodigoCliente, fecha FROM FACTURA_VENTA WHERE id_cliente_fk = [:IdCliente]
-SELECT FV.Id AS NumeroFactura, FV.id_cliente_fk AS CodigoCliente, FV.fecha AS Fecha FROM FACTURA_VENTA FV INNER JOIN DETALLE_FACTURA_VENTA DFV ON FV.Id=DFV.id_factura_venta_fk WHERE DFV.id_articulo_fk = [:IdArticulo]
e)Listado de stock (todos, solo existencias).
- select articulo, sum(CantidadTotal) as Stock from(
select a.descripcion as articulo, sum(dfc.cantidad) as CantidadTotal from detalle_factura_compra dfc inner join articulo a on dfc.id_articulo_fk=a.id group by a.descripcion
union
select a.descripcion as articulo, -sum(dfv.cantidad) as CantidadTotal from detalle_factura_venta dfv inner join articulo a on dfv.id_articulo_fk=a.id group by a.descripcion)
group by articulo

- select articulo, sum(CantidadTotal) as Stock from(
select a.descripcion as articulo, sum(dfc.cantidad) as CantidadTotal from detalle_factura_compra dfc inner join articulo a on dfc.id_articulo_fk=a.id group by a.descripcion
union
select a.descripcion as articulo, -sum(dfv.cantidad) as CantidadTotal from detalle_factura_venta dfv inner join articulo a on dfv.id_articulo_fk=a.id group by a.descripcion)
group by articulo having sum(CantidadTotal)>0
f)Listado de artículos (total y vendidos a un cliente entre fechas con precio de venta).
-SELECT descripcion, precio FROM ARTICULO
-SELECT A.descripción AS Articulo, DFV.precio_unidad AS PrecioVenta, DFV.cantidad AS Cantidad FROM (FACTURA_VENTA FV INNER JOIN DETALLE_FACTURA_VENTA DFV ON FV.Id=DFV.id_factura_venta_fk) INNER JOIN ARTICULO A ON DFV.id_articulo_fk=A.Id WHERE FV.id_cliente_fk = [:IdCliente] AND FV.fecha BETWEEN [:FechaInicial] AND [:FechaFinal]
g)Formato 347 para clientes y proveedores (ventas o compras anuales por importe total superior a 3.005,06€).
- SELECT C.nombre_fiscal, SUM((1+DFV.IVA_aplicable)*DFV.cantidad*DFV.precio_unidad) AS Total from (DETALLE_FACTURA_VENTA DFV INNER JOIN FACTURA_VENTA FV ON DFV.id_factura_venta_fk=FV.id) INNER JOIN Cliente C ON FV.id_cliente_fk=C.Id GROUP BY C.nombre_fiscal HAVING SUM((1+DFV.IVA_aplicable)*DFV.cantidad*DFV.precio_unidad)>3005.6
- SELECT P.nombre_fiscal, SUM((1+DFC.IVA_aplicable)*DFC.cantidad*DFC.precio_unidad) AS Total from (DETALLE_FACTURA_COMPRA DFC INNER JOIN FACTURA_COMPRA FC ON DFC.id_factura_compra_fk=FC.id) INNER JOIN Proveedor P ON FC.id_proveedor_fk=P.Id GROUP BY P.nombre_fiscal HAVING SUM((1+DFC.IVA_aplicable)*DFC.cantidad*DFC.precio_unidad)>3005.6
h)Listado de ventas entre fechas.
SELECT A.descripcion AS Descripcion, DFV.cantidad AS Unidades, DFV.precio_unidad AS Precio, DFV.IVA_aplicable AS IVA FROM (FACTURA_VENTA FV INNER JOIN DETALLE_FACTURA_VENTA DFV ON FV.Id=DFV.id_factura_venta_fk) INNER JOIN ARTICULO A ON A.Id=DFV.id_articulo_fk WHERE FV.fecha BETWEEN [:fechaInicio] AND [:fechaFin]

i)Listado de compras entre fechas (artículos comprados entre fechas).
SELECT A.descripcion AS Descripcion, DFC.cantidad AS Unidades, DFC.precio_unidad AS Precio, DFC.IVA_aplicable AS IVA FROM (FACTURA_COMPRA FC INNER JOIN DETALLE_FACTURA_COMPRA DFC ON FC.Id=DFC.id_factura_compra_fk) INNER JOIN ARTICULO A ON A.Id=DFC.id_articulo_fk WHERE FC.fecha BETWEEN [:fechaInicio] AND [:fechaFin]
j)Listado de clientes con email.
SELECT * FROM CLIENTE WHERE email IS NOT NULL
Nota: Estas consultas han sido probadas sobre la estructura de base de datos mostrada al inicio, sobre MS Access 2007 y con unos pocos datos.

jueves, 21 de julio de 2011

Pseudocódigo (II)

En esta ocasión voy a mostrar el pseudocódigo y el correspondiente código en lenguaje C de un problema un poco más complejo que los anteriores. Además, reflejaré el pseudocódigo sin modificaciones y, a continuación, el el código probado y depurado. De este modo se pueden observar las modificaciones y errores detectados una vez que el código fue compilado, ejecutado y probado. En este caso las modificaciones no fueron muchas, pero tuve que realizar algunas para que el programa funcionase del modo deseado.

Indicar a partir del número de días a partir del 01-01-2011, ¿Cuántos años, meses, semanas y días constituyen el número de días.
Funciones: BISIESTO(ano), DIASMES(mes)

INICIO
DíasInicio=0,anos, meses=0, semanas=0, anoActual=2011, diasRestantes=0
MOSTRAR “Introduzca el número de días: “
LEER días
diasRestantes=dias
MIENTRAS (diasRestantes>0) HACER
  SI (diasRestantes>366)
    SI ESBISIESTO(anoActual)
      diasRestantes=diasRestantes-366
    SINO
      diasRestantes=diasRestantes-365
      anos=anos+1
      anoActual=anoActual+1
    FIN SI
  SINO
    SI (diasRestantes>365)
      diasRestantes=diasRestantes-365
      anos=anos+1
      anoActual=anoActual+1
    SINO
      Índice=0
      MIENTRAS (diasRestantes>NDIAS(i))
        SI ESBISIESTO(anoActual) Y (índice=2)
          diasRestantes=diasRestantes-NDIAS(índice)-1
          meses=meses+1
          índice = índice + 1
        SINO
          Días= días + NDIAS(índice)
          diasRestantes = diasRestantes – NDIAS(índice)
          meses=meses + 1
          índice = índice +1
        FIN SI
      FIN MIENTRAS
      SI (diasRestantes>=7)
        Semanas=diasRestantes/7
        Días=RESTO(diasRestantes/7)
        diasRestantes=0 //Condición de finalización
      FIN SI
    FIN SI
  FIN SI
FIN MIENTRAS
MOSTRAR “El número de años es: “ anos
MOSTRAR “El número de meses es: “ meses
MOSTRAR “El número de semanas es: “ semanas
MOSTRAR “El número de días es: “ dias
FIN


#include <stdio.h>
int main() {
  int diasInicio=0,dias=0, meses=0,anos=0, semanas=0, anoActual=2011, diasRestantes=0;
  int indice=0;

  printf("Introduzca el número de días: ");
  scanf("%d",&diasInicio);

  diasRestantes=diasInicio;
  while (diasRestantes>0) {
    if (diasRestantes>=366) {
      if (esBisiesto(anoActual)) {
        diasRestantes=diasRestantes-366;
      }else {
        diasRestantes=diasRestantes-365;
      }
      anos=anos+1;
      anoActual=anoActual+1;
    }
    else {
      if ((diasRestantes==365)&&(!esBisiesto(anoActual))) {        
          diasRestantes=diasRestantes-365;
          anos=anos+1;
          anoActual=anoActual+1;
      }
      else {
        indice=1;
        while (diasRestantes>=diasMes(indice)) {
          if (esBisiesto(anoActual)&&(indice==2)) {
            diasRestantes=diasRestantes-diasMes(indice)-1;
            meses=meses+1;
            indice++;
          }
          else {
            dias=dias+diasMes(indice);
            diasRestantes=diasRestantes-diasMes(indice);
            meses=meses+1;
            indice++;
          }
        }
       
        if (diasRestantes>=7) {
          semanas=diasRestantes/7;
          dias=diasRestantes%7;
          diasRestantes=0;
        }
        else {
          dias=diasRestantes;
          diasRestantes=0;
        }
      }
    }
  }
 
  printf ("El número de años= %d\n", anos);
  printf ("El número de meses es= %d\n", meses);
  printf ("El número de semanas es= %d\n", semanas);
  printf ("El número de días es= %d\n", dias);

  return(0);
}

int esBisiesto(int ano) {
  if ((ano%4==0) && ((ano%400==0) || (ano%100!=0)))
    return 1;
  else
    return 0;
}

int diasMes(int mes) {
  short diasMeses[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
 
  return (diasMeses[mes-1]);
}

martes, 19 de julio de 2011

Pseudocódigo

Como paso previo a adentrarnos en la progamación en C, hemos estado desarrollando algoritmos para resolver ciertos problemas comunes mediante pseudocódigo. El objetivo fundamental es familiarizarse con las estructuras lógicas más utilizadas en programación (independientemente del lenguaje). Sin embargo, para quién no está habituado a programar puede resultar un poco abstracto resolver los problemas de este modo. Por eso he decidido mostrar algunos ejemplos de pseudocódigo acompañados por el correspondiente código en C. He tratado de utilizar las estructurar más comunes (if, while, for, switch).
INICIO
A=0, B=0
Leer A, B
SI A=B
Mostrar “Los números introducidos son iguales”
SINO
Mostrar “Los números introducidos no son iguales”
FIN

#include
int main() {
int a=0,b=0;

printf("Introduce el primer número: ");
scanf("%d",&a);
printf("Introduce el segundo número: ");
scanf("%d",&b);

if (a==b) printf("Los números introducidos son iguales\n");
else printf("Los números introducidos no son iguales\n");

return(0);
}
Pedir por teclado el número de mes y responder por pantalla el nombre del mes y el número de días que tiene(realizar para los 4 primeros meses)
INICIO
NUM_MES=0
MOSTRAR “Introduzca un número de mes(1-4):”
LEER NUM_MES
HACER EN CASO
EN CASO NUM=1:
MOSTRAR “El mes es enero y tiene 31 días”
EN CASO NUM=2:
MOSTRAR “El mes es febrero y tiene 28 días”
EN CASO NUM=3:
MOSTRAR “El mes es marzo y tiene 31 días”
EN CASO NUM=4:
MOSTRAR “El mes es abril y tiene 30 días”
SEA OTRO VALOR:
MOSTRAR “El número introducido no está en el rango indicado”
FIN

#include
int main() {
int num_mes=0;

printf("Introduzca un número de mes (1-4):");
scanf("%d",&num_mes);

switch(num_mes) {
  case 1:
    printf("El mes es enero y tiene 31 días\n");
    break;
  case 2:
    printf("El mes es febrero y tiene 28 días\n");
    break;
  case 3:
    printf("El mes es marzo y tiene 31 días\n");
    break;
  case 4:
    printf("El mes es abril y tiene 30 días\n");
    break;
  default:
    break;
  }
  return (0);
}
INICIO
NUM_MAX=0, NUM=0
MOSTRAR “Introduzca el número máximo:”
LEER NUM_MAX
MIENTRAS (NUM<=NUM_MAX) HACER MOSTRAR NUM NUM = NUM +1 FIN MIENTRAS FIN

#include <stdio.h>
int main() {
  int num_max=0, num=0;

  printf("Introduzca el número máximo: ");
  scanf("%d",&num_max);
  while (num<=num_max) {
    printf("%d ", num);
    num = num +1;
  }
  printf("\n");
  return(0);
}
Factorial de un número

INICIO
NUM_MAX=0, NUM=1, PROD=1
MOSTRAR “Introduzca el número: “
LEER NUM
MIENTRAS (NUM <= NUM_MAX) HACER
  PROD = PROD * NUM
  NUM = NUM + 1
FIN MIENTRAS
MOSTRAR “El factorial de NUM_MAX es: “ PROD
FIN

#include <stdio.h>
int main() {
  int num_max=0, num=1, prod=1;

  printf("Introduzca un número: ");
  scanf("%d",&num_max);

  while (num<=num_max) {
    prod = prod * num;
    num = num + 1;
  }
  printf ("El factorial de %d es: %d\n",num_max,prod);

  return(0);
}

INICIO
numMax=0
MOSTRAR “Introduzca el número hasta el que quiere contar: “
LEER numMax
PARA valor=0 HASTA numMax
MOSTRAR “El valor es: “ valor
FIN PARA

#include <stdio.h>
int main() {
  int numMax=0, valor=0;

  printf("Introduzca el número hasta el que quiere contar: ");
  scanf("%d",&numMax);

  for (valor=0; valor<=numMax; valor++) {
    printf("El valor es: %d\n", valor);
  }

  return(0);
}
Leer un número (entero y positivo, no hace falta comprobarlo) y determinar si es divisible por 5, 4, 3, 2, y 1 al mismo tiempo.

INICIO
Num=0
MOSTRAR “Introduzca un número: “
LEER Num
SI RESTO(Num/5)=0 Y RESTO(Num/4) =0 Y RESTO(Num/3)=0 Y RESTO(Num/2)=0
MOSTRAR “El número es divisible por 5,4,3,2 y 1”
SINO
MOSTRAR “El número no es divisible por 5,4,3,2 y 1”
FIN

(Solución alternativa)
INICIO
Num=0, Divisible=cierto
MOSTRAR “Introduzca un número: “
LEER Num
SI RESTO(Num/5) <> 0 Divisible=falso
SI RESTO(Num/4) <> 0 Divisible=falso
SI RESTO(Num/3) <> 0 Divisible=falso
SI RESTO(Num/2) <> 0 Divisible=falso
SI Divisible=cierto MOSTRAR “El número es divisible por 5,4,3,2 y 1”
SINO MOSTRAR “El número no es divisible por 5,4,3,2 y 1”
FIN
Indicar si un año es bisiesto.

INICIO
Ano=0;
MOSTRAR “Introducir el año: “
LEER Ano
SI RESTO(Ano/4)=0 Y ((RESTO(Ano/400) =0 Ó RESTO(Ano/100)<>0)) MOSTRAR “El año es bisiesto”
SINO MOSTRAR “El año no es bisiesto”
FIN

/* Código en C para comprobar si un año es bisiesto o no */
#include <stdio.h>
int main() {
  int ano=0;

  printf("Introducir el año: ");
  scanf("%d",&ano);

  if ((ano%4==0) && ((ano%400==0) || (ano%100!=0)))
    printf("El año es bisiesto\n");
  else
    printf("El año no es bisiesto\n");

  return(0);
}
Una compañía precisa de una administrativa.
A las candidatas se les realizan unas preguntas:
-¿Está soltera (1) o casado (2), otro (0)?
-¿Cantidad de hijos que tiene? Si no tiene indicar 0
-¿Posee algún título técnico S/N?
-¿Cuántos años tiene?
Serán preseleccionadas las que cumplan los siguientes requisitos:
+Mujeres solteras que estén en posesión de un título técnico, sin hijos y menores de 25 años.
+Mujeres casadas con edad superior a 40 años y con hijos
Tras introducir los datos indicar a la aspirante si está preseleccionada o no.

INICIO
estadoCivil=0,numHijos=0,titulo=”N”,anos=0
MOSTRAR “¿Está soltera(1), casada(2), otro(0)?”
LEER estadoCivil
MOSTRAR “¿Cantidad de hijos?”
LEER numHijos
MOSTRAR “¿Posee algún título técnico(S/N)?”
LEER titulo
MOSTRAR “¿Cuántos años tiene?”
LEER anos
SI ((estadoCivil=1) Y (numHijos=0) Y (titulo=”S”) Y (anos<25)) O ((estadoCivil=2) Y (edad>40) Y (numHijos>0)) MOSTRAR “Ha sido seleccionada”
SINO MOSTRAR “No ha sido seleccionada”
FIN

#include <stdio.h>
#include <string.h>
int main() {
  int estadoCivil=0, numHijos=0, anos=0;
  char titulo=' ', kk;

  printf("¿Está soltera(1), casada(2), otro(0)?");
  scanf("%d",&estadoCivil);
  printf("¿Cantidad de hijos?");
  scanf("%d",&numHijos);
  printf("¿Posee algún título técnico(S/N)?");
  scanf("%c",&kk);
  scanf("%c",&titulo);
  printf("¿Cuántos años tiene?");
  scanf("%d",&anos);

  if (((estadoCivil==1)&&(numHijos==0)&&(titulo=='S')) ||
     ((estadoCivil==2)&&(anos>40)&&(numHijos>0)))
     printf("Ha sido seleccionada\n");
  else
     printf("No ha sido seleccionada\n");

  return(0);
}

Solicitar por teclado un número entero entre 1 y 2000, y sacarlo por pantalla en números romanos.

INICIO
Num=0, Miles=0, Cientos=0, Decenas=0, Unidades=0, Aux=0
MOSTRAR  “Introduzca un número en el rango 1 a 2000”
LEER Num
MILES = Num/1000
Aux = RESTO(Num/1000)
CIENTOS = Aux/100
Aux = RESTO (Aux/100)
DECENAS = Aux/10
Aux = RESTO (Aux/10)
UNIDADES = Aux

//Mostrar los miles
PARA VALOR=1 HASTA MILES
        MOSTRAR “M”
FIN PARA

//Mostrar las centenas
HACER EN CASO
        EN CASO CIENTOS=1 MOSTRAR “C”
        EN CASO CIENTOS=2 MOSTRAR “CC”
        EN CASO CIENTOS=3 MOSTRAR “CCC”
        EN CASO CIENTOS=4MOSTRAR “CD”
        EN CASO CIENTOS=5 MOSTRAR “D"
        EN CASO CIENTOS=6 MOSTRAR “DC”
        EN CASO CIENTOS=7 MOSTRAR “DCC”
        EN CASO CIENTOS=8 MOSTRAR “DCCC”
        EN CASO CIENTOS=9MOSTRAR “CM”
FIN EN CASO
//Mostrar las decenas

HACER EN CASO
        EN CASO DECENAS =1 MOSTRAR “X”
        EN CASO DECENAS =2 MOSTRAR “XX”
        EN CASO DECENAS =3 MOSTRAR “XXX”
        EN CASO DECENAS =4MOSTRAR “XL”
        EN CASO DECENAS =5 MOSTRAR “L”
        EN CASO DECENAS =6 MOSTRAR “LX”
        EN CASO DECENAS =7 MOSTRAR “LXX”
        EN CASO DECENAS =8 MOSTRAR “LXXX”
        EN CASO DECENAS =9MOSTRAR “XC”
FIN EN CASO

//Mostrar las unidades
HACER EN CASO
        EN CASO UNIDADES =1 MOSTRAR “I”
        EN CASO UNIDADES =2 MOSTRAR “II”
        EN CASO UNIDADES =3 MOSTRAR “III"
        EN CASO UNIDADES =4MOSTRAR “IV”
        EN CASO UNIDADES =5 MOSTRAR “V”
        EN CASO UNIDADES =6 MOSTRAR “VI”
        EN CASO UNIDADES =7 MOSTRAR “VII”
        EN CASO UNIDADES =8 MOSTRAR “VIII”
        EN CASO UNIDADES =9MOSTRAR “IX”
FIN EN CASO
FIN

#include <stdio.h>
int main() {
  int num=0, miles=0, cientos=0, decenas=0, unidades=0, aux=0, i=0;

  printf ("Introduzca un número en el rango 1 a 3999: ");

  scanf("%d", &num);

  miles = num/1000;
  aux = num%1000;
  cientos=aux/100;
  aux=aux%100;
  decenas=aux/10;
  aux=aux%10;
  unidades=aux;

  printf ("El equivalente en números romanos es:  ");

  //Mostrar los miles
  for (i=1; i<=miles; i++) printf("%s","M");

  //Mostrar las centenas
  switch (cientos) {
    case 1:
      printf("%s","C");
      break;
    case 21:
      printf("%s","CC");
      break;
    case 3:
      printf("%s","CCC");
      break;
    case 4:
      printf("%s","CD");
      break;
    case 5:
      printf("%s","D");
      break;
    case 6:
      printf("%s","DC");
      break;
    case 7:
      printf("%s","DCC");
      break;
    case 8:
      printf("%s","DCCC");
      break;
    case 9:
      printf("%s","CM");
      break;
  }

  //Mostrar las decenas
  switch (decenas) {
    case 1:
      printf("%s","X");
      break;
    case 2:
      printf("%s","XX");
      break;
    case 3:
      printf("%s","XXX");
      break;
    case 4:
      printf("%s","XL");
      break;
    case 5:
      printf("%s","L");
      break;
    case 6:
      printf("%s","LX");
      break;
    case 7:
      printf("%s","LXX");
      break;
    case 8:
      printf("%s","LXXX");
      break;
    case 9:
      printf("%s","XC");
      break;
  }

  //Mostrar las unidades
  switch (unidades) {
    case 1:
      printf("%s","I");
      break;
    case 2:
      printf("%s","II");
      break;
    case 3:
      printf("%s","III");
      break;
    case 4:
      printf("%s","IV");
      break;
    case 5:
      printf("%s","V");
      break;
    case 6:
      printf("%s","VI");
      break;
    case 7:
      printf("%s","VII");
      break;
    case 8:
      printf("%s","VIII");
      break;
    case 9:
      printf("%s","IX");
      break;

  }
printf ("\n");
}

martes, 12 de julio de 2011

Almacenar datos en ficheros (I)


Hemos empezado a ver distintos modos de almacenar nuestra información utilizando sistemas informáticos. Durante los primeros intentos de crear bases de datos se utilizaban ficheros de texto. Dos de las técnicas utilizadas eran: asignar una longitud fija a cada campo almacenado, o separar los valores de los distintos campos por comas.
He decidido crear una pequeña aplicación en .NET con un formulario para recoger una serie de datos y, posteriormente, guardar dichos datos utilizando el formato seleccionado. Los ficheros generados se pueden importar para utilizarlos en otras aplicaciones destinadas al manejo y almacenamiento de datos (por ejemplo, sistemas gestores de bases de datos y hojas de cálculo).
La siguiente versión de la aplicación permitirá guardar, consultar y modificar los datos almacenados.
En la imagen siguiente se puede ver el formulario para introducir los datos.

A continuación se pueden ver los resultados obtenidos tras guardar los datos en los distintos formatos definidos (longitud de campos fija y valores separados por comas).


Finalmente, adjunto el código que permite realizar las operaciones requeridas para realizar la tarea que pretendemos.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

/* Método que se ejecuta al pulsar el botón Guardar datos */
private void btnGuardarDatos_Click(object sender, EventArgs e)
{
string cadena = "";
string nombre, apellidos, edad, localidad, codPostal, dni, apodo, fechaNac;
string telefono, numHijos, fumador, estatura, tallaZapato, peso, sueldo;
string lateralidad, comentarios;
string path = "";
FileStream fs = null;

/* Longitud fija de los campos */
if (cboFormato.Text.CompareTo("Longitud fija") == 0)
{
path = "FixedLength.txt";
nombre = txtNombre.Text.PadRight(15);
apellidos = txtApellidos.Text.PadRight(20);
edad = txtEdad.Text.PadRight(3);
localidad = txtLocalidad.Text.PadRight(20);
codPostal = txtCodPostal.Text.PadRight(5);
dni = txtDNI.Text.PadRight(9);
apodo = txtApodo.Text.PadRight(10);
fechaNac = txtFechaNac.Text.PadRight(8);
telefono = txtTelefono.Text.PadRight(9);
numHijos = txtNumHijos.Text.PadRight(2);
fumador = chkFumador.Checked == true ? "1" : "0";
fumador = fumador.PadRight(1);
estatura = txtEstatura.Text.PadRight(4);
tallaZapato = txtTallaZapato.Text.PadRight(2);
peso = txtPeso.Text.PadRight(5);
sueldo = txtSueldo.Text.PadRight(8);
lateralidad = cboLateralidad.Text.Substring(0, 1).PadRight(1);
comentarios = txtObservaciones.Text.PadRight(200);

cadena = nombre + apellidos + edad + localidad + codPostal + dni + apodo + fechaNac + telefono + numHijos;
cadena = cadena + fumador + estatura + tallaZapato + peso + sueldo + lateralidad + comentarios;

MessageBox.Show("*" + cadena + "*");
}

/* Campos separados por comas (CSV) */
if (cboFormato.Text.CompareTo("CSV") == 0)
{
path = "CSV.csv";
nombre = txtNombre.Text.Trim();
apellidos = txtApellidos.Text.Trim();
edad = txtEdad.Text.Trim();
localidad = txtLocalidad.Text.Trim();
codPostal = txtCodPostal.Text.Trim();
dni = txtDNI.Text.Trim();
apodo = txtApodo.Text.Trim();
fechaNac = txtFechaNac.Text.Trim();
telefono = txtTelefono.Text.Trim();
numHijos = txtNumHijos.Text.Trim();
fumador = chkFumador.Checked == true ? "1" : "0";
estatura = txtEstatura.Text.Trim();
tallaZapato = txtTallaZapato.Text.Trim();
peso = txtPeso.Text.Trim();
sueldo = txtSueldo.Text.Trim();
lateralidad = cboLateralidad.Text.Substring(0, 1);
comentarios = txtObservaciones.Text.Trim();

cadena = nombre + "," + apellidos + "," + edad + "," + localidad + "," + codPostal + "," + dni + "," + apodo + "," +
fechaNac + "," + telefono + "," + numHijos + "," + fumador + "," + estatura + "," + tallaZapato + "," + peso +
"," + sueldo + "," + lateralidad + "," + comentarios;

MessageBox.Show("*" + cadena + "*");
}

/* Almacenar los datos en un fichero XML */
if (cboFormato.Text.CompareTo("XML") == 0)
{
/* Próxima versión */
}

if (!File.Exists(path))
{
fs = File.Create(path);
fs.Close();
}
if (File.Exists(path))
{
StreamWriter sw = new StreamWriter(path);
sw.WriteLine(cadena);
sw.Close();
}
}

/* Método auxiliar que divide una cadena con campos de longitud fija y obtiene los
valores correspondientes a cada uno de los campos */
private void fixedLength2form(string cadenaLongFija)
{
string fumador, lateralidad;

fumador = cadenaLongFija.Substring(101,1);
lateralidad = cadenaLongFija.Substring(121,1);

txtNombre.Text = cadenaLongFija.Substring(0, 15); ;
txtApellidos.Text = cadenaLongFija.Substring(15, 20);
txtEdad.Text = cadenaLongFija.Substring(35, 3); ;
txtLocalidad.Text = cadenaLongFija.Substring(38, 20);
txtCodPostal.Text = cadenaLongFija.Substring(58, 5);
txtDNI.Text = cadenaLongFija.Substring(63, 9);
txtApodo.Text = cadenaLongFija.Substring(72, 10);
txtFechaNac.Text = cadenaLongFija.Substring(82, 8);
txtTelefono.Text = cadenaLongFija.Substring(90, 9);
txtNumHijos.Text = cadenaLongFija.Substring(99, 2);
chkFumador.Checked = fumador.CompareTo("1") == 0 ? true : false;
txtEstatura.Text = cadenaLongFija.Substring(102, 4);
txtTallaZapato.Text = cadenaLongFija.Substring(106, 2);
txtPeso.Text = cadenaLongFija.Substring(108, 5);
txtSueldo.Text = cadenaLongFija.Substring(113, 8);
if (lateralidad.CompareTo("D") == 0) cboLateralidad.SelectedIndex = 0;
if (lateralidad.CompareTo("Z") == 0) cboLateralidad.SelectedIndex = 1;
if (lateralidad.CompareTo("A") == 0) cboLateralidad.SelectedIndex = 2;
txtObservaciones.Text = cadenaLongFija.Substring(122, 200);

}

/* Método auxiliar que divide una cadena de campos separados por comas y obtiene los valores
correspondientes a cada uno de los campos almacenados */
private void csv2form(string cadenaCSV)
{
string[] aElementosCadena;
string lateralidad;

aElementosCadena = cadenaCSV.Split(',');
txtNombre.Text = aElementosCadena[0];
txtApellidos.Text = aElementosCadena[1];
txtEdad.Text = aElementosCadena[2];
txtLocalidad.Text = aElementosCadena[3];
txtCodPostal.Text = aElementosCadena[4];
txtDNI.Text = aElementosCadena[5];
txtApodo.Text = aElementosCadena[6];
txtFechaNac.Text = aElementosCadena[7];
txtTelefono.Text = aElementosCadena[8];
txtNumHijos.Text = aElementosCadena[9];
if (aElementosCadena[10].CompareTo("1") == 0) chkFumador.Checked = true;
else chkFumador.Checked = false;
txtEstatura.Text = aElementosCadena[11];
txtTallaZapato.Text = aElementosCadena[12];
txtPeso.Text = aElementosCadena[13];
txtSueldo.Text = aElementosCadena[14];
lateralidad = aElementosCadena[15];
if (aElementosCadena[15].CompareTo("D") == 0) cboLateralidad.SelectedValue = 0;
if (aElementosCadena[15].CompareTo("Z") == 0) cboLateralidad.SelectedValue = 1;
if (aElementosCadena[15].CompareTo("A") == 0) cboLateralidad.SelectedValue = 2;
txtObservaciones.Text = aElementosCadena[16];

}

/* Método que se ejecuta al pulsar el botón Abrir fichero. En este método se abre el fichero
que se corresponde con el método de almacenamiento elegido (longitud fija o valores separados
por comas), se lee la línea que almacena los datos y se obtienen los valores para cada uno
de los campos. */
private void btnAbrirFichero_Click(object sender, EventArgs e)
{
string path = "";
string linea = "";

if (cboFormato.Text.CompareTo("Longitud fija") == 0)
{
path = "FixedLength.txt";
if (File.Exists(path))
{
TextReader tr = new StreamReader(path);
linea = tr.ReadLine();
MessageBox.Show("La línea es: " + linea);
fixedLength2form(linea);
tr.Close();
}
}
if (cboFormato.Text.CompareTo("CSV") == 0)
{
path = "CSV.csv";
if (File.Exists(path))
{
TextReader tr = new StreamReader(path);
linea = tr.ReadLine();
csv2form(linea);
tr.Close();
}
}
}
}
}

viernes, 8 de julio de 2011

Proyecto biblioteca (en Linux bash)


Para aprovechar algún tiempo que me sobró durante la realización del proyecto de la biblioteca, decidí realizar el mismo proyecto sobre la consola de un sistema Linux utilizando bash. Esto me ha permitido recordar un poco la sintaxis de este lenguaje de scripting, del que ya tenía algo de conocimientos. Además, hay que decir que la potencia de los lenguajes de script en la consola de Linux son mucho más potentes que la de MS-DOS.
Para ahorrar tiempo he tratado de traducir directamente los scripts de un lenguaje a otro. En algunos casos la semejanza entre los dos códigos es evidente pero en otros es completamente inexistente. Sin embargo, la lógica es la misma en los dos casos y por tanto los diagramas serían aplicables en los dos casos.


COMPROBAR EXISTENCIA DE DIRECTORIOS
#!/bin/bash
if [ ! -d "LIBROS" ]
then
mkdir LIBROS
fi
if [ ! -d "PRESTAMOS" ]
then
mkdir PRESTAMOS
fi
if [ ! -d "LISTADOS" ]
then
mkdir LISTADOS
fi

MENÚ
#!/bin/bash
./ComprobarDirs.sh

while [ false ]; do

clear
echo "1) Añadir libro"
echo "2) Prestar libro"
echo "3) Listar todos (ordenados por signatura)"
echo "4) Listar todos (ordenados alfabéticamente)"
echo "5) Listar prestados"
echo "6) Listar amigos con préstamos"
echo "7) Devolver libros"
echo "8) Buscar libro"
echo "9) Salir"

echo -e "Elija una opción: \c"
read opcion
echo "La opción elegida es: $opcion"

if [ $opcion -eq 1 ]; then
./AnadirLibro.sh
fi
if [ $opcion -eq 2 ]; then
./PrestarLibro.sh
fi
if [ $opcion -eq 3 ]; then
./ListarLibSig.sh
fi
if [ $opcion -eq 4 ]; then
./ListarLibAlf.sh
fi
if [ $opcion -eq 5 ]; then
./ListarLibPrest.sh
fi
if [ $opcion -eq 6 ]; then
./ListarAmigosPrest.sh
fi
if [ $opcion -eq 7 ]; then
./DevolverLibros.sh
fi
if [ $opcion -eq 8 ]; then
./BuscarLibro.sh
fi
if [ $opcion -eq 9 ]; then
exit
fi

done

AÑADIR LIBROS
#!/bin/bash

echo -e "\nIntroduzca la signatura del libro: "
read signatura
echo -e "\nIntroduzca el título: "
read titulo
echo -e "\nIntroduzca el nombre del autor: "
read autor

fichero="$signatura.lib"
echo -e "$titulo - $autor" > "LIBROS/$fichero"
echo -e "El libro ha sido incluido en la biblioteca"

read -p "Pulse para continuar..."


PRESTAR LIBROS
#!/bin/bash
echo -e "Introduzca el título del libro: "
read titulo
echo -e "Introduzca el nombre del autor: "
read nombreAutor
echo -e "Introduzca el nombre de su amigo: "
read nombreAmigo

fecha=`date +"%m/%d/%Y"`
echo -e "$titulo - $nombreAutor $fecha" > "PRESTAMOS/$nombreAmigo.pre"
echo -e "\nEl préstamo ha sido guardado"

read -p "Pulse para continuar..."

LISTAR LIBROS POR SIGNATURA
#!/bin/bash
if [ -f LISTADOS/ListadoLibrosSig.txt ]; then
rm LISTADOS/ListadoLibrosSig.txt
fi
for f in $( ls LIBROS/*.lib | sort ); do
# nombreLargo=${f%.*}
# nombre=${nombreLargo##*/}
lineaFichero=`cat $f`
titulo=${lineaFichero%-*}
#echo -e "$titulo"
echo -e "$titulo" >> LISTADOS/ListadoLibrosSig.txt
done

echo -e "\n******************************************"
echo -e "+++ LISTADO LIBROS POR SIGNATURA +++"
echo -e "******************************************"
cat LISTADOS/ListadoLibrosSig.txt

read -p "Pulse para continuar..."

LISTAR LIBROS ALFABÉTICAMENTE
#!/bin/bash
if [ -f LISTADOS/ListadoLibAlf.txt ]; then
rm LISTADOS/ListadoLibAlf.txt
fi

echo -e "************************************************"
echo -e "+++ LISTADO LIBROS ORDENADOS ALFABÉTICAMENTE +++"
echo -e "************************************************"
for f in $( ls LIBROS/*.lib ); do
lineaFichero=`cat $f`
titulo=${lineaFichero%-*}
echo -e "$titulo" >> LISTADOS/ListadoLibAlf.txt
done
cat LISTADOS/ListadoLibAlf.txt | sort > kk.tmp
mv kk.tmp LISTADOS/ListadoLibAlf.txt
cat LISTADOS/ListadoLibAlf.txt

read -p "Pulse para continuar..."

LISTAR AMIGOS CON PRÉSTAMOS
#!/bin/bash
if [ -f LISTADOS/ListadoAmigosPrest.txt ]; then
rm LISTADOS/ListadoAmigosPrest.txt
fi

for f in $( ls PRESTAMOS/*.pre | sort ); do
ruta=${f##*/}
nombreAmigo=${ruta%.*}
echo -e "$nombreAmigo" >> LISTADOS/ListadoAmigosPrest.txt
done

echo -e "\n**************************************************"
echo -e "+++ LISTADO ALFABÉTICO DE AMIGOS CON PRÉSTAMOS +++"
echo -e "**************************************************"

cat LISTADOS/ListadoAmigosPrest.txt

read -p "Pulse para continuar..."

DEVOLVER LIBROS
#!/bin/bash
#Obtenemos el nombre del amigo que devuelve los libros y eliminamos del
#directorio PRESTAMOS el archivo cuyo nombre se corresponede con el de
#dicho amigo
echo -e "Introduzca el nombre del amigo: "
read amigo

if [ -f "PRESTAMOS/$amigo.pre" ]; then
rm "PRESTAMOS/$amigo.pre"
echo -e "Los libros han sido devueltos"
else
echo -e "El amigo no existe o no tiene libros prestados\n"
fi
read -p "Pulse para continuar..."

BUSCAR LIBROS
#!/bin/bash
echo -e "Introduzca el título a buscar: "
read tituloBuscado

cat LIBROS/*.lib |grep "$tituloBuscado" >temp.tmp
encontrado=`stat -c%s "temp.tmp"`

if [ $encontrado -eq 0 ]; then
echo -e "No se ha encontrado el libro indicado\n"
else
echo -e "El libro se encuentra en la biblioteca\n"
fi
rm temp.tmp
read -p "Pulse para continuar..."

jueves, 7 de julio de 2011

Proyecto biblioteca (en MS-DOS)


En las últimas clases hemos tenido que crear un pequeño proyecto para poner en práctica el primer módulo del curso. Para ello hemos hecho un programa para la consola de comandos de MS-DOS que gestione una biblioteca.
El primer paso fue realizar un diagrama con la funcionalidad del programa para facilitar posteriormente la etapa de codificación. Para realizar esta tarea descubrí una herramienta online muy interesante (http://www.gliffy.com/). A continuación muestro los diagramas más genéricos realizados sobre la aplicación.


Una vez finalizada la etapa de planificación, era el momento de empezar a programar.
El primer paso es comprobar si existe la estructura de directorios, y si no es así crearla:

COMPROBAR EXISTENCIA DE DIRECTORIOS
@echo off
REM Comprobar la existencia de los directorios LIBROS, PRESTAMOS y LISTADOS
REM y, en caso de no existir, crearlos
echo ComprobarDirs 1
if not exist LIBROS md LIBROS
if not exist PRESTAMOS md PRESTAMOS
if not exist LISTADOS md LISTADOS
echo ComprobarDirs 2

Después se crea el menú principal mostrando las opciones que ofrece el programa y esperando por la elección del usuario:

MENÚ
@echo off
:inicio
call ComprobarDirs.bat
cls
echo 1) Anadir libro
echo 2) Prestar libro
echo 3) Listar todos (ordenados por signatura)
echo 4) Listar todos (ordenados alfabeticamente)
echo 5) Listar prestados
echo 6) Listar amigos con prestamos
echo 7) Devolver libros
echo 8) Buscar libro
echo 9) Salir

set /p opcion=Elija una opcion:
echo.

REM Opcion 1 (añadir libro)
if %opcion%==1 call AnadirLibro.bat
REM Opcion 2 (prestar libro)
if %opcion%==2 call PrestarLibro.bat
REM Opcion 3 (listar libros por signatura)
if %opcion%==3 call ListarLibSig.bat
REM Opcion 4 (listar libros alfabeticamente)
if %opcion%==4 call ListarLibAlf.bat
REM Opcion 5 (listar libros prestados)
if %opcion%==5 call ListarLibPrest.bat
REM Opcion 6 (listar amigos con prestados)
if %opcion%==6 call ListarAmigosPrest.bat
REM Opcion 7 (devolver libros)
if %opcion%==7 call DevolverLibros.bat
REM Opcion 8 (buscar libro)
if %opcion%==8 call BuscarLibro.bat
REM Opcion 9 (salir del programa)
if %opcion%==9 goto salir

goto inicio
:salir
echo Saliendo del programa...

A continuación se crean cada uno de los archivos .bat para realizar cada una de las tareas:

AÑADIR LIBROS
@echo off
REM Obtener signatura, título y autor del libro
set /p signatura=Introduzca la signatura del libro:
set /p titulo=Introduzca el titulo:
set /p autor=Introduzca el nombre del autor:

REM Crear un fichero "signatura.lib" y guardar en el
REM título - nombre autor
echo %titulo% - %autor% > .\LIBROS\%signatura%.lib
echo El libro ha sido incluido en la biblioteca
pause

PRESTAR LIBROS
@echo off
REM Obtenemos los parámetros titulo, nombreAmigo y fecha actual
set /p titulo=Introduzca titulo del libro:
set /p nombreAutor=Introducir nombreAutor:
set /p nombreAmigo=Introduzca el nombre de su amigo:
for %%A in (%Date%) do set fecha=%%A

REM Creamos el fichero "NombreAmigo.pre" y guardamos en el los
REM valores Título, nombreAmigo y fecha
echo %titulo% - %nombreAutor% - %fecha% > .\PRESTAMOS\%nombreAmigo%.pre
echo El prestamo ha sido guardado
pause

LISTAR LIBROS POR SIGNATURA
@echo off
REM Obtenemos todos los archivos de la carpeta libros
if exist .\LISTADOS\listadoLibrosAlf.txt del .\LISTADOS\listadoLibrosAlf.txt

SETLOCAL EnableDelayedExpansion
cd
for /f "tokens=1" %%G in ('dir /b LIBROS\*.lib') do (
set k=LIBROS/%%G
for /f "tokens=1 delims=-" %%A in (!k!) do echo a: %%A
echo %%H >> .\LISTADOS\listadoLibrosAlf.txt
)
echo.
echo El listado solicitado ha sido realizado y guardado en disco
echo.
pause

LISTAR LIBROS ALFABÉTICAMENTE

@echo off
REM Obtenemos todos los archivos de la carpeta libros
if exist .\LISTADOS\listadoLibrosAlf.txt del .\LISTADOS\listadoLibrosAlf.txt
for %%G in (.\LIBROS\*.lib) do (
for /f "tokens=1 delims=-" %%H in (%%G) do echo %%H >> .\LISTADOS\listadoLibrosAlf.txt
)
sort .\LISTADOS\listadoLibrosAlf.txt > temp.txt
move temp.txt .\LISTADOS\listadoLibrosAlf.txt
type .\LISTADOS\listadoLibrosAlf.txt
echo.
echo El listado solicitado ha sido realizado y guardado en disco
echo.
pause

LISTAR AMIGOS CON PRESTAMOS
@echo off
REM Obtener archivos de la carpeta prestamos y mostrar el nombre del archivo sin
REM extensión
if exist .\LISTADOS\listadoAmigosPrest.txt del .\LISTADOS\listadoAmigosPrest.txt
for /f "tokens=1 delims=." %%G in ('dir /b PRESTAMOS\*.pre') do echo %%G >> .\LISTADOS\listadoAmigosPrest.txt
type .\LISTADOS\listadoAmigosPrest.txt
pause

DEVOLVER LIBROS
@echo off
REM Obtener el nombre del amigo que devuelve los libros
set /p amigo=Introduzca el nombre del amigo:
REM Eliminar de la carpeta PRESTAMOS el archivo correspondiente al amigo indicado
del .\PRESTAMOS\%amigo%.pre 2> nul
echo Los prestamos indicados han sido eliminados
pause

BUSCAR LIBROS

@echo off
REM Buscar en el directorio LIBROS si alguno de los ficheros contiene el título seleccionado
REM Obtenemos el título a consultar
set /p titulo=Introduzca el titulo a buscar:
for /f %%G in ('dir /b .\LIBROS\*.lib') do (
for /f "tokens=2 delims=:" %%H in ('find /c ^"%titulo%^" .\LIBROS\%%G') do (
if %%H gtr 0 (
goto hayLibros
)
)
)
goto noHayLibros
:hayLibros
echo.
echo En la biblioteca existe algun libro con ese titulo
echo.
goto salir
:noHayLibros
echo En la biblioteca no existe ningun libro con ese titulo
:salir
pause

viernes, 1 de julio de 2011

Pendrive protegido contra escritura

Recuerdo que hace ya algún tiempo me pasó lo mismo que me pasó ayer (se le llama tropezar dos veces con la misma piedra). Tuve un problema con una memoria USB que consistía en que al intentar modificar su contenido el sistema operativo mostraba una ventana indicando que no se podía realizar la operación porque el dispositivo estaba protegido contra escritura. Ayer recordé que ya había pasado por ello, pero no recordaba como lo había solucionado. Lo primero que hice fue buscar en Google y, como siempre, hay respuestas para todos los gustos (es un virus, hay que instalar una aplicación que resuelve el problema, introduce tu número de móvil que ya te mostramos la solución, modifica el registro, etc.) y en este caso ninguna de las soluciones que me parecían factibles funcionó. Como tenía un poco de prisa en aquel momento no insistí. Sin embargo, hoy me he puesto a indagar con más calma y he dado con la solución.
El primer problema está resuelto y para resolver el segundo he decidido publicar una entrada en el blog explicando la solución que funciona por si vuelve a ocurrirme lo mismo.

La solución del problema es muy sencilla:
1.- Hay que acceder al registro ejecutando el comando regedit y aparecerá una nueva ventana con el editor de registro de Windows.
2.- En el panel de la izquierda debemos ir seleccionando consecutivamente las siguientes ramas del árbol:
     HKEY_LOCAL_MACHINE -> System -> CurrentControlSet -> Control -> StorageDevicePolicies
y una vez seleccionada la ruta completa debería verse lo mismo que se muestra en la imagen. En caso de que existiese algún valor adicional debería ser eliminado, es decir, si en el panel derecho del editor hay alguna entrada más aparte de la mostrada en la imagen (Default    REG_SZ    value not set) debe ser eliminada (pulsando el botón derecho del ratón sobre Default y seleccionando Eliminar). Una vez hecho esto se puede cerrar el editor del registro y el problema debería estar solucionado.


RAID

En la actualidad el uso de sistemas RAID de almacenamiento está bastante instaurado, fundamentalmente en lugares donde la necesidad de gran cantidad de espacio de almacenamiento es vital. En los siguientes enlaces se explica detalladamente en que consiste esta técnica, los distintos tipos y las ventajas que ofrece sobre los discos sistemas normales de almacenamiento (los discos simples).

http://www.monografias.com/trabajos6/sira/sira.shtml

http://bytepile.com/raid_class.php

Además en los siguientes enlaces se puede obtener información acerca de los sistemas de almacenamiento de datos más utilizados en la actualidad.

http://www.e-abaco.net/2009/05/11/tecnologias-de-almacenamiento-de-red-san-nas-das/

http://www.act.cl/web/Productos/Infraestructura/Storage/SistemadeAlmacenamientoenCintas/tabid/225/language/es-CL/Default.aspx