====== Examen Parcial - 75.08 Sistemas Operativos - 25/06/2009 ======
**Cátedra:** Clúa
**Fecha:** 1er Oportunidad - 1er Cuatrimestre 2009
**Día:** 26/06/2009
**Tema:** Perl (Tema 1)
Esta página está incompleta; podés ayudar completando el material.
===== Enunciado =====
Leer un archivo de input cuyo nombre es pasado como parámetro y cuyo separador es pasado como parámetro (parámetros uno y dos respectivamente).
Sumar las cantidades por producto usando una estructura hash (el campo producto es el que se emplea como clave y el campo cantidad es el que se debe acumular).
Grabar un archivo de salida denominado <"nombre">**.sal** (este <"nombre"> debe ser solicitado por standard input) los productos con cantidad acumulada superior a 1000.
Como el formato del archivo de entrada es desconocido, además se deben pasar como parámetros la ubicación del campo producto y la ubicación del campo cantidad.
Ejemplo: para el archivo datos.prd, con separador coma y formato: fecha factura cliente cantidad producto precio, la invocación correcta es: **datos.prd , 5 4**
__**Condiciones para la resolución:**__
1 Que el archivo de entrada exista, se pueda leer, tenga al menos 2 campos y no este vacio.
2 Que los parámetros de ubicación deteminen ubicaciones válidas y distintas [Ejemplo de invocaciones erróneas: datos.prd , 4 4 (porque son iguales) o datos.prd , 7 4 (porque el archivo de input tiene solo 6 campos)]
3 Que sean 4 parámetros, si se pasan más ignorar los que sobran, si se pasan menos es error.
\ Parámetro 1: Nombre del archivo de Input
\ Parámetro 2: Separador del archivo de Input
\ Parámetro 3: Ubicación del campo producto
\ Parámetro 4: Ubicación del campo cantidad
4 Si se verifica alguno de estos errores mostrar por pantalla un mensaje descriptivo del error y cancelar el programa.
5 No usar archivos auxiliares, comandos Unix (bajo ningún concepto) ni expresiones regulares (excepto las expresiones regulares simples de las funciones predefinidas de perl).
6 Abrir y cerrar adecuadamente los archivos. En todos los archivos (input y output) el separador de registros es el new line.
===== Resolución =====
#!/usr/bin/perl -w
################################################################
# AUTOR: Maximiliano Milicich (maximiliano.milicich@gmail.com)
################################################################
if ($#ARGV < 3) {
print "Sintaxis incorrecta: debe informar al menos 4 parametros.".$/;
exit 1;
}
$nombrearch_input = $ARGV[0];
$separador = $ARGV[1];
$poscampo_prod = $ARGV[2];
$poscampo_cant = $ARGV[3];
# Validacion de los parms de entrada:
if ($poscampo_prod == $poscampo_cant || $poscampo_prod <= 0 || $poscampo_cant <= 0) {
print "Error: Posicion de campo cantidad y producto deben ser mayores a cero y no pueden ser iguales".$/;
exit 1;
}
open(ARCH_IN, '<'.$nombrearch_input) || die "No se pudo abrir el archivo $nombrearch_input";
close(ARCH_IN);
if ($separador =~ /^\s*$/) {
print "Separador no puede ser vacio".$/;
exit 1;
}
# Definimos la minima cant de campos q va a necesitar cada registro, en base a los parms de entrada:
if ($poscampo_prod > $poscampo_cant) {
$min_cantcampos = $poscampo_prod;
}
else {
$min_cantcampos = $poscampo_cant;
}
# Pedimos al usuario nombre de archivo de salida:
$nombrearch_output = '';
while ($nombrearch_output =~ /^\s*$/) {
print "Ingrese el nombre del archivo de salida: ";
$nombrearch_output = ;
}
chomp($nombrearch_output);
$nombrearch_output = $nombrearch_output.'.sal';
# Procesamos la data del archivo:
open(ARCH_IN, '<'.$nombrearch_input) || die "No se pudo abrir el archivo $nombrearch_input";
%totalcantxprod = ();
while ($linea = ) {
if ($linea =~ /^\s*$/) {
next;
}
@campos = split(/$separador/, $linea);
$cantcampos = $#campos + 1;
if ($cantcampos < $min_cantcampos) {
print "Error: Los registros del archivo $nombrearch_input deben tener al menos $min_cantcampos campos".$/;
close(ARCH_IN);
exit 1;
}
$totalcantxprod{$campos[$poscampo_prod -1]} += $campos[$poscampo_cant -1];
}
close(ARCH_IN);
# Armamos la Salida:
open(ARCH_OUT, ">$nombrearch_output") || die "No se pudo abrir archivo output $nombrearch_output";
foreach $prod (keys(%totalcantxprod)) { # Otra opcion para esto (mas cortita) es : while (($prod, $cant) = each %totalcantxprod) { ... }
$cant = $totalcantxprod{$prod};
if ($cant > 1000) {
print ARCH_OUT $prod.$/;
}
}
close(ARCH_OUT);
# Llamadas a Sistema Operativo!
# Con esto vemos el resultado y borramos el archivo, asi podemos volver a testear la corrida :-)
system("cat $nombrearch_output");
system("rm $nombrearch_output");
===== Ejemplo de uso =====
$ script.pl datos.ent , 2 3
Archivo datos.ent
lala,ZANAHORIA,100,lala
lala,ZANAHORIA,100,lala
lala,PEPINO,100,lala
lala,KANIKAMA,500,lala
lala,ZANAHORIA,100,lala
lala,PEPINO,100,lala
lala,TOFU,100,lala
lala,ZANAHORIA,100,lala
lala,KANIKAMA,500,lala
lala,ZANAHORIA,100,lala
lala,PEPINO,100,lala
lala,ZANAHORIA,100,lala
lala,PEPINO,100,lala
lala,KANIKAMA,500,lala
lala,PEPINO,800,lala
Resultado:
* PEPINO
* KANIKAMA
===== Discusión =====
Si ves algo que te parece incorrecto en la resolución y no te animás a cambiarlo, dejá tu comentario acá.