Re: string retrieval issue




Quoth mbliven1@xxxxxxxxx:

Paul Lalli wrote:
mbliven1@xxxxxxxxx wrote:
That's where I'm stuck. If the flat file looks like this:

Chicago Bears|NFC North
Detroit Lions|NFC North

then everything is great. However, if my file looks like this:
Chicago Bears|NFC North
Chicago Bulls|East Conference

then the script fails. In other words, if both lines begin with the
exact same string to the first space, then it will fail. It fails by
not writing the third element (Chicago Bulls) back to the array).
Ideas?

... You obviously did something wrong. How, precisely, are you
expecting anyone to tell you what you did wrong without seeing the code
you wrote?

Have you read the Posting Guidelines for this group? They're posted
here twice a week. I suggest you read them before replying.

My bad about the post. I have now read the guidelines.

....but seem to be unwilling to follow them.

Here is the code:


Where is

use strict;
use warnings;

?

open (FILE, "+<test.txt") || die ("test.txt wont open");

Use two-arg open.
Use lexical filehandles.
Say why the open failed.
The first rule of programming is: never type anything twice. Put the
filename in a variable.

my $database = 'test.txt';
open(my $FILE, '+<', $database) || die("'$database' won't open: $!");

If you use or instead of || those parens are optional:

open my $FILE, '+<', $database
or die "can't open '$database': $!";

but the code's OK like that if you find it easier to understand.

flock FILE, 2;

Don't *ever* use numeric constants for flock, seek, &c. Ask Perl to get
them right for you.
Check that you got the lock.

use Fcntl qw/:flock/; # this goes at the top

flock $FILE, LOCK_EX
or die "can't lock '$database': $!";

@lines = <FILE>;

You need to declare variables under 'use strict'.

my @lines = <$FILE>;

$j=0;
$k=0;

These would need declaring as well, except you very rarely need loop
counters in Perl. Perl knows how long your arrays are.

You do, however, need

my @splitdata;

foreach $element (@lines) {
^^ my

($element1, $element2) = split(/\|/, $element);

Variables with similar names are a red flag. They mean you should be
using data structures: in this case, an array.

my @elements = split(/\|/, $element);

@splitdata[$j] = $element1;

Don't use @ for accessing single array elements. It appears to work, but
it doesn't mean quite what you think it does. See perldoc -q @array.

$splitdata[$j] = $element1;

@splitdata[$k] = $element2;

This is pointless. $j and $k will always be equal, so you set the same
element twice. Every other element will be blank. I presume you meant to
set successive elements?

Use Perl's array operators, and then you don't need the temporaries
either:

push @splitdata, split /\|/, $element;

$j = $j + 2;

It's generally clearer to use the assignment operators where you can:

$j += 2;

, except, of course, that you don't need this at all.

$k=$k + 2;
}

foreach $p (param()) {

What is param? You didn't include it in your script. I'm going to guess
you meant to put

use CGI qw/:standard/;

at the top: when the posting guidelines say 'a short, complete script'
they mean you need to post the *whole* of your script. You also need to
provide example input: in this case, a query string.

Note that the order of parameters is not guaranteed to be the same as
the order of fields in the form. You should give your paramaters names
and access them by name.

$formvalue = param($p);
@formvalue[$i] = $formvalue;

if ($formvalue eq "") {
@final[$i] = @splitdata[$i];
}
else {
@final[$i] = $formvalue;
}

This can be written more simply as

$final[$i] = $formvalue || $splitdata[$i];

$i++;
}

I don't really understand what you are trying to achieve here. A
somewhat cleaner solution might be

my @params = params;
my %final;
$final{$_} = shift @splitdata for @params;
$final{$_} = param($_) for grep param($_), @params;

but I really think that a better answer would be to put the form field
names into your database. Do you have to use that file format? If you
could change to something like GDBM, then you could reduce the whole
script down to

use warnings;
use strict;

use GDBM_File;
use CGI qw/:standard/;

tie my %data, GDBM_File => './data', GDBM_WRCREAT;

$data{$_} = param($_) for grep param($_), params;

as GDBM handles locking for you. This will consider a parameter value of
'0' to be equivalent to '', so you may prefer

$data{$_} = param($_) for grep { length param($_) }, params;

It also assumes that your fields all have unique names; again, this may
not be the case, but you didn't provide us with any input data.

$x=0;
$y=0;
$z=0;

foreach (@final) {
$firstpart = @final[$x];
$secondpart = @final[$y];

Again, $x and $y are the same, so you're getting the same element twice.
Also, the loop loops once for every element in @final, but you're adding
2 to $x each time, so before long you'll be off the end of the array.

$writevalue = "$firstvalue|$secondpart";

What is $firstvalue? Is this your real script, or is that the bug you
were having trouble with? I can't see how it would produce the effect
you describe, though, unless this is not your whole script.

@finalwrite[$z] = $writevalue;
$x = $x + 2;
$y = $y + 2;
$z++;
}

seek FILE, 0, 0;

Don't use magic numbers, use constants.

use Fcntl qw/:seek/;

seek $FILE, 0, SEEK_SET;

truncate FILE, 0;

print FILE @finalwrite;

Since you haven't set $,, this will print the array elements all on one
line, separated by spaces. I don't think that's what you meant.

Ben

--
I must not fear. Fear is the mind-killer. I will face my fear and
I will let it pass through me. When the fear is gone there will be
nothing. Only I will remain.
benmorrow@xxxxxxxxxxxxx Frank Herbert, 'Dune'
.



Relevant Pages

  • Re: even rows for checkbox forms with no splitting of boxes from values
    ... 'mod' on the array length with a denominator equal to the width of the row, ... State saving really depends on what the script is already doing. ... So I usually roll my own checkboxes. ... #this is to create an array with 25-50 strings 2-10 in length ...
    (comp.infosystems.www.authoring.cgi)
  • Re: settimeout needs alert() ???
    ... function slider { ... and use script to replace the src and title attributes. ... are downloaded completely. ... The usual strategy is to load all of the images in to an array of image ...
    (comp.lang.javascript)
  • Re: Changing file output format
    ... > I would like to change output format of a file from: ... The chomp function is for situations where you may not know whether a line is terminated by a newline. ... If you are not manipulating the data set as a whole, there is no good reason to put it into an array. ... > However, the script did not print the entire array elements all at once, and that the elements are not joined together in the array, as shown in the output below: ...
    (perl.beginners)
  • Re: library (random numbers)
    ... Get into the habbit of using ... With such small libraries/scripts as these, ... Now you've FUBARed your script. ... $#arr is the last index of the array. ...
    (perl.beginners)
  • Yar Re: medieval english was knight ranks and titles
    ... My, she was yawl. ... Some script adapter, unsurprisingly, didn't ... > that if jimmy stewart is in a movie with cary grant then jimmy ... episodes of New York and Chicago series have had references to parking ...
    (sci.lang)