I've begun learning Qbasic. For a beginner exercise, I started with a simple text game. A mountain is located "north", and when you type "north" the console should print "Mountain" after pressing Enter. However, when "north" is typed and Enter is pressed, the code is not being executed. Is this just a beginner's mistake? Should I be pressing something different than Enter?
Here's the code:
CLS
PRINT "There is a mountain to the North"
PRINT "There is a cactus to the East"
PRINT "There is a river to the South"
PRINT "There is a shack to the East"
PRINT " "
INPUT "Type a direction:", direction$
IF direction$ = "north" THEN PRINT "Mountain"
And the output from repl.it:
QBasic (qb.js)
Copyright (c) 2010 Steve Hanov
:
There is a mountain to the North
There is a cactus to the East
There is a river to the South
There is a shack to the East
:
Type a direction: north
:
Your code works just fine when running QBasic in DOSBox, but apparently the QB JavaScript library used by repl.it doesn't work quite as QBasic does. When you press Enter, the input should just end, and the end-of-line sequence shouldn't be stored (or should be removed automatically). Unfortunately, the end-of-line sequence was not removed by the JavaScript library. The result is that the following works when it wouldn't work in QBasic:
IF direction$ = "north" + CHR$(10) THEN PRINT "Mountain"
In fact, I added a simple alternative to test the interpreter and received a parse error before I figured out the problem with CHR$(10):
IF direction$ = "north" THEN PRINT "Mountain" ELSE PRINT "Not Mountain"
Based on this problem, I suggest running your program using the real thing (in a DOS emulator like DOSBox) or even something like FreeBASIC or QB64, both of which are based on QBasic and retain the same syntax, though I think QB64 is perhaps a little more compatible with the original.
You could also strip off the trailing ascii characters:
INPUT X$
IF INSTR(X$, CHR$(10)) THEN
X$ = LEFT$(X$, INSTR(X$, CHR$(10)) - 1) ' trim string
END IF
X$ = LCASE$(X$) ' and force case
That way X$ will contain only 'north'..
Related
I identified a problem of special characters with “I” on a turkish version of Windows 10 with a Turkish Excel version. “i” gives another letter in Turkish when it is translated to uppercase: “İ” and not “I”, as for instance when "i" is converted to upper case in English.
The problem is that when I use non case sensitive Excel search formulas (for instance “match” or “countif” formulas), the Turkish Excel will look for “i” or “İ” (with a dot), which it doesn’t find as the letters are uppercase in the lookup range (and there's no "İ"), while the English version look for “i” or “I”, which they’ll find.
To summarize, I search for "i" in a non-case sensitive way, and my Turkish colleague doesn't find any result, because his computer looks for "i" and "İ", and all the expected results are with "I".
I cannot ask the users having this problem to change the language in Excel or in Windows, nor change the lookup source or target ranges. But I can change the formulas (match and countifs are used).
I'm not sure where this lower to uppercase conversion is coming from, if it's from Excel or Windows. But after installing a Turkish version of Excel on a German version of Windows, I didn't have the problem. So I presume the problem is coming from Windows (some language settings, in the end, knowing that is interesting but won't help much)...
I was thinking to writ a VBA formula to change texts to uppercase AND change dotted capital “İ” to dotless capital “I” with replace, then use this string in my search functions. But I cannot find the dotted capital “İ” in the Chr() formula... I think the Chr() function doesn't use the extended ASCII characters, just the standard ones. See the kind of function I intended to use below.
Function upper_i(myStr As String) As String
upper_i = UCase(myStr)
upper_i = Replace(upper_i, Chr(???), "I")
End Function
How can I tell Excel I want a dotted capital "İ" here?
Thanks for your help!
Assuming I'm reading correctly, maybe try:
Function upper_i(myStr As String) As String
upper_i = UCase$(myStr)
upper_i = Replace(upper_i, ChrW(304), "I")
End Function
Seems to pass the test below at least:
Private Sub TestFunction()
Dim someText As String
someText = "ok, ok, " & ChrW(304)
Debug.Assert someText <> "OK, OK, I"
someText = upper_i(someText)
Debug.Assert someText = "OK, OK, I"
End Sub
I didn't really understand why you're making the string uppercase, but maybe I need to read your question a few more times.
& CHAR(10) & REPT(" ", 20)& "5. Change object BusinessCardRequest(FirstName=$CreatedFor/FirstName;LastName=$CreatedFor/Surname;EmailAddress=$CreatedFor/Email;MobileNumber=$CreatedFor/Mobile;PositionTitle=if $PositionFirst != empty then $PositionFirst/Title else "" "";Brand=if $PositionFirst != empty then getCaption($PositionFirst/Brand) else "" "")"
I have above code in excel and I want to escape so that I show 2 empty string as value for If condition. But it gives error I tried using 3 like """ """ it is also not working. But when I remove one it works.
How to correctly escape 2 " " in excel
The correct way to escape a " in Excel is to add one more " before it.
By escaping a " you are asking Excel to treat it as literal text.
For example:
"The ""fox"" jumped over the lazy dog"
would evaluate as
The "fox" jumped over the lazy dog
In answer to your example below:
But it gives error I tried using 3 like """ """ it is also not working. But when I remove one it works.
You don't have to encase the problematic character in escape characters, you only need to immediately precede the problematic character with the escape character.
From the VBA help file:
GoTo Statement
Branches unconditionally to a specified line within a procedure.
Syntax
GoTo _line_
The required line argument can be any line label or line number.
Remarks
GoTo can branch only to lines within the procedure where it appears.
My question is, how can I jump to a line number using GoTo? (I know how to jump to a label.)
(Note: I'm asking this for curiosity's sake. I have no intention of actually using GoTo this way.)
I understand your dislike of the answer "start the line with a line number", but you can't argue with facts. That is exactly what they mean.
The syntax of VBA/VB6 is designed to be backwards-compatible with the syntax of QuickBasic, and before that with the syntax of GW-Basic/MS-Basic, which dates to the late 1970's and even earlier: the original Dartmouth BASIC Language was created in the '60s.
In MS-Basic, like in every other Basic implementation of the era, every line you added to a program had to start with a line number. The line number told the Basic interpreter two things: a) that you were storing the line (otherwise the interpreter would execute it immediately), and b) in what position of the program the line belonged. Why do something so arcane? because when Basic was invented it was intended to be interactive, in a world where the only form of interactivity was a command-line prompt, on a teletype-style printing terminal.
And there were no labels.
A typical Basic session might have looked like this, where > stands for a command processor prompt (this is made-up, but close enough to how it worked). Remember: there are no cursor keys or screens. You are typing on a typewriter - with a roll of paper instead of a screen - and the typewriter responds back at you by printing on the paper as well!:
Welcome to B.A.S.I.C.
Ok <--- Ok told you the interpreter was ready
>LIST <--- print the program
Ok <--- No program, so nothing to list.
>PRINT 2 + 7 <--- No line number, so execute immediately
9 <--- The command executes
Ok
>30 PRINT 2 + 7 <--- Line number, so store the command in position 30
Ok
>10 I = 42 <--- Line number, so store in line 10
Ok
>20 PRINT I + 12 <--- Store on line 20, so insert between 10 and 30
Ok
>LIST <--- Print the program so far
10 I = 42
20 PRINT I + 12
30 PRINT 2 + 7
Ok
>RUN <--- Execute the stored program now
54 <--- line 10 has no output. Line 20 outputs this
9 <--- line 30 outputs this
Ok <--- Done running the program
>20 <--- an empty line number: it means delete the line
Ok
>LIST
10 I = 42
30 PRINT 2 + 7 <--- line 20 is gone!
Primitive? Maybe, but you have to start somewhere.
Back then, you always used GOTO by providing the line number where you wanted the code to jump. It was just how it worked. For example:
10 PRINT "Testing, "
20 I = 1
30 PRINT I; ","
40 IF I >= 3 THEN 60
50 GOTO 30
60 END
QuickBasic was an enhanced version of Basic published by Microsoft that supported optionally compiling programs into executables, rather than running then in the interpreter interactively. Among other enhancements, it also added these two features:
Because it ran full-screen with a fully-featured GUI text editor, it didn't need line numbers to designate where each new line went; you just moved the cursor and typed: traditional line numbers were now optional. In fact, they were discouraged because in a full-featured editor, they just got in the way. But they couldn't just remove them because they were so central to BASIC compatibility, so they were still supported. And they still are, even in VBA.
Since they didn't want you to use line numbers, they needed an alternative for commands that required line numbers as targets, such as GOTO. you were now allowed to place line text labels that could be used as targets for GOTO, etc.
So, you can see that line numbers are not just "line labels made out of digits". They are actually an alternative syntax that has been maintained for compatibility with older versions of the language.
That's it. The help file is simply telling you about the "modern" syntax of GOTO (with text labels), and that - if you really want to - you can still use the legacy syntax with line numbers and legacy GOTO syntax that was invented in the mid-1960's.
Sub Jump()
10 Dim A As Integer
20 A = 25
30 GoTo 50
40 A = 50
50 Debug.Print A
End Sub
It's a throwback to the old (really old) BASIC days, where line numbers were required. Now labels are used.
Sub Jump2()
Dim A As Integer
A = 25
GoTo JumpToHere
A = 50
JumpToHere:
Debug.Print A
End Sub
But using GoTo is considered poor programming, with the exception of OnError GoTo ...
One very useful purpose for old fashion line numbers is for error handling. Many folks utilize a standard error handler of the Sort:
proc name (args)
on error goto handler
code
.
.
exit proc
handler:
debug.print err.number & "(" & err.description & ") in Module: " & ModuleName & "- Proc:" & ProcName at & now
resume next
Exit Proc
Which can be made somewhat more useful In the code Is line numbered, as the ErrLine Property will return the line number
of the offending executable line.
debug.print err.number & "(" & err.description & ") - on Line " & errLine & " in Module: " & ModuleName & "- Proc:" & ProcName at & now
declaring the line number and declaring a lable is basicly the same
but using a line number as a big advantage: it does not use memory!
if your "our of memory" you will not be able to declare a lable
but you will be able to declare a line numer and use that as a "goTo"
sub mySub()
....
on error goto 100
...
exit sub
100: msgbox("Error")
end sub
I read many comments about GOTO being poor programming..
Back in the olden days when
a Hewlit Packard 25 had 25 memories to store all instructions and variables
BASIC was still Beginners All purpose Symbolic Instruction Code and
much better than doing things in 6502 Assembler
I went to computer conference where the
one of the experts was takling about a new language that used blocks and
None of GOTO GOSUB AND RETURN .. yea PASCAL
At the time I KNEW it was impossible to have such a language
but since have spent about 20 years teaching
and designing commercial software in PASCAL
With MS backing their Office with VBA of course Pascal has become rare
even though Delphi was still used as a early years teaching language.
To cut IT short
If you consider the machine code constructed for IF then else end if
and the fact that VBA still evaluates ALL of AND OR NOT XOR in an
If ....... Then when you need to evaluate one a few million times
the then GOTO can save you a few seconds.
However on the topic of ON Error Resume Next
many use these to test if a workbook is open or a Sheets exists
on a closed workbook... ...etc etc ..
In some cases that is poor programming in that the program has to
check all before showing an error whereas
for each ....
while Not Found
found = a = b
wend
only has to check until found
My first teaching computer was a PDP 8 ... 8Kb ..
Punched tape teletype for printing and I/O .. 7 Octal switches to boot.
Then moved up to Comodore 64 ..
Current 16 GB computer has memory of 250,000 of them.
a topical comment
with the FBI CIA etc .....Homeland Security Trumps them all.
I am using ruby on rails but that does not matter much for this question. Let's say that i have a statement like this
error = 'this is an error message'
I have noticed that I end up doing this a lot
error = 'this is an error message'
puts "error = #{error.inspect}"
I am sure a macro can be written which would take the work on the left hand side of left most = and then create another line along with template shown above.
I am using mvim on mac. Any pointer in terms of where I should start to look for developing what I want.
Try snipmate:
http://www.vim.org/scripts/script.php?script_id=2540
I recorded a simple macro that does your sample. To record a macro type q followed by what register you want the macro to be put in (convention calls for qq). To play the macro type # then the macro register. You can view this at :help recording
To write the macro, use the following commands (and here is how is should look in the register)
^yEoputs "error = #{^Op.inspect}"^[
^ moves to the first non whitespace character of the line
yE yanks to the end of the space separated word.
o Puts you in insert mode on the next line
puts "error = #{ is the text that you type out
^O is ctrl+O (capital letter o) - this allows the next, and only the next command to be run in command mode, which is...
p Puts the yanked word, after this command is run you're still in insert mode
.inspect}" is the text that you type and finally...
^[ is Esc
I would go for:
nnoremap µ :s/^\s*\(\k\+\)\s*=.*/&\rputs "\1 = #{\1.inspect}"/<cr>
:s presents the advantage of doing the job plus matching the assigned variable if any. Doing the same thing with classical commands like yw, p, etc would be more cumbersome.
If the template become more complex, we can rely on template-file expanders as long as they easily permit to call viml function like matchstr(). Of course, in that case I would use mu-template with the following template-file:
VimL:" $Id: {rtp}/template/ruby/inspect.template
VimL: let s:value_start = '¡'
VimL: let s:value_end = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:varname = matchstr(getline(line('.')-1), '^\s*\zs\k\+\ze\s*=')
VimL: if empty(s:varname) |throw "the previous line don't assign any variable" |endif
puts "¡s:varname¡ = #{¡s:varname¡.inspect}"<++>
VimL:"vim: encoding=utf-8
If you're doing these on the fly, a snipmate snippet could look like this:
${1:error} = '${2:error message here}'
puts "error = #{$1.inspect}"
If, on the other hand you're just wanting to output pre-existing variables for debugging purposes. Nick-Canzoneri's macro may be more useful.
The command below for Windows Speech Recognition forces the speech recognition engine to use literal text (""all seventy six people paid five dollars") instead of the default ("all 76 people paid $5").
I'm trying to adapt this command to remove the spaces between words so that I could program using speech by saying things like:
"Security Manager"
-> "Security Manager"
"Compound That"
-> "SecurityManager"
The way I think this could work is by using a regex to remove the spaces between the selected text. So, in the following code:
<command priority="5">
<listenFor>literal that</listenFor>
<emulateRecognition>select that</emulateRecognition>
<sendKeys>{250 WAIT}{{CTRL}}c{250 WAIT}</sendKeys>
<!-- Works by first inserting the word " literal " before each word
example "all 76 people paid $5"
is emulated as "literal all literal 76 literal people literal paid literal $5"
which produces the result "all seventy six people paid five dollars"
EmulateRecognition can fail if the text contains improper formatting or nonsense words
(which can easily happen if only part of a word in the document is included in the text selection).
When the failure can be handled by "On Error Resume Next", such as EmulateRecognition("literal s")
or EmulateRecognition("multiple spaces"), we restore the original text and show feedback message.
Unfortunately, some failures, such as EmulateRecognition("nonsens"), cause macros to immediately
halt. This is why "replace that with " is used. Either it succeeds, or it fails non-destructively
(before any text is deleted). Unfortunately, this can be confusing for the user because the macro
can fail without doing anything visible to the user (no changes to the text, and no SetTextFeedback.)
-->
<script language="VBScript">
<![CDATA[
that = Application.clipboardData.GetData("text")
Set regEx = New RegExp
regEx.Pattern = "[^\s\w,;:]"
If regEx.Test(that) Then
Application.SetTextFeedback("Try again without any punctuation selected")
Else
regEx.Pattern = "(\s) *(\S)"
regEx.Global = True
that = regEx.Replace(" " & that, "$1literal $2")
On Error Resume Next
Application.EmulateRecognition("replace that with" & that)
If 0 <> Err.Number Then
Application.SetTextFeedback("Try again with only the digits selected")
End If
End If
]]>
</script>
</command>
instead of writing this:
regEx.Pattern = "(\s) *(\S)"
regEx.Global = True
that = regEx.Replace(" " & that, "$1literal $2")
I think it would need to use some other regex pattern that extracts whitespace between words and pushes the words together in the new output.
I'm not sure how to do that. Would appreciate if anyone has a suggestion.
Since you're already using the 'literal' command, you could also use the 'nospace' command to suppress spaces between words. See the examples on my blog.