====== 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á.