<?xml version="1.0" encoding="utf8"?>
<!DOCTYPE html
	PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=uft8">
   <META NAME="DATE" CONTENT="11/2/2003">
   <META NAME="Author" CONTENT="J. J. Merelo">
   <META NAME="Description" CONTENT="Tutorial de PERL en castellano, con ejemplos y ejercicios">
   <META NAME="Keywords" CONTENT="curso de perl, tutorial de perl, manual de perl, programacion"> 
   <TITLE>Tutorial de Perl:  Ahorrando energ&iacute;as  </TITLE>
<script language="JavaScript">
var contador = 1;
var contadores= new Array;
function multicontador(  numero ) {
      if ( ! contadores[ numero ]  )
          contadores[ numero ] = 1;
      else
          contadores[numero ]++;
      document.write( contadores[numero] );
};

</script>
<link rel ='stylesheet' type = "text/css" href = "perl.css">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#ffffff" LINK="#0000FF" VLINK="#551A8B" ALINK="#FF0000">
<TABLE  align=center cellpadding=5 bgcolor='darkseagreen'>
	<tr>

	<td>
			 <!-- Atomz.com Search HTML for Tutorial de PERL en castellano -->
	  <form method="get" action="http://search.atomz.com/search/">
	    <input size=25 name="sp-q"><br /><input type=submit value="Busca en el tutorial">
	    <input type=hidden name="sp-a" value="0002147b-sp00000001">
	  </form>
	</td>

	<td align='center'>
			<h1><a href='indice.html'>Tutorial de <strong>PERL</strong> en castellano </a>: Ahorrando energ&iacute;as</h1>
	</td>

    <td align='right' valign='top'><a href='tutoperl16.html'> Preguntas frecuentemente preguntadas</a><br><a href='tutoperl17.html'> Bibliograf&iacute;a.</a><br><a href='tutoperl18.html'> Recursos Internet</a><br><a href='tutoperl7.html'> Recordando, que es gerundio</a><br></td>
	</tr>
</table>

<h3>Operadores, matrices y la variable por defecto <code>$_</code></h3>



<P>Como nuestro pol&iacute;tico corrupto, por su experiencia en el ramo
de la construcci&oacute;n, ha sido nombrado delegado de Obras P&uacute;blicas,
tiene que pasar la mayor parte del tiempo visitando carreteras, caminos,
puentes y veredas. Nada mejor, pues, que comprar un port&aacute;til <a 
href=http://www.amd.com target=_new>AMD K6-2</a> para ir introduciendo las mordidas en el propio lugar donde se originen.
El problema es el limitado rango de las bater&iacute;as, que hacen que
si hay que viajar de Albacete a Cuenca, se gaste la bater&iacute;a a la
altura de Motilla del Palancar. Para ahorrar energ&iacute;a, decide modificar
su programa de forma que escriba menos en el disco; es decir, que cargue
todos los datos en memoria, y los guarde s&oacute;lo cuando termine el
bucle. Adem&aacute;s, para no poner la excusa a la comisi&oacute;n del
Congreso (que ya pide Anguita a voces) de que no se acuerda de nada, decide
grabar tambi&eacute;n las fechas y horas de los sucesos. Escribe, con su
pericia creciente en <strong>Perl</strong>, el programa <a href='memoria.pl.html'><code>memoria.pl</code></a>
(listado 3).</P>

<table class=listado align=center cellspacing=0 border=0
cellpadding=1><tr><td bgcolor=black><table cellspacing=0 border=0 cellpadding=2 width=100%><tr><td bgcolor=white><pre><font size=+2>1&nbsp;<font color=blue>until</font>(0) {
2&nbsp;     <font color=red>print</font> "Cliente\n";
3&nbsp;     <font color=red>chop</font>( <font color=green>$paganini</font> = &lt;STDIN&gt;);
4&nbsp;     <font color=blue><font color=blue>last</font></font> <font color=blue>if</font> !<font color=green>$paganini</font>;
5&nbsp;     <font color=red>print</font> "Valor inmueble\n";
6&nbsp;     <font color=red>chop</font>(<font color=green>$valor</font> = &lt;STDIN&gt;);
7&nbsp;     <font color=green>$comision</font> = <font color=green>$valor</font> * 0.25;
8&nbsp;     (<font color=green>$seg</font>, <font color=green>$min</font>, <font color=green>$hora</font>, <font color=green>$dia</font>, <font color=green>$mes</font>, <font color=green>$anho</font>, <font color=green>@zape</font>) = <font color=red>localtime</font>(<font color=red>time</font>);
9&nbsp;     <font color=green>$mes</font>++;
10&nbsp;     <font color=green>$anho</font>+=1900;
11&nbsp;     <font color=green>$zipi</font> = "<font color=green>$paganini</font> <font color=green>$comision</font> <font color=green>$hora</font>:<font color=green>$min</font> <font color=green>$dia</font>/<font color=green>$mes</font>/<font color=green>$anho</font>\n";
12&nbsp;     <font color=red>push</font>( <font color=green>@mem</font>, <font color=green>$zipi</font> );     
13&nbsp;};
14&nbsp;
15&nbsp;<font color=red>open</font> (MANTA,"&gt;clientes.mas");
16&nbsp;<font color=blue>foreach</font> (<font color=red>sort</font> <font color=green>@mem</font> ) {
17&nbsp;     <font color=red>print</font> MANTA;
18&nbsp;}
19&nbsp;<font color=red>close</font> (MANTA);
</font></pre>

</td></tr></table></td></tr><caption><font face="arial,helvetica">Listado <script>multicontador(1);</script>: Programa memoria.pl</font></caption></table>


<P>En esta peque&ntilde;a modificaci&oacute;n del programa anterior, y
en la l&iacute;nea 8, se introduce una nueva estructura de <strong>Perl</strong>: el <I>array</I>
o lista. Un <I>array</I> se indica con el s&iacute;mbolo @ (arroba), aunque
a cada elemento de un array nos referiremos con la notaci&oacute;n <code>$mem[0]</code>,
ya que es un escalar. En general, tanto los operadores como las funciones
en <strong>Perl</strong> se comportan de forma diferente si se trata de un entorno <I>escalar</I>
o si se trata de un entorno de <I>lista</I> o vectorial. En este caso,
el operador <code>localtime</code> devuelve una lista compuesta
por los segundos, minutos y demas, tom&aacute;ndolo de la funci&oacute;n
time que devuelve el n&uacute;mero de segundos transcurridos desde hace
mucho tiempo (1970, para ser exactos). Adem&aacute;s, estamos utilizando
la lista <code>@zape</code> para contener el resto de los
elementos de la hora, que no nos interesan (ser&iacute;an el d&iacute;a
de la semana y cosas as&iacute;). Por supuesto, tambi&eacute;n se podr&iacute;a
haber hecho de otra forma, mucho m&aacute;s larga<pre>
<code>@fecha= localtime(time);
$seg = $fecha[0];
...</code></pre>
<p>Las matrices empiezan en <strong>Perl</strong> en 0 habitualmente,
como sucede en C; pero esto se puede cambiar (usando la variable global
<code>$[</code>). Hay que tener cuidadito con la variable
<code>$anho</code>, que devuelve, al contrario de lo que se pudiera
pensar, el n&uacute;mero de años transcurridos desde 1900. Eso da lugar a
todo tipo de pequeños efectos 2000, que todavía se ven por alg&uacute;n sitio 
Web. Por eso, en la línea 10, se le suma 1900, para que dé el año
actual con cuatro cifras. Tal como en el lenguaje C,
<code>$anho+=1900</code> equivale a <code>$anho=$anho+1900</code>;
</p>

<P>En la l&iacute;nea 12 hay un nuevo operador, <code>push</code>.
Este operador hace precisamente eso, achuchar un escalar o una lista al
principio de otra lista (recordad que lista y <I>array </I>son pr&aacute;cticamente
sin&oacute;nimos). En este caso, estamos metiendo la cadena que hemos creado,
<code>$zipi</code>, al principio de la matriz <code>@mem</code>
(que, por cierto, tampoco hemos tenido que declarar ni dimensionar). Si
queremos eliminar el primer componente de una matriz, se hace con el operador
obvio, <code>$cadena = pop(@mem);</code>

<P>En la l&iacute;nea 16 aparece una nueva orden de control de bucle: <code>foreach</code>,
<I>para cada</I>, que repite el cuerpo del bucle para cada uno de los elementos
de la lista que hay contenida entre par&eacute;ntesis. Se puede abreviar
por <code>for</code>, aunque tambi&eacute;n se puede comportar
como lo hace en C. &iquest;Y cu&aacute;l es la lista a la que se aplica?
La que hemos creado anteriormente, pero por orden (de ah&iacute; el <code>sort</code>).
En este caso la ordenar&aacute; por orden alfab&eacute;tico, saliendo algo
como esto
<pre><code>Uno 750 12:0 31/1/2000
otro 1402654 12:0 31/1/2000
otro mas 4020267 12:1 31/1/2000
y otro mas todavia 4040.25 12:1 31/1/2000
</code></pre>

<P>Sin embargo, dentro del bucle no parece que pase nada; y, &iquest;d&oacute;nde
diablos se ha metido la variable de bucle?. Lo que ocurre es que en estos
casos <strong>Perl</strong> tiene una <I>variable por defecto</I>, <code>$_</code>,
que es la variable de bucle por defecto y sobre la que act&uacute;an los
operadores y funciones tambi&eacute;n por defecto. Es decir, que el bucle
anterior equivaldr&iacute;a a<pre>
<code>foreach $_ (sort @mem) {
    print MANTA $_;
}</code>
</pre>

<P>Y aunque s&eacute; que ya est&aacute;is esperando que lo diga, se puede
hacer de otra forma, esta vez menos <strong>Perl</strong>&iacute;stica; utilizando bucles
normales y corrientes<pre>
for ($i = 0; $i&lt;=$#mem; $i++) {
    print MANTA $mem[$i];
}</pre>
<p>si bien en este caso el fichero de salida
no estar&aacute; ordenado. En este caso se utiliza la construcci&oacute;n
<code>$#&lt;nombre de matriz></code>, que devuelve el &uacute;ltimo
&iacute;ndice existente para esa matriz. Ojo, se trata del &uacute;ltimo
&iacute;ndice, no del n&uacute;mero de elementos de la matriz; por eso
los bucles en <strong>Perl</strong> usan un <code>&lt;=</code> para terminar.
</p>

<p><table class=ejercicio width=100% cellpadding=2 cellspacing=0 border=0>
    <tr><td bgcolor=green><table width=100% bgcolor=white cellspacing=0 cellpadding = 6><tr>
<td><ol>
<li>  Hacer un programa que imprima su entrada estándar en orden
inverso,empezando por la &uacute;ltima línea y acabando por la primera. Se
ejecutará con <pre> 
unix% cat &lt;nombre del fichero&gt; ¦invert.pl</pre>
<em>Pistas</em>Usar la orden pop, que extrae el primer elemento de un array. <em>Reto</em> Hacerlo en una sola línea.</li>

<li> $. es una variable que contiene la línea del fichero de la que se
está leyendo. Teniendo esto en cuenta, crear un filtro (es decir, un
programa que lea de entrada estándar y escriba en salida estándar, tal 
como el anterior) que
imprima un fichero con el n&uacute;mero de línea al principio de cada
una.</li> 

<li> Hacer un histo(pro)gra, es decir, un programa que recoja una serie de valores
numéricos (con valores reales entre 0 y 100), los distribuya en cinco cubos (del 0 al 20, entre 20 y 40, y así
sucesivamente), calcule las frecuencias de cada uno de los cubos, e imprima barras
horizontales cuya longitud es función de la frecuencia.</li>
</td></tr></table></td></tr><caption><font face="arial,helvetica">Ejercicios <script>multicontador(3);</script></font></caption></table></p>


<TABLE  align=center cellpadding=5 bgcolor='darkseagreen'><tr><td>[<a href='tutoperl16.html'> Preguntas frecuentemente preguntadas</a>] [<a href='tutoperl17.html'> Bibliograf&iacute;a.</a>] [<a href='tutoperl18.html'> Recursos Internet</a>] [<a href='tutoperl7.html'> Recordando, que es gerundio</a>] </td></tr></table>

</BODY>
</HTML>
