Syntax error with UCASE$? - qbasic

Not sure what this means. It says it's a syntax error with UCASE$ but can I not put letter$ in there?
CLS
PRINT "Do you want lower case or upper case? (U/L)"
DO
CASED$ = INKEY$
LOOP UNTIL CASED$ = "U" OR CASED$ = "L"
IF CASED$ = "L" THEN
FOR char = 1 TO 26
READ letter$
PRINT letter$; " = "; ASC(letter$)
SLEEP 1
NEXT char
ELSE
FOR char = 1 TO 26
READ letter$
UCASE$(letter$)
PRINT letter$; " = "; ASC(letter$)
SLEEP 1
NEXT char
END IF
DATA a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z

UCASE$ is a function that returns a string. You need to pass what it returns into a variable. A common behavior of most built-in functions in BASIC is that they can stand in place of a variable or expression.
letter$ = UCASE$(letter$)
To demonstrate why this is, try
a$ = "h"
PRINT a$, UCASE$(a$)
in a new program. As you can see, UCASE$ itself becomes the new string instead of manipulating the original string. If you want to preserve the result of the function, you must pass it into a variable.

Related

How can I extract first and last line from multiple text blocks separated with new line?

I have a file containing multiple tests with detailed action written one beneath another. All test blocks are separated one from another by new line. I want to extract only first and last line from the all blocks and put it on one line for each block into a new file. Here is an example:
input.txt:
[test1]
duration
summary
code=
Results= PASS
[test2]
duration
summary=x
code=
Results=FAIL
.....
[testX]
duration
summary=x
code=
Results= PASS
output.txt should be sometime like this:
test1 PASS
test2 FAIL
...
testX PASS
eg2:
[Linux_MP3Enc_xffv.2_Con_37_003]
type = testcase
summary = MP3 encoder test
ActionGroup[Linux_Enc] = PASS
ActionGroup[Linux_Playb] = PASS
ActionGroup[Linux_Pause_Resume] = PASS
ActionGroup[Linux_Fast_Seek] = PASS
Duration = 230.607398987 s
Total_Result = PASS
[Composer__vtx_007]
type = testcase
summary = composer
Background[0xff000000] = PASS
Background[0xffFFFFFF] = PASS
Background[0xffFF0000] = PASS
Background[0xff00FF00] = PASS
Background[0xff0000FF] = PASS
Background[0xff00FFFF] = PASS
Background[0xffFFFF00] = PASS
Background[0xffFF00FF] = PASS
Duration = 28.3567230701 s
Total_Result = PASS
[Videox_Rotate_008]
type = testcase
summary = rotation
Rotation[0] = PASS
Rotation[1] = PASS
Rotation[2] = PASS
Rotation[3] = PASS
Duration = 14.0116529465 s
Total_Result = PASS
Thank you!
Short and simple gnu awk:
awk -F= -v RS='' '{print $1 $NF}' file
[Linux_MP3Enc_xffv.2_Con_37_003] PASS
[Composer__vtx_007] PASS
[Videox_Rotate_008] PASS
If you do not like the brackets:
awk -F'[]=[]' -v RS='' '{print $2 $NF}' file
Linux_MP3Enc_xffv.2_Con_37_003 PASS
Composer__vtx_007 PASS
Videox_Rotate_008 PASS
Using sed as tagged (although other tools would probably be more natural to use) :
sed -nE '/^\[.*\]$/h;s/^Results= ?//;t r;b;:r;H;x;s/\n/ /;p'
Explanation :
/^\[.*\]$/h # matches the [...] lines, put them in the hold buffer
s/^Results= ?// # matches the Results= lines, discards the useless part
t r;b # on lines which matched, jump to label r;
# otherwise jump to the end (and start processing the next line)
:r;H;x;s/\n/ /;p # label r; append the pattern space (which contains the end of the Results= line)
# to the hold buffer. Switch Hold buffer and pattern space,
# replace the linefeed in the pattern space by a space and print it
You can try it here.
One way to solve this is using a regular expression such as:
(?<testId>test\d+)(?:.*\n){4}.*(?<outcome>PASS|FAIL)
The regex matches your sample output and stores the test id (e.g. "test1") in the capture group named "testId" and the outcome (e.g. "PASS") in the capture group "outcome".
(Test it in regexr)
The regex can be used in any language with regex support. The below code shows how to do it in Python.
(Test it in repl.it)
import re
# Read from input.txt
with open('input.txt', 'r') as f:
indata = f.read()
# Modify the regex slightly to fit Python regex syntax
pattern = '(?:.*)(?P<testId>test\d+)(?:.*\n){4}.*(?P<outcome>PASS|FAIL)'
# Get a generator which yeilds all matches
matches = re.finditer(pattern, indata)
# Combine the matches to a list of strings
outputs = ['{} {}'.format(m.group('testId'), m.group('outcome')) for m in matches]
# Join all rows to one string
output = '\n'.join(outputs)
# Write to output.txt
with open('output.txt', 'w') as f:
f.write(output)
Running the above script on input.txt containing:
[test1]
duration
summary
code=
Results= PASS
[test2]
duration
summary=x
code=
Results=FAIL
[test444]
duration
summary=x
code=
Results= PASS
yields a file output.txt containing:
test1 PASS
test2 FAIL
test444 PASS
In order to print the first and last line from the block, how about:
awk -v RS="" '{
n = split($0, a, /\n/)
print a[1]
print a[n]
}' input.txt
Result for the 1st example:
[Linux_MP3Enc_xffv.2_Con_37_003]
Total_Result = PASS
[Composer__vtx_007]
Total_Result = PASS
[Videox_Rotate_008]
Total_Result = PASS
The man page of awk tells:
If RS is set to the null string, then records are separated by blank lines.
You can easily split the block with blank lines with this feature.
Hope this helps.

Error with Substring()

$fileName = "Name of TheFolder_NE_ED"
$lengthFileName = $fileName.length
$shortenLengthFileName = $lengthFileName - 5
Write-Host("Name of TheFolder_NE_ED").Substring($shortenLengthFileName,$lengthFileName)
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
I am having a problem with SubString() function, it errors with:
I tried printing out values of my variables but they seemed fine.
In PowerShell, substring works in a slightly different way.
With your existing code you could try this:
$fileName = "Name of TheFolder_NE_ED"
$lengthFileName = $fileName.length
$shortenLengthFileName = $lengthFileName - 5
Write-Host("Name of TheFolder_NE_ED").Substring($shortenLengthFileName)
Explanation:
The first parameter inside Substring should be the starting index of the character(in this case 18). Now from that letter it will start counting till the character (which you have to pass as a second parameter). Else it will by default go to the end of the string.
So, if you want to pass 2 parameters and do that, then change it to:
Write-Host("Name of TheFolder_NE_ED").Substring($shortenLengthFileName,5)
For further reference, follow Substring Use
Hope it helps.

Autofiltering Excel with multiple filter conditions

I am trying to autofilter in Excel using the below VBScript code. This script called multiple times from a Perl program.
Dim objExcel : Set objExcel = GetObject(,"Excel.Application")
objExcel.Visible = True
objExcel.Selection.AutoFilter
objExcel.ActiveSheet.Range("G1").AutoFilter WScript.Arguments.Item(0), _
WScript.Arguments.Item (1)
Now I would like to know: is there a way by which I can pass an array for WScript.Arguments.Item (1) so that all the conditions are selected in one go? The task is to delete the filtered value. I call this script through Perl multiple times and the above script filter one value at a time and delete. The program works fine, but is slow.
Following is the part of Perl which calls the VBScript.
while(<FILE>){
chomp;
system("CSCRIPT "."\"$currentWorkingDirectory\"".'aboveVBS.vbs 9 '."\"$_\"");
sleep(2);
}
If you put quotes around the values, VBScript will treat it as a single argument.
> cscript script.vbs arg1 "multiple values for arg 2"
In the script:
WScript.Echo WScript.Arguments.Count ' ==> 2
a = Split(WScript.Arguments(1))
WScript.Echo a(0) ' ==> multiple
WScript.Echo a(1) ' ==> values
WScript.Echo a(2) ' ==> for
WScript.Echo a(3) ' ==> arg
WScript.Echo a(4) ' ==> 2
Excel expects:
Range.AutoFilter <Field>, <Criteria>, <Operator>
If you want a list of criteria to filter on, you'll use xlFilterValues for the <Operator> argument. <Criteria> will be an array of string values, which we created above.
Const xlFilterVaues = 7
objExcel.ActiveSheet.Range("G1").AutoFilter WScript.Arguments.Item(0), a, xlFilterValues
So, just try adding Split() around WScript.Arguments(1) in your existing code, and pass xlFilterValues for the third param.
If only your second argument changes, you could pass the entire content of your data file to the VBScript:
local $/;
my $args = <FILE>;
$args =~ s/^\s+|\s+$//g;
$args =~ s/\r?\n/" "/g;
system("cscript \"$currentWorkingDirectory\\your.vbs\" 9 \"$args\"");
and change the processing in your VBScript to this:
Set xl = CreateObject("Excel.Application")
xl.Visible = True
Set wb = xl.Workbook.Open("C:\path\to\your.xlsx")
Set ws = wb.Sheets(1)
...
xl.Selection.AutoFilter
For i = 1 To WScript.Arguments.Count - 1
ws.Range("G1").AutoFilter WScript.Arguments(0), WScript.Arguments(i)
...
Next
Or you could simply call the VBScript with the field and the path to the data file:
system("cscript \"$currentWorkingDirectory\\your.vbs\" 9 \"$filepath\"");
and do all the processing in VBScript:
Set xl = CreateObject("Excel.Application")
xl.Visible = True
Set wb = xl.Workbook.Open("C:\path\to\your.xlsx")
Set ws = wb.Sheets(1)
...
xl.Selection.AutoFilter
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(WScript.Arguments(1))
Do Until f.AtEndOfStream
ws.Range("G1").AutoFilter WScript.Arguments(0), f.ReadLine
...
Next
f.Close
Applying more than 2 AutoFilter conditions to a column at the same time is not possible. Check the signature of the AutoFilter method in the documentation:
expression .AutoFilter(Field, Criteria1, Operator, Criteria2, VisibleDropDown)
expression An expression that returns a Range object.
You have Critera1 and Criteria2 and an Operator for combining the two. Calling the AutoFilter method with another set of criteria replaces the existing criteria.

how to search for a sub string within a string in QBasic

I am creating a simple chat programme in QBasic that will answer questions based on some specific key words present in the user input.therefore I need a way to search for a sub string (I.e. A specific word)within a string.
So, please help me.
To find out if a string contains a certain (sub-)string, you can do this:
text$ = "nonsense !"
IF INSTR( text$, "sense" ) >= 1 THEN
PRINT "This text makes sense !"
END IF
And no, I was not able to test this, as a no longer have QBasic on my PC ;-)
According to the link from the comment above >= 1 is ok
I think INSTR is usually used as follows:
sent$ = "This is a sentence"
PRINT INSTR(1, sent$, "is")
PRINT INSTR(4, sent$, "is")
PRINT INSTR(1, sent$, "word")
the first PRINT command will print a '3' since the first location of "is" within the sentence is at position 3. (The 'is' in 'This')
the second PRINT command starts searching at position 4 (the 's' in 'This'), and so finds the "is" at position 6. So it will print '6'.
the third PRINT command will print a '0' since there is no instance of "word" in the sentence.
Counts the occurrences of a substring within a string.
T$ = "text to be searched and to be displayed"
S$ = "to"
l = 1
DO
x = INSTR(l, T$, S$)
IF x THEN
n = n + 1
l = x + LEN(S$)
ELSE
EXIT DO
END IF
LOOP
PRINT "text '"; S$; "' matches"; n; "times."

Trouble padding a Perl string array without increasing array length

I have an integer value my $reading = 1200;.
I have an array my #DigitField = "000000000";
I want to replace the right-hand 4 elements of the array with $reading's value, and I want to do this programmatically using Perl's length function as shown below.
I've tried.
my #DigitField = "000000000";
my $reading = 1200;
splice #DigitField, length(#DigitField) + 1, length $reading, $reading;
print #DigitField;
but I'm getting
0000000001200
and I want the string to remain nine characters wide.
What are some other ways to replace part of a Perl string array?
I think you are possibly confused - the # sigil indicates #DigitField is an array variable. A string is not an array.
I think you want to format the number:
my $reading = 1200;
my $digitfield = sprintf('%09d', $reading);
print $digitfield, "\n";
I added a \n to the end of the print, this adds a newline. Depending on the context of your program, you may or may not want this in the final.