• Publicidad

Problema en subrutinas

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Problema en subrutinas

Notapor perliña » 2013-05-12 09:40 @444

¡Buenas!

Estoy haciendo un programa en el cual, a partir de un elemento de una matriz, quiero saber la suma de los elementos de su alrededor para, a partir de ella, determinar unas condiciones, todo ello, imprimido en un documento .txt.

Yo creo que fallan las subrutinas, ya que no me las imprime.
Esto es lo que tengo hasta ahora:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. @fila0=(0,0,0,0,0,0);
  2. @fila1=(0,1,0,1,1,0);
  3. @fila2=(0,1,1,0,0,0);
  4. @fila3=(0,1,1,0,1,0);                          
  5. @fila4=(0,1,0,1,1,0);
  6. @fila5=(0,0,0,0,0,0);
  7. $nombre="vida.txt";
  8.  
  9. open(AA,">$nombre") || die "cannot open the file: $!";
  10. print AA "GENERACIÓN 0\n";
  11.  
  12. print AA "@fila1\n";
  13. print AA "@fila2\n";
  14. print AA "@fila3\n";
  15. print AA "@fila4\n";
  16.  
  17.  
  18. print AA "GENERACIÓN 1\n";
  19. my @d1=(0);    
  20. my @d2=(0);
  21. my @d3=(0);
  22. my @d4=(0);
  23. $i=1;
  24.  
  25. while ($i<=4) {@a=@fila1,@b=@fila0,@e=@fila2;suma();@b=@d1,@e=@fila1;sust();$i++;}
  26.  
  27. while ($i<=4) {suma(@a=@fila2,@fila1,@fila3);sust($i,@d2,@fila2);$i++;}
  28.  
  29. while ($i<=4) {suma(@a=@fila3,@fila2,@fila4);sust($i,@d3,@fila3);$i++;}
  30.  
  31. while ($i<=4) {suma(@a=@fila4,@fila3,@fila5);sust($i,@d4,@fila4);$i++;}
  32.  
  33. print "@d1\n @d2\n @d3\n @d4\n";
  34.  
  35. print AA "@d1";
  36. print AA "@d2";
  37. print AA "@d3";
  38. print AA "@d4";
  39.  
  40. sub suma (my @a, my @b, my @c) {
  41.         $suma=(@a[$i-1]+@a[$i+1]+@b[$i-1]+@b[$i]+@b[$i+1]+@c[$i-1]+@c[$i]+$c[$i+1]);
  42.         }
  43.        
  44. sub sust (my @b, my @e) {
  45.                  if ($suma>5) {push(@b,0);};
  46.                  if ($suma<3) {push(@b,0);};
  47.                  if ($suma>4 && @e[$i]==0) {push($b,1)}
  48.                    }
  49.  
  50. close(AA);
  51.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


Ayuda por favor. Gracias de antemano.
perliña
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2013-04-09 05:18 @262

Publicidad

Re: Problema en subrutinas

Notapor explorer » 2013-05-12 10:21 @472

En Perl, por defecto(*), no soporta firmas en la definición de las subrutinas.

Cuando se comienza con Perl, lo mejor es pedirle ayuda al propio Perl para que nos diga que es lo que hemos escrito mal.

Para eso, lo mejor es escribir los programas con este encabezado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
El 'strict' nos obligará a programar de forma 'estricta': todas las variables deberán ir declaradas con my(). Si no, Perl nos dirá que quizás nos hemos equivocado a la hora de escribir alguna variable.
El 'warnings' activará los sistemas de alertas, y Perl nos avisará de cualquier cosa rara que vea. El 'diagnostics' nos dará aún más información sobre esas advertencias.

Si coloco esas líneas en tu programa, salen un montón de errores, a causa sobre todo del modo 'strict'. Si desactivo esa línea, solo salen advertencias, siendo las dos primeras:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Prototype after '@' for main::suma : my@a,my@b,my@c at code_34608.pl line 45 (#1)
    (W illegalproto) A character follows % or @ in a prototype.  This is
    useless, since % and @ gobble the rest of the subroutine arguments.
   
Illegal character in prototype for main::suma : my@a,my@b,my@c at code_34608.pl
        line 45 (#2)
    (W illegalproto) An illegal character was found in a prototype declaration.
    Legal characters in prototypes are $, @, %, *, ;, [, ], &, \, and +.
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
que quiere decir que has construido mal la definición de las funciones.

En lugar de
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub suma (my @a, my @b, my @c) {
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
se debe escribir así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub suma () {
  2.     my(@a, @b, @c)= @_;     # los argumentos son pasados a través de la variables especial @_
  3.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y aquí tenemos otro problema...

Cuando hacemos una llamada con array y hash, Perl "despliega" todos los elementos de esas variables, y los manda como una única lista de elementos hacia la subrutina. Ejemplo: si tenemos esto:
my @a = qw( 0 0 0 0 );
my @b = qw( 0 1 1 0 );
suma(@a, @b);


Perl hará la llamada así: suma( 0, 0, 0, 0, 0, 1, 1, 0 ); Entonces, cuando llega a la línea, dentro de la subrutina:

my(@x, @y) = @_;

Perl "mete" todos los valores en @x, y no deja ninguno para @y. Perl no sabe que eran dos array separados. Una vez hecho el despliegue, no hay forma de saber cuántos elementos tiene cada uno (bueno, se podría saber, haciendo alguna trampa).

En el caso de querer pasar (más de un) array o (más de un) hash, lo normal es hacerlo por "referencia":

suma(\@a, \@b);

En esa llamada estamos pasando exactamente dos valores escalares: dos referencias, una a cada uno de los array. En la subrutina, solo queda recibirlos:

my($array1_ref, $array2_ref) = @_; # recibimos dos valores escalares

y ya podemos acceder a los elementos de cada uno de ellos, pero como son referencias, hay que hacerlo con una indirección:

print $array1_ref->[0]; # primer elemento del primer array

o a todos:

for my $celda (@$array2_ref) { # recorremos todos los valores, directamente

for(my $j = 0; $j < @$array2_ref; $j++) { # recorremos todos los índices de los valores

(La notación '_ref' es solo eso: una notación. Sirve para que, visualmente, sepamos que esas escalares almacenan una referencia, y que entonces deben ser accedidas de una forma especial).

Más información en tu propio ordenador en perldoc perlsub, y en la Web.

Aparte, hay más detalles... en la línea 25 estás llamando a suma() sin pasarle ningún argumento.

Si quieres trabajar con una matriz bidimensional, a veces es mejor usar una estructura bidimensional:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @matriz = (
  2.     [ 0, 0, 0, 0, 0, 0 ],
  3.     [ 0, 1, 0, 1, 1, 0 ],
  4.     [ 0, 1, 1, 0, 0, 0 ],
  5.     [ 0, 1, 1, 0, 1, 0 ],
  6.     [ 0, 1, 0, 1, 1, 0 ],
  7.     [ 0, 0, 0, 0, 0, 0 ],
  8. );
  9.  
  10. print "Elemento 3,2 = ", $matriz[2][1], "\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Más información en tu propio ordenador en perldoc perllol, y en la Web (traducido al español).

(*) Por medio de módulos sí que es posible usar firmado de subrutinas.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 17 invitados