how to know the last printed text in QBasic - qbasic

I want to know that how to get the last printed text in QBasic.
Like if the program prints several lines, then how to get the last line printed.
Like this-
Print "aaaaaaa"
Print "bbbbbbb"
Then the program will get the last printed line i.e. bbbbbbb

Something like this maybe?
str$ = "aaaaaaa"
PRINT str$
str$ = "bbbbbbb"
PRINT str$
PRINT "last printed line:"; str$
Alternatively, as explained here, you can retrieve characters from screen memory by using PEEK at segment &HB800 , so something like this
DEF SEG = &HB800
mychar = PEEK(1) 'etc
You'd have to keep track of on which line was last printed to know where exactly you need to PEEK, so that will probably get very complicated very quickly...
For that reason I recommend you to rethink what it is exactly that you are trying to accomplish here because "screen scraping" like this is usually just a bad idea.

Given that last printed string did not end with semicolon, this code should do the trick:
FOR char.num = 1 TO 80
last.line$ = last.line$ + chr$(SCREEN(CSRLIN - 1, char.num))
NEXT char.num
PRINT "Content of last line printed to is:"; last.line$
Explanation: CSRLIN returns the current line of the cursor. SCREEN(y, x) returns the ascii-code of the character at y, x position (line, row) on the screen. Each time a string not ending with semicolon is printed to the screen, it is printed on the current line (y position) of the cursor, which is then incremented by one.

I realise this question already has an accepted answer but I have my own solution where instead of trying to work out what PRINT last PRINTed you instead use you own PRINT SUB in this example MYPRINT. While its not perfect and it only takes strings (hence STR$(123) and uses SHARED variables which are not necessarily advisable it is nicer than poking in the memory.
DECLARE SUB MYPRINT (text$)
DIM SHARED lastprint$
MYPRINT ("Hello, World!")
MYPRINT (STR$(123))
MYPRINT ("Hi Again")
MYPRINT (lastprint$)
SUB MYPRINT (text$)
PRINT (text$)
lastprint$ = text$
END SUB
The output:
Hello, World!
123
Hi Again
Hi Again

Related

Perl: how to format a string containing a tilde character "~"

I have run into an issue where a perl script we use to parse a text file is omitting lines containing the tilde (~) character, and I can't figure out why.
The sample below illustrates what I mean:
#!/usr/bin/perl
use warnings;
formline " testing1\n";
formline " ~testing2\n";
formline " testing3\n";
my $body_text = $^A;
$^A = "";
print $body_text
The output of this example is:
testing1
testing3
The line containing the tilde is dropped entirely from the accumulator. This happens whether there is any text preceding the character or not.
Is there any way to print the line with the tilde treated as a literal part of the string?
~ is special in forms (see perlform) and there's no way to escape it. But you can create a field for it and populate it with a tilde:
formline " \#testing2\n", '~';
The first argument to formline is the "picture" (template). That picture uses various characters to mean particular things. The ~ means to suppress output if the fields are blank. Since you supply no fields in your call to formline, your fields are blank and output is suppressed.
my #lines = ( '', 'x y z', 'x~y~z' );
foreach $line ( #lines ) { # forms don't use lexicals, so no my on control
write;
}
format STDOUT =
~ ID: #*
$line
.
The output doesn't have a line for the blank field because the ~ in the picture told it to suppress output when $line doesn't have anything:
ID: x y z
ID: x~y~z
Note that tildes coming from the data are just fine; they are like any other character.
Here's probably something closer to what you meant. Create a picture, #* (variable-width multiline text), and supply it with values to fill it:
while( <DATA> ) {
local $^A;
formline '#*', $_;
print $^A, "\n";
}
__DATA__
testing1
~testing2
testing3
The output shows the field with the ~:
testing1
~testing2
testing3
However, the question is very odd because the way you appear to be doing things seems like you aren't really doing what formats want to do. Perhaps you have some tricky thing where you're trying to take the picture from input data. But if you aren't going to give it any values, what are you really formatting? Consider that you may not actually want formats.

Perl hash while loop cannot find the key value

I am confused by one perl question, anyone has some idea?
I use one hash structure to store the keys and values like:
$hash{1} - > a;
$hash{2} - > b;
$hash{3} - > c;
$hash{4} - > d;
....
more than 1000 lines. I give a name like %hash
and then, I plan to have one loop statement to search for all keys to see whether it will match with the value from the file.
for example, below is the file content:
first line 1
second line 2
nothing
another line 3
my logic is:
while(read line){
while (($key, $value) = each (%hash))
{
if ($line =~/$key/i){
print "found";
}
}
so my expectation is :
first line 1 - > return found
second line 2 - > return found
nothing
another line 3 - > return found
....
However, during my testing, only first line and second line return found, for 'another line3', the
program does not return 'found'
Note: the hash has more than 1000 records.
So I try to debug it and add some count inside and find out for those found case, the loop has run like 600 or 700 times, but for the 'another line3' case, it only runs around 300 times and just exit the loop and did not return found.
any idea why it happens like that?
and I have done one more testing is if my hash structure is small, like only 10 keys, the logic works.
and I try to use foreach, and It looks like foreach does not have this kind of issue.
The pseudo code you give should work fine, but there might be a subtle problem.
If after you found your key and print it out you end the while loop, the next time each is called, it will continue where you left. Put it in other words "each" is an iterator that stores its state in the hash it iterates over.
In http://blogs.perl.org/users/rurban/2014/04/do-not-use-each.html the author explains this in more detail. His conclusion:
So each should be treated as in php: Avoid it like a plague. Only use it in optimized cases where you know what you are doing.
The problem is not very well articulated by OP, provided sample data are poor for demonstration purpose.
Following sample code is an attempt based on provided problem description by OP.
Recreate filter hash from DATA block, compose $re_filter consisting of filter hash keys, walk through a file given as an argument on command line to filter out lines matching $re_filter.
use strict;
use warnings;
my $data = do { local $/; <DATA> };
my %hash = split ' ', $data;
my $re_filter = join('|',keys %hash);
/$re_filter/ && print for <>;
__DATA__
1 a
2 b
3 c
4 d
Input data file content
first line 1
second line 2
nothing
another line 3
Output
first line 1
second line 2
another line 3

Print function in a foreach loop : my scalar and text does not print

This is a extract from my code :
foreach my $nouveau_code (#tableau_codes_utilises) {
my $code_found = 0;
foreach my $ligne_code_prospect (#tableau_liste_codes_prospects) {
//SOME CODE
}
print "HERE IS $nouveau_code\n";
if ( $code_found == 0 ) {
print "le code $nouveau_code n'a pas été trouvé\n";
STDOUT->autoflush;
}
}
And the result of an iteration where $code_found is equal to 0 is (code is hidden here, but is alphanumeric) :
HERE IS PAR****
n'a pas été trouvé
I do not understand why the second print (in the if sequence) does not print the whole line. I guess there is a buffering problem but I cannot find what is going on.
Any help would be appreciated.
At a guess, $nouveau_code has come from a file that originated on a Windows system and you are processing it on Linux?
If you use chomp in such a circumstance then it will remove the trailing newline, but not the carriage return, and printing the value will reset the screen cursor to the beginning of the line before printing anything else
The simple fix is to replace chomp with s/\R//, which will remove the CR as well as the LF on the end of the line
I suspect what is happening here is that your second data item contains backspaces (BS) or a carriage return (CR). So
your first item runs and prints out the first time, but since code_found=1 it doesn't go into the if.
your second item runs and the CR or BS in the data obscure the fact that the HERE IS was printed
your second item does not have a code found so the second print happens and the first part of it is overwritten by the same CR or BS sequence in your variable
The easy way to confirm this is to redirect your output and look at it like so:
script > check.log
vim check.log
and you should see the extra data in there. less would work fine in place of vim also.

Update command line output

My program (which happens to be in Perl, though I don't think this question is Perl-specific) outputs status messages at one point in the program of the form Progress: x/yy where x and yy are a number, like: Progress: 4/38.
I'd like to "overwrite" the previous output when a new status message is printed so I don't fill the screen with status messages. So far, I've tried this:
my $progressString = "Progress\t$counter / " . $total . "\n";
print $progressString;
#do lots of processing, update $counter
my $i = 0;
while ($i < length($progressString)) {
print "\b";
++$i;
}
The backspace character won't print if I include a newline in $progressString. If I leave out the newline, however, the output buffer is never flushed and nothing prints.
What's a good solution for this?
Use autoflush with STDOUT:
local $| = 1; # Or use IO::Handle; STDOUT->autoflush;
print 'Progress: ';
my $progressString;
while ...
{
# remove prev progress
print "\b" x length($progressString) if defined $progressString;
# do lots of processing, update $counter
$progressString = "$counter / $total"; # No more newline
print $progressString; # Will print, because auto-flush is on
# end of processing
}
print "\n"; # Don't forget the trailing newline
Say
$| = 1
somewhere early in your program to turn autoflushing on for the output buffer.
Also consider using "\r" to move the cursor back to the beginning of the line, rather than trying to explicitly count how many spaces you need to move back.
Like you said, don't print out a newline while your progress counter is running or else you will print out your progress on a separate line instead of overwriting the old line.
I know it's not quite what you asked for, but possibly better. I happened on this same problem and so rather than deal with it too much went to using Term::ProgressBar which looks nice too.
You can also use the ANSI escape codes to directly control the cursor. Or you can use Term::ReadKey to do the same thing.
I had to tackle something similar to this today.
If you don't mind reprinting the entire line, you could do something like this:
print "\n";
while (...) {
print "\rProgress: $counter / $total";
# do processing work here
$counter++;
}
print "\n";
The "\r" character is a carriage return-- it brings the cursor back to the beginning of the line. That way, anything you print out overwrites the previous progress notification's text.

Why does my Perl if condition always evaluate to true?

In Perl, I need to read a .conf file that contains either a 0 or a 1. If the value is one, I need to execute whatever is in the if statement. Here is what I have now:
open(CONF, "/var/web/onhit.conf");
if(<CONF>) {
print "Hello World!";
}
close(CONF);
The contents of the if statement always evaluate, even if the .conf file contains a 0. I know the file reading is correct because this code can read the file correctly:
open(CONF, "/var/web/onhit.conf");
print <CONF>;
close(CONF);
If the file contains a 1, it prints a 1, and vice versa. Does anyone know what is wrong with my first snippet? Sorry, but I am a n00b at Perl. :-)
EDIT: Apparently, you had the truth value of your post inverted, and you meant to say that the if() statement always executed. This makes sense. What happens is that <CONF> reads in the string "1\n" or "0\n", not the number 1 or 0. The trailing newline prevents "0" from evaluating as false, so you need to chomp() it (or use the int() function, as mentioned in the other post). Either way should work.
(Note that, unfortunately, chomp() does not return the chomp()ed string, but a count of how many characters it removed, so you can't just say if(chomp(my $tmp = <CONF>)) and be done with it.)
Anyway, this is what I did:
open(CONF, "/var/web/onhit.conf");
chomp(my $tmp = <CONF>);
if($tmp) {
print "Hello, world!\n";
}
close CONF;
A few recommendations:
Consider using the three-argument form of open(), or at least specifying "<" in front of the filename.
Consider using a variable to hold a filehandle ($conf) rather than using the older, clumsier filehandle form (CONF).
This is the code I would have written:
open my $conf, "<", "/var/web/onhit.conf";
chomp(my $tmp = <$conf>);
if($tmp) {
print "Hello, world!\n";
}
close $conf;
You simply need to convert the string to an integer using the int function.
open(CONF, "/var/web/onhit.conf");
if(int(<CONF>)) {
print "Hello World!";
}
close(CONF);
Or you could just include in the newline in the comparison:
if (<CONF> =~ /^1$/) {
}