• Publicidad

Problemas con arrays y funciones

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

Problemas con arrays y funciones

Notapor mygr83 » 2006-07-04 06:00 @292

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: Seleccionar todo
sub funcion
($valor)=@_;
....
$fich[0]="cero";
$fich[1]="uno";
.....
return $fich


En el programa principal:

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

y no obtengo nada.
Espero que podais ayudarme.

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


En el programa principal:
Código: Seleccionar todo
@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
mygr83
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2006-07-04 05:55 @288

Publicidad

Notapor explorer » 2006-07-04 07:57 @373

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

Prueba con este programa:
Código: Seleccionar todo
#!/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: Seleccionar todo
#!/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).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

sigo obteniendo el mismo error

Notapor mygr83 » 2006-07-05 03:14 @176

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
mygr83
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2006-07-04 05:55 @288

Notapor explorer » 2006-07-05 03:29 @187

¿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?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor mygr83 » 2006-07-05 04:47 @241

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: Seleccionar todo
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
mygr83
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2006-07-04 05:55 @288

Notapor explorer » 2006-07-05 05:40 @277

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: Seleccionar todo
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: Seleccionar todo
#!/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: Seleccionar todo
> ./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.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor mygr83 » 2006-07-05 06:31 @313

Muchísimas gracias por tu ayuda. Ya por fin pude solucionar mi problema.
Un saludo
mygr83
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2006-07-04 05:55 @288

Otra solución

Notapor explorer » 2006-07-05 06:53 @328

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: Seleccionar todo
    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.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
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: Google [Bot] y 2 invitados

cron