qbasic-What is wrong with my code?I'm not getting what i want - qbasic

I tried to make a simple login program using qbasic. I used 3 sub modules and 1 main module. Here is the code:
DECLARE SUB login ()
DECLARE SUB menu ()
DECLARE SUB REGISTER ()
CLS
CALL menu
END
SUB login
OPEN "USERPASS.TXT" FOR INPUT AS #2
CLS
97
LOCATE 2, 30: PRINT "LOGIN"
LOCATE 4, 10: INPUT "PLEASE ENTER CORRECT USERNAME OR PRESS B IF YOU WANT TO GO BACK"; USER$
IF UCASE$(USER$) = "B" THEN
CLOSE #2
CALL menu
ELSE
DO WHILE NOT EOF(2)
INPUT #2, U$, p$
IF U$ = USER$ THEN
TEMPUSER$ = U$
PASSWORDS$ = p$
EXIT DO
END IF
LOOP
END IF
IF USER$ = TEMPUSER$ THEN
98
PRINT PASSWORDS$
LOCATE 5, 30: INPUT "ENTER PASSWORD OR PRESS B if you want to go back"; password$
IF UCASE$(password$) = "B" THEN
GOTO 97
ELSE
IF password$ = PASSWORDS$ THEN
PRINT "HURRAY YOU LOGGED IN"
ELSE
GOTO 98
END IF
END IF
ELSE
GOTO 97
END IF
CLOSE #2
END SUB
SUB menu
CLS
23
LOCATE 2, 30: PRINT "MAIN MENU"
LOCATE 4, 30: PRINT "1.LOGIN"
LOCATE 5, 30: PRINT "2.REGISTER"
LOCATE 6, 30: INPUT "PLEASE! Enter 1 or 2"; a
IF a = 1 THEN
CALL login
ELSE
IF a = 2 THEN
CALL REGISTER
ELSE
CLS
GOTO 23
END IF
END IF
END SUB
SUB REGISTER
CLS
OPEN "userpass.txt" FOR APPEND AS #1
LOCATE 2, 30: PRINT "REGISTER MENU"
LOCATE 4, 30: INPUT "ENTER NEW USERNAME"; NEWU$
CLS
LOCATE 4, 30: INPUT "ENTER NEW PASSWORD"; PASSU$
WRITE #1, NEWU$, PASSU$
END SUB
Everything is as my desire but in sub module login something is wrong I guess. The login massage does not come even if I enter correct password and username. But if I enter username which does not exist, it shows the login message. Please help. Thanks in advance.

You're missing an END IF to match ELSEIF UCASE$(USER$) <> "B" THEN (by the way: if UCASE$(USER$) = "B" is false, then UCASE$(USER$) <> "B" is true, so you could simply say ELSE there).
You might try indenting in a bit more conventional manner:
every IF, ELSEIF, ELSE, and END IF that matches is in the same column, and
everything inside those statements is indented a few more spaces.
The same indentation rules can be applied to SELECT CASE, WHILE-WEND, DO-LOOP, and FOR-NEXT.
Anyway, you might see the missing END IF if you did that:
SUB login
OPEN "USERPASS.TXT" FOR INPUT AS #2
CLS
97
LOCATE 2, 30: PRINT "LOGIN"
LOCATE 4, 10: INPUT "PLEASE ENTER CORRECT USERNAME OR PRESS B IF YOU WANT TO GO BACK"; USER$
IF UCASE$(USER$) = "B" THEN
CLOSE #2
CALL menu
ELSEIF UCASE$(USER$) <> "B" THEN
WHILE NOT EOF(2)
INPUT #2, U$, p$
IF U$ = USER$ THEN
TEMPUSER$ = U$
PASSWORDS$ = p$
END IF
WEND
IF USER$ = TEMPUSER$ THEN
98
PRINT PASSWORDS$
LOCATE 5, 30: INPUT "ENTER PASSWORD OR PRESS B if you want to go back"; password$
IF UCASE$(password$) = "B" THEN GOTO 97
ELSEIF UCASE$(password$) <> "B" THEN
IF password$ = PASSWORDS$ THEN
PRINT "HURRAY YOU LOGGED IN"
ELSE
GOTO 98
END IF
END IF
ELSE
GOTO 97
END IF
CLOSE #2
END SUB

Related

Opening a file inside a subroutine for read/write in Perl

I am trying to open a file inside a subroutine to basically substitute some lines in the file. But since, it was not working, I tried a simpler way of printing a line instead of substitute, for debug purposes. Following is the subroutine code.
sub replace {
while (<INPUT_FILE>){
my $cell = $_[0];
our $rpl;
if ($_=~ /^TASK\|VALUE = (.*)/ ) {
my $task = $1;
chomp $task;
$rpl = $cell . '_' . $task . '_bunch_rpl';
print "000: $rpl\n";
}
elsif ($_=~ /^(.*)\|VALUE = (.*)/ ) {
my $line = $_;
chomp $line;
my $ip_var = $1;
my $ip_val = $2;
chomp $ip_var;
chomp $ip_val;
my $look= $ip_var."|VALUE";
open(REPLAY_FILE, "+<$rpl") || die "\ncannot open $rpl\n";
while (my $rpl_sub = <REPLAY_FILE>) {
if ($rpl_sub =~ /^$line/) {
print "\n 111: $ip_val";
}
}
close REPLAY_FILE;
}
elsif ($_=~ /^\s*$/) {
print "\n";
return ;
}
}
}
The code prints the following as of now.
000: lfr_task62_bunch_rpl
111: 2.0.9.0
111: INLINE
111: POWER
000: aaa_task14_bunch_rpl
Expected output is:
000: lfr_task62_bunch_rpl
111: 2.0.9.0
111: INLINE
111: POWER
000: aaa_task14_bunch_rpl
111: 0.45
111: NO
The input sample is:
TASK_CELL_NAME|VALUE = lfr
TASK|VALUE = task62
TASK_VERSION|VALUE = 2.0.9.0
CHIP_PKG_TYPE|VALUE = INLINE
JUNK_LINE = JUNK
JUNK_LINE = JUNK
FULL_ESD|VALUE = POWER
TASK_CELL_NAME|VALUE = aaa
TASK|VALUE = task14
CUSTOM_CELL_DENSITY|VALUE = 0.45
CUSTOM_CELL_SS|VALUE = NO
Can someone tell me the mistake I am doing here?
UPDATE: Main code below
my #cell_names;
open(INPUT_FILE, "<$ip_file") || die "\n!!!ERROR OPENING INPUT FILE. EXITING SCRIPT!!!\n";
while (<INPUT_FILE>) {
if ($_=~ /(.*) =\n/ ) {
$mw -> messageBox(-message=> "\nFormat not correct on line $. of input file. Exiting script\n");
exit;
}
elsif ($_=~ /(.*) =\s+\n/ ) {
$mw -> messageBox(-message=> "\nFormat not correct on line $. of input file. Exiting script\n");
exit;
}
elsif ($_=~ /(.*) = \s+(.*)/ ) {
$mw -> messageBox(-message=> "\nFormat not correct on line $. of input file. Exiting script\n");
exit;
}
elsif ($_=~ /^TASK_CELL_NAME\|VALUE = (.*)/ ) {
my $cell_name = $1;
chomp $cell_name;
unless(grep( /^$cell_name $/, #cell_names )) {
push #cell_names, "$cell_name ";
#$count++;
#print "\nCELL NAME: $cell_name\n";
replace($cell_name);
}
}
}
close INPUT_FILE;
Update: lfr_task62_bunch_rpl before running code:
# Select fund
FUND|VALUE = mmi
# Select bank
BANK|VALUE = citi
# Select cell name
TASK_CELL_NAME|VALUE = lfr
# Select task
TASK|VALUE = task62
# Select task version
TASK_VERSION|VALUE = 1.0.9.0
# Select fund type
FULL_ESD|VALUE = MUTUAL
# Select customer premium
CUSTOM_CELL_SS|VALUE = YES
# Select customer brand density
CUSTOM_CELL_DENSITY|VALUE = 0.76
# Select card chip
CHIP_PKG_TYPE|VALUE|VALUE = OUTLINE
Expected lfr_task62_bunch_rpl after running code:
# Select fund
FUND|VALUE = mmi
# Select bank
BANK|VALUE = citi
# Select cell name
TASK_CELL_NAME|VALUE = lfr
# Select task
TASK|VALUE = task62
# Select task version
TASK_VERSION|VALUE = 2.0.9.0
# Select fund type
FULL_ESD|VALUE = POWER
# Select customer premium
CUSTOM_CELL_SS|VALUE = YES
# Select customer brand density
CUSTOM_CELL_DENSITY|VALUE = 0.76
# Select card chip
CHIP_PKG_TYPE|VALUE|VALUE = INLINE
It's not really clear what this code is supposed to do. But I can immediately see a few problems with the logic. Let's step through a few iterations of the loop, using your sample data file.
The first time, the line of data read in is:
TASK_CELL_NAME|VALUE = lf
So that matches on your second regex match. You set a few variables and then (because $ip_var is equal to "TASK_CELL_NAME") you skip to the else clause and close a filehandle that isn't open.
Next time round, we read:
TASK|VALUE = task62
That matches your first regex match. The variable $rpl_file is set to "XXX_lfr_bunch_rpl" (where 'XXX' is the parameter passed to the subroutine - obviously, I don't know what that is). You print a "000" line with that value and open the file with that name in r/w mode.
Third time round, we get this data:
TASK_VERSION|VALUE = 2.0.9.0
This matches your second regex and because $ip_var isn't equal to "TASK_CELL_NAME" we go into the if clause. This reads from your open filehandle and prints a "111" line. But this generates a warning if you have use warnings switched on as the line includes the value of $rpl_file which is currently defined. It was set the last time around the loop, but because the variable is declared inside the loop, it has now lost its value. We then close the filehandle.
The fourth iteration will be the last one that's really interesting. We get this data:
CHIP_PKG_TYPE|VALUE = INLINE
This also matches the second regex, so we do a lot the same as the third iteration. But the difference here is that when we try to read from the filehandle, we get a warning because that filehandle is closed. Oh, and then we close it again for good measure :-)
As I said at the start, I can't really work out what we're trying to do here. But I can see that the logic is very strange. You really need to go back to the drawing board and think through your logic again.
Update:
With the updated version of your code, I'm still seeing problems.
On the first iteration, the data is:
TASK_CELL_NAME|VALUE = lf
So this matches your second regex. That goes into the piece of code that opens the other file and tries to read from it. But it expects to find the filename in $rpl and that variable hasn't been given a value yet. So the open() fails and the program dies.

Perl6 one liner execution. How is the topic updated?

Executing the one liner to process CSV a line at a time from stdin:
perl6 -ne 'my #a; $_.split(",").kv.map: {#a[$^k]+=$^v}; say #a; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"}';
Typing in:
1,1
1,1
^D
Gives the following output:
BEGIN
ENTER
1,1
[1 1]
1,1
[2 2]
LEAVE
END
Here we can see that the one liner is not a block executed multiple times as the ENTER and LEAVE phaser are only executed once.
This makes sense as the variable #a is accumulating. If the one liner was a block the value of #a would be reset each time.
My question is how does the topic variable $_ get updated? The topic variable is a Str (at least that's what $_.^name says). How does its value update without re-entering the block?
What am I missing?
When you add -n it adds a for loop around your code.
You think it adds one like this:
for lines() {
# Your code here
}
The compiler just adds the abstract syntax tree nodes for looping without actually adding a block.
(
# Your code here
) for lines()
(It could potentially be construed as a bug.)
To get it to work like the first one:
( # -n adds this
-> $_ { # <-- add this
# Your code here
}( $_ ) # <-- add this
) for lines() # -n adds this
I tried just adding a bare block, but the way the compiler adds the loop causes that to not work.
In general ENTER and LEAVE are scoped to a block {}, but they are also scoped to the “file” if there isn't a block.
ENTER say 'ENTER file';
LEAVE say 'LEAVE file';
{
ENTER say ' ENTER block';
LEAVE say ' LEAVE block';
}
ENTER file
ENTER block
LEAVE block
LEAVE file
Since there is no block in your code, everything is scoped to the “file”.
The -n command line argument puts a loop around your program,
for $*ARGFILES.lines {
# Program block given on command line
}
whereas the program execution phasers you used (BEGIN and END), are run once either at compile time or after the program block has finished, so they will not be part of the loop at run time.
The ENTER block phaser will run at every block entry time, whereas the
the LEAVE block phaser will run at every block exit time. So these phasers will be run for each line read in the for loop.
Update -- Rakudo 2020.10
Running your original accumulator code (using the -ne linewise flag) gives the following result. Note how the word "final" appears in every line:
~$ perl6 -ne 'my #a; $_.split(",").kv.map: {#a[$^k]+=$^v}; say #a, " final"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
ENTER
[1 1] final
[2 3] final
[3 6] final
LEAVE
END
Below, running essentially duplicate scripts back-to-back with the -ne flag gives an interesting result. BEGIN, ENTER,LEAVE, and END show up in the exact same location, duplicated on the order of once-per-call:
~$ perl6 -ne 'my #a; .split(",").kv.map: {#a[$^k]+=$^v}; say #a, " final_a"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"}; my #b; .split(",").kv.map: {#b[$^k]+=$^v}; say #b, " final_b"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
BEGIN
ENTER
ENTER
[1 1] final_a
[1 1] final_b
[2 3] final_a
[2 3] final_b
[3 6] final_a
[3 6] final_b
LEAVE
LEAVE
END
END
However, removing the -ne flag below lets you run a for lines() {...} loop within the Raku code itself (single script, not duplicated back-to-back). This result seems more in line with what you were expecting:
~$ perl6 -e 'my #a; for lines() {.split(",").kv.map: {#a[$^k]+=$^v};}; say #a, " final"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
ENTER
[3 6] final
LEAVE
END
I think the short answer to your questions is that Phasers respect Block/Loop semantics, but are limited script-wise as to how many times they will report back to the implementer (apparently only once per call). But the ultimate difference is that the return to the user is linewise for the -ne command line flag, as compared to an internal for lines() {...} loop sans the -ne command line flag.
Finally, you can always force the reloading of the $_ topic variable with the andthen infix operator. Maybe this is what you were looking for all along:
~$ perl6 -e 'my #a; for lines() {.split(",").kv.map: {#a[$^k]+=$^v} andthen $_.say }; say #a, " final"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
ENTER
(1 1)
(2 3)
(3 6)
[3 6] final
LEAVE
END
[Test file under analysis, below].
~$ cat drclaw.txt
1,1
1,2
1,3
https://docs.raku.org/language/operators#index-entry-andthen

How to make the script to return with specified value in Perl debugger?

I tried various ways, but none works...
DB<4> T
. = main::t() called from file `dbg' line 6
DB<4> return;
DB<5> T
. = main::t() called from file `dbg' line 6
DB<5> return 1;
DB<6> T
. = main::t() called from file `dbg' line 6
DB<6> eval('return')
DB<7> T
. = main::t() called from file `dbg' line 6
The point is I don't want the subsequent code to be run, just return with specified value.
So it's not r.
This is obviously ghetto but you could wait until you pop back out of routine and then manually set the lvalue before proceeding in the calling routine.

How can I enter a password using Perl and replace the characters with '*'?

I have a Perl script that requires the user to enter a password. How can I echo only '*' in place of the character that the user types, as they type it?
I'm using Windows XP/Vista.
In the past I have used IO::Prompt for this.
use IO::Prompt;
my $password = prompt('Password:', -e => '*');
print "$password\n";
If you don't want use any packages... Only for UNIX
system('stty','-echo');
chop($password=<STDIN>);
system('stty','echo');
You can play with Term::ReadKey. Here is a very simple example, with some detection for backspace and delete key. I've tested it on Mac OS X 10.5 but according to the ReadKey manual it should work under Windows. The manual indicates that under Windows using non-blocking reads (ReadKey(-1)) will fail. That's why I'm using ReadKey(0) who's basically getc (more on getc in the libc manual).
#!/usr/bin/perl
use strict;
use warnings;
use Term::ReadKey;
my $key = 0;
my $password = "";
print "\nPlease input your password: ";
# Start reading the keys
ReadMode(4); #Disable the control keys
while(ord($key = ReadKey(0)) != 10)
# This will continue until the Enter key is pressed (decimal value of 10)
{
# For all value of ord($key) see http://www.asciitable.com/
if(ord($key) == 127 || ord($key) == 8) {
# DEL/Backspace was pressed
#1. Remove the last char from the password
chop($password);
#2 move the cursor back by one, print a blank character, move the cursor back by one
print "\b \b";
} elsif(ord($key) < 32) {
# Do nothing with these control characters
} else {
$password = $password.$key;
print "*(".ord($key).")";
}
}
ReadMode(0); #Reset the terminal once we are done
print "\n\nYour super secret password is: $password\n";
You should take a look at either Term::ReadKey or Win32::Console. You can use those modules to read the single key strokes and emit '*' or whathever.
Building on Pierr-Luc's program, just added some control on the backslashes. With this, you can't keep pressing backslash forever:
sub passwordDisplay() {
my $password = "";
# Start reading the keys
ReadMode(4); #Disable the control keys
my $count = 0;
while(ord($key = ReadKey(0)) != 10) {
# This will continue until the Enter key is pressed (decimal value of 10)
# For all value of ord($key) see http://www.asciitable.com/
if(ord($key) == 127 || ord($key) == 8) {
# DEL/Backspace was pressed
if ($count > 0) {
$count--;
#1. Remove the last char from the password
chop($password);
#2 move the cursor back by one, print a blank character, move the cursor back by one
print "\b \b";
}
}
elsif(ord($key) >= 32) {
$count++;
$password = $password.$key;
print "*";
}
}
ReadMode(0); #Reset the terminal once we are done
return $password;
}
using Pierr-Luc's program
# Start reading the keys
ReadMode(4); #Disable the control keys
while(ord($key = ReadKey(0)) != '13' )
# This will continue until the Enter key is pressed (decimal value of 10)
{
# For all value of ord($key) see http://www.asciitable.com/
if(ord($key) == 127 || ord($key) == 8 && (length($password) > 0)) {
# DEL/Backspace was pressed
#1. Remove the last char from the password
chop($password);
#2 move the cursor back by one, print a blank character, move the cursor back by one
print "\b \b";
} elsif(ord($key) > 32) {
$password = $password.$key;
print "*";
}
}
ReadMode(0); #Reset the terminal once we are done
Have you tried storing the string (so that your program can still read it) and find out its length then create a string of the same length, but only use '*'?

How can I suppress Excel's password prompt in Perl?

Please tell me a solution to suppress passsword prompting of an excel file.
use Win32::OLE;
my $xlApp = Win32::OLE->new('Excel.Application');
$xlApp->{Visible} = 0;
$xlApp->{DisplayAlerts} = 0;
# Open excel file.
my $xlBook = $xlApp->Workbooks->Open("C:\\Documents and Settings\\username\\Desktop\\testfile.xls");
my $Sheet1 = $xlBook->Worksheets(1);
my $row = 1;
my $col = 1;
$Sheet1->Cells($row,$col)->{'Value'} = 5;
if (Win32::OLE->LastError)
{
print "File protected";
}
$xlBook ->Close();
undef $xlBook;
If you know the passwords, you can supply them in the password and/or writerespassword arguments of the open command. Excel will not prompt for the passwords if they are supplied this way.
If you don't know the passwords but want to prevent the dialog box from appearing, you can supply dummy passwords in these parameters ("ThisIsNotAPassword", for instance). I have not found this in the documentation, but tested it in Excel 2003:
If the Excel file does not have passwords, it is opened.
If it does have passwords (other than those supplied), it will not ask the user for a password, but fail with an error you can detect.
You may convert the following vb code to perl and give a try,
Please note that this code is for vbproject, similary you can check for the worksheets, cells, or entire sheet, the same way.
' returns TRUE if the VB project in the active document is protected
' Please not
Function ProtectedVBProject(ByVal wb As Workbook) As Boolean
Dim VBC As Integer
VBC = -1
On Error Resume Next
VBC = wb.VBProject.VBComponents.Count
On Error GoTo 0
If VBC = -1 Then
ProtectedVBProject = True
Else
ProtectedVBProject = False
End If
End Function
Example:
If ProtectedVBProject(ActiveWorkbook) Then Exit Sub
For Worksheet
If ActiveWorkbook.ProtectStructure=True Then Exit Sub
For active work book windows
If ActiveWorkbook.ProtectWindows= True Then Exit sub
and so on..
Or You can open excel sheet with password
The Open method for the Workbook
object, takes 12 arguments. To open a workbook with password protection, you would need to write the following code:
Workbooks.Open "Book1.xls", , , ,"pswd"
You can also check with perl the same with empty arguments. I am not sure how to give...
Working off of lakshmanaraj's idea, and unknown's response:
use Win32::OLE;
sub is_protected_vb_project {
my $work_book = shift;
eval {
my $count = $work_book->{VBProject}{VBComponents}{Count};
};
Carp::carp $# if $#;
return $# ? 1 : 0;
}
my $work_book = Win32::OLE->GetObject( 'd:/some/path/somewhere.xls' );
printf "is_protected_vb_project( \$work_book )=%s\n"
, is_protected_vb_project( $work_book )
;