Utrecht has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks, I have a question/problem concerning a printf in an if-statement. In the following code I am going through a file with data in time. Some of this data is worthless which is represented by a file holding the start and endtimes of these worthless timespans in epoch seconds($gapsfile). For each day I want to calculate the number of gaps as well and print these to file. However for some reason the printf in the if-statement which checks if a next day begins ( if(! ($julday == $julday_old)) ) does not work. It does print to filehandle OUT1 before the if statement. The print statements, printing the same variables to standard output in the if-statement do function as well. I am confused.....?? thanks in advance!
my $error_cnt = 0; my $day_cnt = 0; my $month = 0; my $test; my $julday_old; open(OUT,">$resultsfile.corrected"); open(OUT1,">$resultsfile.gaps"); open(INP, $resultsfile); while (<INP>){ chomp($_); my $line = $_; my ($timestr,$timebin,$fish,$vel,$azi,$px,$py) = split(/\s+/,$line); my ($year,$julday,$hour,$min,$sec,$msec) = split(/\./,$timestr); my $timest = timegm_nocheck($sec,$min,$hour,$julday,$month,$year); my $timeend = $timest + 512; $julday_old = $julday if $. == 1; #$test = sprintf"%s %s\n",$julday_old,$day_cnt if $. != 1; #printf OUT1 "%s",$test; if(! ($julday == $julday_old)){ printf OUT1 "%s %s\n",$julday_old,$day_cnt; print "$julday_old "; print "$day_cnt\n"; $julday_old = $julday; $day_cnt = 0; } open(IN,"$gapsfile"); while (<IN>){ chomp($_); my ($sttime,$endtime) = split(/\s+/,$_); if ($sttime < $timest && $endtime > $timeend){ print "Timespan $timestr will be removed\n"; $day_cnt++; $error_cnt++; last; } elsif ($endtime > $timest+3.2 && $endtime < $timeend){ print "Timespan $timestr will be removed\n"; $day_cnt++; $error_cnt++; last; } elsif ($sttime+3.2 < $timeend && $sttime > $timest){ print "Timespan $timestr will be removed\n"; $day_cnt++; $error_cnt++; last; } else{ printf OUT "$line\n"; } } close(IN); } close(OUT); + close(OUT1); print "\n\nTotal number of timespans of 8m 32s removed is: $error_cnt\ +n"; close(INP);

Replies are listed 'Best First'.
Re: printf in if-statement
by toolic (Bishop) on Apr 21, 2009 at 13:48 UTC
    Without a small sample of your input file, it is not simple to reproduce your results. Try to print both values before your "if" line:
    print "julday >>>$julday<<<\n"; print "julday_old >>>$julday_old<<<\n";

    Are these values integers, or are they floating point values?

    Isn't...

    if(! ($julday == $julday_old)){

    the same as...?

    if ($julday != $julday_old){
Re: printf in if-statement
by lostjimmy (Chaplain) on Apr 21, 2009 at 13:55 UTC

    Nothing jumps out at me as being wrong in your code, but I do have some stylistic things and best practices you might want to consider...

    • You should really be checking the success of your open calls. Also, most people will suggest the three argument form of open and lexical file handles: open my $out, ">", "$resultsfile.corrected" or die "could not open $resultsfile.corrected: $!"
    • You don't need to use printf at all in this code. Using print and string interpolation is usually easier to read: print $out1 "$julday_old $day_cnt\n"
    • I think that if (! ($julday == $julday_old)) would be better written as if ($julday != $julday_old)

    OK, enough of my opinions.

    So the only real question I have is, are you sure that block of code is being reached? I assume you're seeing the printouts to the console, but I just thought I would ask.
    Update: I reread the question and saw that the prints are showing up on stdout. I'm out of ideas...

      Hi, thank you for your input. I am sorry I was bothering you, because I think I was a little too hasty with my question. For some reason, the print-statement is not executed realtime, but only after the while over filehandle INP is finished. I don't understand why this buffering occurs in this case as normally it doesn't, but the code works fine anyway.
        I don't understand why this buffering occurs in this case as normally it doesn't

        I'd say it's the other way around: buffering is the default behaviour. Only under certain circumstances, the behaviour is changed, for example when the handle is connected to a terminal (like STDOUT, typically). In this case, line-buffering (as opposed to block-buffering) is used, because an interactive mode of operation is assumed.

        You could enable auto-flushing, though (on any handle):

        use IO::Handle; open my $fh, ">", "test.out" or die $!; $fh->autoflush(); print $fh "..."; # is being written immediately

        (see also Re: Troubles with do...while loop and sleep (line- vs. block-buffered))

Re: printf in if-statement
by ikegami (Patriarch) on Apr 21, 2009 at 13:59 UTC