/ Forside / Teknologi / Udvikling / Perl / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Perl
#NavnPoint
bjarneA 141
poul_from 50
soccer 30
Nicknack 14
Tmpj 0
Underligt problem med løkke..?
Fra : Rander


Dato : 15-04-04 21:18

På forhånd undskyld det lange indlæg, men jeg kunne ikke lige finde ud af
at forklare mit problem uden at inkludere en del kode - men altså:

Jeg holder en webside for en radio-station, og får hver uge tilsendt deres
dansktop i Word-format, som jeg konverterer til ren tekst (med antiword
uden problemer - så langt så godt.

I ren tekst ser en linie f.eks. sådan her ud:

|12|Bar' det ikke går helt galt |Hannibal Henrik Hildorf |12 |5 |10 |

Altså placering, titel, kunstner, placering sidste uge, antal uger og
højeste placering.

Jeg har så lavet et script der konverterer hele dynen til HTML, og det har
virket fint indtil nu.

Der er hver uge fem boblere, hvor linierne ser sådan her ud:

|22|Bar' det ikke går helt galt |Hannibal Henrik Hildorf | | | |

Altså blank i de tre sidste felter. Det konverterer jeg med følgende stump:

if (@lines[($i+$count)] =~ /^\|\s*[0-9]+\s*\|/)
{
@lines[($i+$count)] =~ /^\|\s*.*\s*\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|/;
@titel[$listenr] = $1;
@kunstner[$listenr] = $2;
@sidst[$listenr] = $3;
@uger[$listenr] = $4;
@max[$listenr] = $5;
$listenr++;
}
else
{
@lines[($i+$count)] =~ /^\|\s*\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|/;
@titel[$listenr-1] = @titel[$listenr-1] . $1;
@kunstner[$listenr-1] = @kunstner[$listenr-1] . $2;
@sidst[$listenr-1] = @sidst[$listenr-1] . $3;
@uger[$listenr-1] = @uger[$listenr-1] . $4;
@max[$listenr-1] = @max[$listenr-1] . $5;
$listlength++;
}

else-tingen er for det tilfælde at et af felterne er for langt og bliver
ombrudt i cellen af word, og kommer til at stå på to linier i tekstfilen.
Som det ses er jeg heller ikke interesseret i placeringen (første felt), da
denne alligevel genereres internt...

Og her kommer så mit problem: Hver uge siges farvel til fem numre. Det ser
så sådan her ud:

| |Bar' det ikke går helt galt |Hannibal Henrik Hildorf |22 |0 |0 |

I dette tilfælde kom bobleren altså ikke ind. Koden er så:

if (@lines[($i+$count)] =~ /\|\s*[0-9]+\s*\|/)
{
@lines[($i+$count)] =~ /^\|\s*\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|/;
@titel[$listenr] = $1;
@kunstner[$listenr] = $2;
@sidst[$listenr] = $3;
@uger[$listenr] = $4;
@max[$listenr] = $5;
$listenr++;
}
else
{
@lines[($i+$count)] =~ /^\|\s*\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|/;
@titel[$listenr-1] = @titel[$listenr-1] . $1;
@kunstner[$listenr-1] = @kunstner[$listenr-1] . $2;
@sidst[$listenr-1] = @sidst[$listenr-1] . $3;
@uger[$listenr-1] = @uger[$listenr-1] . $4;
@max[$listenr-1] = @max[$listenr-1] . $5;
$listlength++;
}

Virker fint. Men i denne uge har vedkommende der har skrevet listen
efterladt feltet med højeste placering (sidste felt i linien) blankt
(består altså af tre spaces) - og det opdagede jeg først da jeg kiggede på
top og så, at scriptet har brugt ca. 98% CPU-kraft siden middag i går!

Jeg har prøvet at trace igennem scriptet og fundet ud af, at når den når
linien med det sidste felt uden noget tal, så hopper den konstant til
else-delen og hænger så i et endeløst loop (ovenstående kodestump er pakket
ind i en for-løkke, der tæller op til $listlength)...

Ud af det vil jeg så gætte på at det er mine regulære udtryk der er gale -
jeg har prøvet lidt frem og tilbage, men kan ikke få det til at virke.

Er der en perl-ekspert tilstede?
--
Lars Rander, www.rander.dk ICQ#: 987520 ** Pil ikke ved min adresse **
Sjathelt og beskytter af det svage køn (udnævnt af diktator SEJ 5/6-99)

Jeg har aldrig mødt en mand, der var så ignorant, jeg ikke kunne lære
noget af ham. (Galileo Galilei)


 
 
Tore Aursand (16-04-2004)
Kommentar
Fra : Tore Aursand


Dato : 16-04-04 03:41

On Thu, 15 Apr 2004 22:18:19 +0200, Rander wrote:
> På forhånd undskyld det lange indlæg, men jeg kunne ikke lige finde ud af
> at forklare mit problem uden at inkludere en del kode - men altså:
> [...]

Du leser informasjonen på en merkelig måte, og det vil antagelig hjelpe
deg om du er litt mer fleksibel ved innlesing. Eksempel:

while ( <DATA> ) {
chomp;
my ( undef,
$position,
$title,
$artist,
$last_week,
$no_weeks,
$highest) = split( /\Q|\E/, $_ );
}

Hvis du prøver deg frem med denne måten å lese inn informasjonen på,
så kan det hende resten "går av seg selv".


--
Tore Aursand <tore@aursand.no>
"Have you ever had a dream, Neo, that you were so sure was real? What
if you were unable to wake from that dream? How would you know the
difference between the dream world and the real world?" (Morpheus, The
Matrix)

Lasse Hillerøe Peter~ (16-04-2004)
Kommentar
Fra : Lasse Hillerøe Peter~


Dato : 16-04-04 12:01

In article <b973l1-r1c.ln1@rander.dk>, Rander <lrNOSPAM@rander.dk>
wrote:

> På forhånd undskyld det lange indlæg, men jeg kunne ikke lige finde ud af
> at forklare mit problem uden at inkludere en del kode - men altså:


> Jeg har prøvet at trace igennem scriptet og fundet ud af, at når den når
> linien med det sidste felt uden noget tal, så hopper den konstant til
> else-delen og hænger så i et endeløst loop (ovenstående kodestump er pakket
> ind i en for-løkke, der tæller op til $listlength)...
****************************************!

Av, av!

>
> Ud af det vil jeg så gætte på at det er mine regulære udtryk der er gale -
> jeg har prøvet lidt frem og tilbage, men kan ikke få det til at virke.
>
> Er der en perl-ekspert tilstede?

Man behøver ikke være perl-ekspert for at se at der i hvert fald er en
ting galt.

Kig lidt på den her one-liner:
'my $ll = 1; for(my $i = 0; $i < $ll; $i++) { $ll++ }'
Jeg tror du har et tilsvarende problem i den sidste linie af
else-blokken.

Derudover kunne det være en god ide, som Tore foreslår, at strukturere
din kode lidt anderledes, så du deler løkkens krop op i to dele:
- En del, som parser (dvs opdeler tegnene) dit input
- En del som analyserer dit input og evt indsætter det i listen.

Derved undgår du det du så vidt jeg kan se gør nu: replikerer de samme
linier med minimale forskelle fire gange.

Det er også en god ide at undgå fejlen med $listlength ved at sikre sig
at man i løkker der læser input også faktisk æder noget input hver gang,
og holder op når der ikke er mere. Bagefter kan man så pynte løkken med
output, og den vil stadig garanteret stoppe. Hvis input er en fil, er
Tore's while-løkke at foretrække, har man et @array som du (og det er
som regel en god ide *ikke* først at snuppe en fil med @array = <DATA>,
med mindre man er sikker på at filen er lille) bør man altid bruge

foreach my $elem (@array) { ... }

eller i visse sjældne tilfælde måske

foreach my $i (0 .. $#array)

Den traditionelle C-style for-løkke er en forklædt while; og det kan
føre til eksempler som ovenstående one-liner hvis man ikke passer på.

Det er OK at du bruger flere arrays, et for hvert felt, men hvis du har
mod på at lære en smule om hashes som records og arrays af referencer
kan du gøre koden endnu mere overskuelig.

-Lasse

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408914
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste