-1

I'm fairly new to coding and I need a fail statement to print out as if it were an or die.

Part of my code for an example:

    print "Please enter the name of the file to search:";
    chomp (my $filename=<STDIN>) or die "No such file exists. Exiting program. Please try again."\n;

    print "Enter a word to search for:";
    chomp (my $word=<STDIN>);

I need it to do it for both of these print/chomp statements. Is there anyway to just add on to this?

Whole program:

#!/usr/bin/perl -w

use strict;

print "Welcome to the word frequency calculator.\n";
print "This program prompts the user for a file to open, \n";
print "then it prompts for a word to search for in that file,\n";
print "finally the frequency of the word is displayed.\n";
print " \n";

print "Please enter the name of the file to search:";
while (<>){
        print;
}

print "Enter a word to search for:";
chomp( my $input = <STDIN> );

my $filename = <STDIN>;

my$ctr=0;
foreach( $filename ) {
        if ( /\b$input\b/ ) {
                $ctr++;
        }
}
print "Freq: $ctr\n";

exit;
distro
  • 41
  • 5
  • 2
    I'm a bit puzzled by the logic in your program, the error message indicates you are doing something with a file but at that point all its doing is reading input from standard in. – adrianp Nov 16 '16 at 23:34
  • I can post the whole program, I just don't see how it would help though considering my question though. – distro Nov 16 '16 at 23:41
  • Oh, this update changes things a bit, doesn't it. My answer stands for the original question of testing reads from `<>` and `chomp`. I'll update to this new content. – zdim Nov 16 '16 at 23:55

1 Answers1

2

You don't need to test the filehandle read <> for success. See I/O Operators in perlop. When it has nothing to read it returns an undef, which is precisely what you want so your code knows when to stop reading.

As for removing the newline, you want to chomp separately anyway. Otherwise, once the read does return an undef you'd chomp on an undefined variable, triggering a warning.

Normally, with a filehandle $fh opened on some resource, you'd do

while (my $line = <$fh>) {
    chomp $line;
    # process/store input as it comes ...
}

This can be STDIN as well. If it is certainly just one line

my $filename = <STDIN>;
chomp $filename;

You don't need to test chomp against failure either. Note that it returns the number of characters that it removed, so if there was no $/ (newline typically) it legitimately returns 0.

To add, it is a very good practice to always test! As a part of that mindset, please make sure to always use warnings;, and I also strongly recommend coding with use strict;.


Update to a significant question edit

In the first while loop you do not store the filename anywhere. Given the greeting that is printed, instead of that loop you should just read the filename. Then you read the word to search for.

# print greeting

my $filename = <STDIN>;
chomp $filename;

my $input = <STDIN>;
chomp $input;

However, then we get to the bigger problem: you need to open the file, and only then can you go through it line by line and search for the word. This is where you need the test. See the linked doc page and the tutorial perlopentut. First check whether a file with that name exists.

if (not -e $filename) {
    print "No file $filename. Please try again.\n";
    exit;
}

open my $fh, '<', $filename  or die "Can't open $filename: $!";

my $word_count = 0;
while (my $line = <$fh>) 
{
    # Now search for the word on a line
    while ($line =~ /\b$input\b/g) {
        $word_count++;
    }
}
close $fh  or die "Can't close filehandle: $!";

The -e above is one of the file-tests, this one checking whether the given file exists. See the doc page for file-tests (-X). In the code above we just exit with a message, but you may want to print the message prompting the user to enter another name, in a loop.

We use while and the /g modifier in regex to find all occurencies of the word on a line.

I'd like to also strongly suggest to always start your programs with

use warnings 'all';
use strict;
zdim
  • 64,580
  • 5
  • 52
  • 81
  • But I WANT to, I'm aware I don't need to. – distro Nov 16 '16 at 23:51
  • @distro OK, that's in principle very good -- but with `chomp` you don't _want to_. It returns a number of chars that it removed, so if it didn't find a newline it returns a zero. So a 'normal' test (with `or`) would trigger for a wrong reason. If you are concerned with a builtin function call just _failing_ then you'd have to test nearly every statement! – zdim Nov 16 '16 at 23:53
  • Okay, I appreciate the advice. But is there absolutely no way to do this? I want my program to exit as well as display my own message if a file that the user puts in isn't there. – distro Nov 16 '16 at 23:56
  • @distro I'm updating the answer, to your edit. That's something else, unrelated to `chomp`. The `chomp` merely works on a _string_, that in your case contains the file-name and a newline. It doesn't deal with the actual file. – zdim Nov 17 '16 at 00:01
  • You may want to run the program yourself, the program works fine I just want to know a way to make it exit and print a message if it fails to find a file in the first chomp statement. Maybe it is impossible though and if so what would you recommend me using isteand? – distro Nov 17 '16 at 00:03
  • ALSO I put the wrong code... My apology I'll update again – distro Nov 17 '16 at 00:05
  • @distro Again, the `chomp` statement has absolutely nothing to do with the actual file. It works on a variable that contains only the _name_ of the file. You test for a file using `-e` file-test operator. I've updated the answer, and will add some more – zdim Nov 17 '16 at 00:05
  • Would you be able to PM me? I have a few concerns/questions and don't want to spam this question. – distro Nov 17 '16 at 00:12
  • @distro I am be happy to help, but can't talk extensively right now. The updates in the answer give you all you need to take the filename and the word to search for, check whether such a file exists in the first place, and then go through its lines. (Just `print` them to test that it all works.) I suggest to work through this first, and then let me know so we can continue. Normally it is a good idea to ask well-focused questions. So you may want to post another for further concerns. But let me know what it is in short first. – zdim Nov 17 '16 at 00:16
  • I got it working partially to the point where I'm happy that you helped me! lol.. I left my chomp statement and added an if statement to it and it's doing exactly what I wanted. Thank you very much – distro Nov 17 '16 at 00:20
  • @distro Great -- keep working. My answer spells out basics of how you open and work with a file. Read or at least scan through the linked docs. Let me know how it goes! – zdim Nov 17 '16 at 00:26
  • @distro I added a link to a much better page to read on opening files. Thank you for the attribution. As further questions come post them as new questions, if they're different enough. I'd suggest to try to articulate things as well as you can and _then_ post. Let me know if there is more to clarify about this. – zdim Nov 17 '16 at 00:57