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

Hello All ,

I have a probelme with mycode . I have written a code which accpets the character from a keyboard and checks , whether the input character is same as in the array on a character by character basis.

But , while it takes the input .its getting executed twice . Even I tried with STDIN , its hanging up after input so , no further processing .

Please help me to get rid of this .

My code is

<code> #! /usr/bin/perl open (FILE, "c:\\Users\\yashu\\Desktop\\SNLP\\EX4\\test.txt" ) || die +$!; undef($/); $mytext = <FILE>; $mytext = lc($mytext); $mytext =~ s/[^a-z|]/ /g; @wordarray = split(//,$mytext); print "@wordarray \n "; $len =@wordarray ; print "\n the lenght of the array is : $len "; $i=0; $j=0; $iter=0; while ($i<=$len-1) { print " \n Value of i is : $i "; print " \n Value of j is : $j "; print " \n Value of character in array is : $wordarray[$i] "; print " \n Enter the character : "; $char = getc(); #$char = substr($character,1); print " input is $char "; chomp($char); print " \n inputted character is : $char "; if ( $char eq $wordarray[$j]) { print "Correct !!"; $iter++; $count[$i]=$iter; $j++; $i++; $iter=0; } else { print "\n Wrong please try again "; $iter++; print "\n Number of attempts : $iter "; } }

Replies are listed 'Best First'.
Re: getc working twice .
by eyepopslikeamosquito (Archbishop) on May 29, 2011 at 01:11 UTC

    Your Perl coding style is about ten years behind the curve. Things like lack of "use strict" and not using lexical file handles and three-argument open. If you want to seriously improve your Perl, I suggest you start by reading the excellent and free Modern Perl book.

    I've tidied up your code and made a first attempt at converting it to a more modern style. The intent of your program is not entirely clear to me. Have a go at running the program below and let me know how close it is to solving your problem. See the comments below for more information on some of the changes I made to your original code.

    # Always start your scripts with use strict and use warnings. use strict; use warnings; $| = 1; # autoflush your print statements # This subroutine slurps a text file into a string. # Note the use of a lexical file handle and three-argument open # and localization of the $/ global variable. # Note that the lexical $fh is automatically closed at end # of scope, i.e. when the subroutine exits. sub slurp_file { my $file = shift; open( my $fh, '<', $file ) or die "error: open '$file': $!"; local $/ = undef; return <$fh>; } # Note: you can use forward slashes on Windows (saves you escaping bac +kslashes). my $file = 'c:/Users/yashu/Desktop/SNLP/EX4/test.txt'; my $mytext = slurp_file($file); $mytext = lc $mytext; # $mytext =~ s/[^a-z|]/ /g; # your original replaces with space $mytext =~ s/[^a-z|]//g; # this deletes [^a-z|] instead my @wordarray = split //, $mytext; my $iter = 0; print "@wordarray\n"; # Note with a for loop you don't need the ugly array indexes. for my $wordchar (@wordarray) { while (1) { print " \n Enter the character then press ENTER : "; my $char = <STDIN>; chomp $char; if ( length($char) != 1 ) { print "you must enter exactly one character (not $char)\n"; next; } print "\n inputted character is : $char "; if ( $char eq $wordchar ) { print "Correct !!"; last; } print "\n Wrong please try again "; $iter++; print "\n Number of attempts : $iter "; } } print "\nNumber of failed attempts: $iter\n";
    To input the character without having to press ENTER you would need to employ the Term::ReadKey module (see also perlfaq5 "How can I read a single character from a file? From the keyboard?").

Re: getc working twice .
by ig (Vicar) on May 29, 2011 at 01:01 UTC

    I'm not sure what you mean by its getting executed twice or its hanging up after input but I suspect one of your problems is line termination.

    Input from the keyboard is normally buffered. Your program can't ready any input until the user presses the Enter key, after which the whole line of input becomes available to the program, and the input includes the line termination character. Within your program, this will be a single character "\n". For example, if the user presses the key A and waits, the program will do nothing - it won't have any input available to read and getc() will wait. This may not be what you want. If the user then presses the Enter key, the program will have the string "a\n" (assuming the shift or shift lock were not active when A was pressed) available to read. Then getc() will return the next input character: "a". And the next time your program calls getc() it will immediately return the next input character: "\n". This is probably not what you want.

    So, you have two issues: line buffering of input and line termination.

    What do you want your program to do if the user presses A then B then C then Enter, producing the input "abc\n"?

    Maybe you want to process the 'a' and ignore "bc\n". In this case, you could use line oriented input instead of getc(). You might try something like the following:

    #! /usr/bin/perl open( FILE, "test.txt" ) || die $!; $mytext = do { local $/; <FILE>; }; $mytext = lc($mytext); $mytext =~ s/[^a-z|]/ /g; @wordarray = split( //, $mytext ); print "@wordarray \n "; $len = @wordarray; print "\n the lenght of the array is : $len "; $i = 0; $j = 0; $iter = 0; while ( $i <= $len - 1 ) { print " \n Value of i is : $i "; print " \n Value of j is : $j "; print " \n Value of character in array is : $wordarray[$i] "; print " \n Enter the character : "; $line = <STDIN>; chomp($line); # remove the trailing line termination if(length($line) > 1) { print "extra characters \"" . substr($line,1) . "\" ignored\n" +; } $char = substr($line,0,1); print " input is $char "; chomp($char); print " \n inputted character is : $char "; if ( $char eq $wordarray[$j] ) { print "Correct !!"; $iter++; $count[$i] = $iter; $j++; $i++; $iter = 0; } else { print "\n Wrong please try again "; $iter++; print "\n Number of attempts : $iter "; } }

      Please post your code using <code> </code> tags instead of <pre> </pre> tags so it will display properly and be available for download.    TIA