0

I have a file with almost 1,500 names of Marvel heroes, each name in new line. I have to ask user what his favourite hero is and find out if it's a hero from the list or not. Here's what I have right now. It doesn't work: I can guess only the last hero from the list. For the rest it just prints that they are not on the list.

print "Whats your favourite hero?\n";
my $hero = <stdin>;
chomp $hero;

open FILE, "<list_marvel.txt";
my @marvel = <FILE>;
chomp(@marvel);

my $result = 0;
foreach (@marvel) {
    if ($_ eq $hero);
}

if ($result == 1) {
    print "That hero is on the list";
}
else {
    print "$hero is not on the list.\n";
}

Here are two files: -Perl code : Perl Code -List of heroes : List

4
  • That's how we did it in classes and, as far as i know, the array is filled correctly with all the names. When i tried printing them all everything was there. Commented Jun 10, 2015 at 8:09
  • 2
    You really should use three argument open and check if you were successful. Like this: open FILE, '<', 'list_marvel.txt' or die "error on opening:$!'. And honestly, it seems to me like you're getting taught a perl that is over ten years old. If you want to use it somewhere else, I strongly suggest that you pick up some books like ”Learning perl” and “Modern Perl” to complement your classes. Commented Jun 10, 2015 at 8:18
  • 3
    @moffeltje: Please don't "fix" British English to American English Commented Jun 10, 2015 at 8:25
  • @Borodin Oops, didn't think about it.. habits.. ;) Commented Jun 10, 2015 at 8:36

6 Answers 6

1

Your program has a syntax error and won't compile. It certainly won't find only the last name on the list

The main problem is that you never set $result, and if($_ eq $hero) should be something like $result = 1 if($_ eq $hero)

You must always use strict and use warnings at the top of every Perl program you write. It is an enormous help in finding straighforward problems

Here's a working version

use strict;
use warnings;

my $filename = 'list_marvel.txt';

open my $fh, '<', $filename or die qq{Unable to open "'list_marvel.txt'": $!};

print "Whats your favourite hero? ";
my $hero = <>;
chomp $hero;

my $found;
while ( <$fh> ) {
    chomp;
    if ( $_ eq $hero ) {
        ++$found;
        last;
    }
}

print $found ? "$hero is on the list\n" : "$hero is not on the list";
Sign up to request clarification or add additional context in comments.

5 Comments

This one gives the same results as mine with added ++result;. It works only for last element from the list.
@Looter11: I apologise - it was missing a chomp. Try now
Still nothing. I'm starting to wonder if it's something wrong with my files, because none of this replies works as intended. Even though i know they are good (in theory), something is preventing them from working.
@Looter11: Then at a guess you have leading or trailing spaces on your file records. Try s/\s+\z// instead of chomp
That was it! I couldn't find any spaces when scrolling down the file, but after using that expression instead of chomp, everything works fine. Thank you!
1

You don't set $result anywhere to true.

Make your foreach loop like this:

foreach(@marvel){
  $result = $_ eq $hero;
}

or

foreach (@marvel){
  $result = 1 if $_ eq $hero
}

Comments

1

You forgot to increment your $result. If you indent your code properly, it is easier to see.

foreach (@marvel) {
    # here something is missing
    if ( $_ eq $hero );
}

Add $result++ if $_ eq $hero; in the foreach.


You should always use strict and use warnings. That would have told you about a syntax error near );.

Also consider using the three argument open with lexical filehandles.

Rewritten it looks like this:

use strict;
use warnings;
use feature 'say'; # gives you say, which is print with a newline at the end

say "What's you favourite hero?";
my $hero = <STDIN>;
chomp $hero;

# alsways name variables so it's clear what they are for
my $found = 0;

# die with the reason of error if something goes wrong
open my $fh, '<', 'list_marvel.txt' or die $!;

# read the file line by line    
while ( my $line = <$fh> ) {
  chomp $line;
  if ( $line eq $hero ) {
    # increment so we know we 'found' the hero in the list
    $found++;

    # stop reading at the first hit
    last;
  }
}
close $fh;

# no need to check for 1, truth is enough
if ( $result ) {
    say "That hero is on the list.";
}
else {
    say "$hero is not on the list.";
}

3 Comments

This shows only the last one as well, for every other name it says its not on the list. I tried almost every method posted here and all of them show only the last element of the list properly.
@Looter: Please add the file to the question. If all the solutions should work if the data is exactly the same as what you entered. Hence, it's not the same.
Strictly speaking it's a list of characters, not heroes :P
0

First, you miss setting the $result at around if($_ eq $hero).

Then, you may wish to make you comparison case insensitive. This would require a regular expression, e.g.:

$result = 1 if (/^$hero$/i);

1 Comment

Case-independent equality is usually written lc eq lc $hero (or fc eq fc $hero if you are using Unicode and have version 16 or later of Perl)
0

Just modified your code. After if condition increment $result. Always use use strict and use warnings and always use 3 arguments to open a file.

use strict;
use warnings;

print "Whats your favourite hero?\n";
my $hero = <stdin>;
chomp $hero;
open FILE, "<", "list_marvel.txt" or die $!;
chomp (my @marvel = <FILE>);
close FILE;

my $result = 0;

foreach my $name (@marvel)
{
    if($name eq $hero)
    {
        $result++;
    }
}
if ($result == 1)
{
    print "That hero is in the list.\n";
} 
else
{
    print "$hero is not in the list.\n";
}

1 Comment

You don't want to do ++ and then compare to 1, in case there are duplicates
0

This will take a single user entry from STDIN. It will run through the file of hero names, and if one matches the user entry it will print the name and exit the loop. If the name is not found it will tell you:

use warnings;
use strict; 

open my $file1, '<', 'input.txt' or die $!;

print "Enter hero: ";
chomp(my $hero = <STDIN>);

my $result = 0;
while(<$file1>){
    chomp;
    if (/$hero/){   
        print "$_\n";
        $result++;
        last;
    }
}
print "hero not in list\n" if $result == 0;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.