Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Problemas con arrays y funciones

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Mar Jul 04, 2006 5:00 am
mygr83
Perlero Nuevo
Perlero Nuevo
Registrado: 04 Jul 2006
Mensajes: 6
Problemas con arrays y funciones Responder citando

Hola:
Soy nueva en perl y tengo un pequeño problema. Estoy haciendo una función que devuelve un array cuyos elementos son cadenas, y en el programa principal él valor de la función es asignada a otra variable, y uno de los elementos de esa variable(que será de tipo array) es mostrado por pantalla.

Lo que he hecho es algo así:
Dentro de la función:
Código:
sub funcion
($valor)=@_;
....
$fich[0]="cero";
$fich[1]="uno";
.....
return $fich


En el programa principal:

Código:
$var=@funcion($valor);
print $var[0];

y no obtengo nada.
Espero que podais ayudarme.

También he probado a poner:
Código:
sub funcion
($valor)=shift(@_);
....
$fich[0]="cero";
$fich[1]="uno";
.....
return @fich


En el programa principal:
Código:
@var=funcion($valor);
print $var[0];

y tampoco me funciona.

Nota: La función recibe un valor como parámetro, y ese parámetro luego lo utilizo para hacer unos cálculos aunque ahí no aparezca.

Un saludo
Mensaje Mar Jul 04, 2006 6:57 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4084
Ubicación: Valladolid, España
Responder citando

mygr83 está probando una solución que le he dado en otro foro.

Prueba con este programa:
Código:
#!/usr/bin/perl
use warnings;
use strict;

sub funcion {
    my $valor = shift(@_);
    # ... más cosas con $valor ...
    my @fich;
    $fich[0] = "cero";
    $fich[1] = "uno";
    $fich[2] = $valor;
    return @fich;
}

my $val = "nolose";
my @var = funcion( $val );
print $var[0],"\n";  # pinta un "cero"

Lo que estamos haciendo dentro de la función es crear un nuevo array llamado @fich, al que le damos unos valores.
Luego, lo devolvemos en el return (realmente estamos devolviendo todos los valores de @fich, no una referencia a ella),
En el resto del programa, @var recibe los elementos de @fich devueltos por la función.
Y finalmente, sacamos uno de sus valores. Si pintáramos el valor de $var[2] saldría el mismo valor que le hemos pasado a la función.

Otra forma de devolver el array al exterior de la función es devolviendo una referencia a él. Es más rápido, sobre todo si @fich tiene miles de elementos:
Código:
#!/usr/bin/perl
use warnings;
use strict;

sub funcion {
    my $valor = shift(@_);
    # ... más cosas con $valor ...
    my @fich;
    $fich[0] = "cero";
    $fich[1] = "uno";
    $fich[2] = $valor;
    return \@fich;
}

my $val = "nolose";
my $var = funcion( $val );
print $var->[0],"\n"; # Pinta "cero"
El programa es el mismo, pero ahora necesitamos acceder al array de otra forma. Ya que lo que nos devuelve como una referencia, tenemos que guardarlo en una variable escalar ($var), y luego desreferenciarlo con (->, igual que haríamos en C).
Mensaje Mie Jul 05, 2006 2:14 am
mygr83
Perlero Nuevo
Perlero Nuevo
Registrado: 04 Jul 2006
Mensajes: 6
sigo obteniendo el mismo error Responder citando

Hola de nuevo!
He intentado hacerlo de las dos formas que me has dicho, y sigo obteniendo el mismo error, que es el siguiente:

Use of uninitialized value in print

en la linea de print $var[0].

He probado de varias formas y ya no se que hacer.

Un saludo y gracias
Mensaje Mie Jul 05, 2006 2:29 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4084
Ubicación: Valladolid, España
Responder citando

¿Has probado el programa que te he puesto antes y te falla?
¿Puedes poner el programa o parte de él, que estás probando?

Te repito que si quieres que te ayude Perl, coloca use strict; y use warnings; al principio del programa.

El fallo indica que la función no ha devuelto ningún valor y que estás intentando pintar un valor no definido. El problema parece estar dentro de la función, en el momento del return, o que efectivamente, no está devolviendo nada en ese array. ¿Has comprobado el valor del array antes de salir de función?
Mensaje Mie Jul 05, 2006 3:47 am
mygr83
Perlero Nuevo
Perlero Nuevo
Registrado: 04 Jul 2006
Mensajes: 6
Responder citando

Hola!

Yo pienso que el problema que tengo se encuentra dentro de la función, ya que no es tan sencilla, como la que puse, sino que hace más cosas dentro de las cuales puede haber errores.

Código:
sub funcion {
    my $var=shift(@_);
    my @fich;
    if (@ARGV==1) {
        $file=$ARGV[0];
    }
    open FIL, '< '.$file or die "Error: No se pudo abrir el fichero \n";
    @config=<FIL>;
    close FIL;

    #leemos los datos del fichero
    for ($Linea=0; $Linea<@config; $Linea++) {
        #comparamos el primer valor con el parámetro pasado
        $comp= $var cmp $dat[0];
        $num=0;
        if ($comp == 0) {
            #si coinciden los valores almacenamos el segundo valor del fichero
            $fich[$num]=$dat[1];
            print $fich[$num]; #comprobamos que tiene valor
            $num=$num+1;
        }
    }

    return @fich;
}


Yo lo que quiero hacer, con esta función, es leer de un fichero un conjunto de líneas. En cada línea hay dos valores. Entonces leemos el primero y lo comparamos con el parámetro que pasamos a la función y si coincide almacenamos en el array el segundo valor de la línea, y después la función tiene que devolver el array con esos valores.

Muchas gracias de nuevo
Mensaje Mie Jul 05, 2006 4:40 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4084
Ubicación: Valladolid, España
Responder citando

Pues entonces se vé claro... Estás usando la variable @dat ($dat[0] y $dat[1]) sin haberlas inicializado.
Por eso no se mete nada en la variable @fich. Y por eso la función no devuelve nada...
Y la variable $num siempre se pone a 0 en el bucle interno...

Supongamos que tenemos un fichero de texto, en que cada línea hay dos valores que están separados por un tabulador. Por ejemplo:
Código:
luis    2
nancy   3
luis    1

entonces con el programa siguiente localizamos las líneas con un determinado primer campo y obtenemos de ellas un array con los segundos campos:
Código:
#!/usr/bin/perl
use warnings;
use strict;

# Constantes
my $fichero = "kk.txt";

# Variables
my $valor;          # Qué tenemos que buscar
my @resultado;      # Resultado de la búsqueda

# Funciones
###
# funcion
#   Abre el $fichero y busca aquellas líneas cuyo primer campo
#   coincida con el campo a buscar, indicado como primer parámetro.
#   Devuelve un array con todos los segundos campos de las líneas.
sub funcion {
    my $campo_a_buscar = shift @_;
    my $num = 0;                        # Contador de respuestas
    my @fich;

    # Lectura del fichero
    open FICHERO, '<', $fichero or die "Error: No se pudo abrir el fichero $fichero: $!\n";
    my @config = <FICHERO>;
    close FICHERO;

    # Leemos los datos del fichero
    for (my $Linea = 0; $Linea < @config; $Linea++) {

        # Obtenemos los dos campos de la línea
        my @dat = split(" ", $config[$Linea]);
        next unless @dat == 2;  # Si hubo un error, seguimos con la siguiente línea

        # Si es el campo que buscamos...
        if ( $dat[0] eq $campo_a_buscar ) {
            chomp($dat[1]);         # Quitamos el final de línea en el segundo campo
            $fich[$num] = $dat[1];  # almacenamos el segundo valor del fichero
#           print $fich[$num];      # comprobamos que tiene valor
            $num=$num+1;
        }
    }

    return @fich;
}

# Programa principal
# Qué es lo que tenemos que buscar
if ( @ARGV ) {
    $valor = $ARGV[0];
}
else {
    die "Uso: $0 <campo a buscar>\n";
}

@resultado = funcion( $valor );     # A buscar!!!
if ( @resultado ) {
    print "Encontrado $valor: @resultado\n";
}
else {
    print "No se encontró $valor en ninguna línea.\n";
}

__END__

Obtenemos las siguientes salidas:
Código:
> ./kk.pl luis
Encontrado luis: 2 1
> ./kk.pl nancy
Encontrado nancy: 3
> ./kk.pl mygr
No se encontró mygr en ninguna línea.


Naturalmente, este problema se puede resolver de otras formas (por algo esto es Perl), pero aquí te he puesto una parecida a lo que ya tenías.
Mensaje Mie Jul 05, 2006 5:31 am
mygr83
Perlero Nuevo
Perlero Nuevo
Registrado: 04 Jul 2006
Mensajes: 6
Responder citando

Muchísimas gracias por tu ayuda. Ya por fin pude solucionar mi problema.
Un saludo
Mensaje Mie Jul 05, 2006 5:53 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4084
Ubicación: Valladolid, España
Otra solución Responder citando

Bueno, esta es otra forma de hacerlo, un poco más corta, pero espero que no sea muy complicada... te la numero por líneas y te la comento al final.
Código:
    1 #!/usr/bin/perl
    2 use warnings;
    3 use strict;
    4
    5 @ARGV or die "Uso: $0 <campo a buscar>\n";
    6 my $valor = $ARGV[0];
    7
    8 my $fichero = "kk.txt";
    9 open FICHERO, '<', $fichero
   10     or die "Error: No se pudo abrir el fichero $fichero: $!\n";
   11 my @config = <FICHERO>;
   12 chomp(@config);
   13 close FICHERO;
   14
   15 if ( my @encontrados = buscar( $valor ) ) {
   16     print "Encontrado $valor: @encontrados\n"
   17 } else {
   18     print "No se encontró $valor en ninguna línea.\n"
   19 }
   20
   21 sub buscar {
   22     my $campo_a_buscar = shift @_;
   23     my @encontrados;
   24     my @campos;
   25
   26     foreach my $linea ( @config ) {
   27         @campos = split(' ', $linea);   # Obtenemos los dos campos de la línea
   28         next                            # Miramos siguiente línea...
   29             unless @campos == 2;        # ...si el número de campos no es 2
   30
   31         push @encontrados, $campos[1]           # Almacenamos el segundo campo...
   32             if $campos[0] eq $campo_a_buscar;   # ...si hemos encontrado el primero
   33     }
   34
   35     return @encontrados;
   36 }
   37
* Las 3 primeras líneas son como -casi- siempre, las mismas
* En las líneas 5 y 6, nos leemos el término a buscar
* De la 8 a 13, nos leemos el $fichero y lo guardamos en @config. Aprovechamos para quitar (chomp) los finales de línea a todas las líneas
* En la 15 buscamos el $valor y lo guardamos en @resultados. Si el número de elementos devueltos es superior a 1, se cumple la condición cierta del if y pinta la línea 16. Sino, la 18
* En la 26, usamos un bucle foreach, porque vamos a recorrer todas las líneas. Cada una se queda almacenada, dentro del bucle, en la variable $linea
* En la siguiente, dividimos (split) la $linea en @campos separados por ' ' (un espacio en blanco, que equivale a cualquier número de espacios, tabuladores, etc)
* Si no hemos encontrado exactamente dos campos (línea 29) termina el actual bucle foreach y lo intenta con la siguiente (next) $linea (línea 28)
* En la 31 y 32, si hemos encontrado el mismo (eq) $campo_a_buscar que el primer campo ($campo[0])...
* ... metemos (push) en @resultados el valor del segundo campo ($campo[1])
* En la 35, devolvemos (return) todos los valores @encontrados.
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group