Page 1 of 1

Use of GOTO

Posted: Sat Jan 06, 2007 12:27 am
by bigbluehacker
I am trying to rewrite a program with hundreds of GOTOs without using even one. But I quickly ran into a problem.

Code: Select all

alldigit: PRINT "Do you want to use all digits?"
INPUT "Press Y or N and ENTER", alldigit$
IF alldigit$ <> "Y" and alldigit$ <> "N" THEN PRINT "ERROR":GOTO alldigit

How can I avoid using GOTO and a line label?

Posted: Sat Jan 06, 2007 7:16 am
by Ralph
Instead of:

Code: Select all

alldigit: PRINT "Do you want to use all digits?" 
INPUT "Press Y or N and ENTER", alldigit$ 
IF alldigit$ <> "Y" and alldigit$ <> "N" THEN PRINT "ERROR":GOTO alldigit 
use a WHILE/WEND or a DO/LOOP loop, for instance:

Code: Select all

WHILE alldigit$ <> "Y" and alldigit$ <> "N"
   PRINT "Press Y or N"
   alldigit$="":WHILE alldigit$="":alldigit$=UCASE$(INKEY$):WEND
WEND 

Posted: Sun Jan 07, 2007 2:08 am
by bigbluehacker
Thanks for your help. You got me thinking in the right direction. By using a DO...LOOP and INPUT instead of INKEY$, I can make the routine echo the wrong key press, then clear the screen and reprint the original prompts.

Code: Select all

DO UNTIL alldigit$ = "y" or alldigit$ = "n"
     CLS: PRINT  "Do you want to use all digits?  "
     INPUT "Press y or n   ", alldigit$
LOOP
Thanks again. I'm sure I'll have more questions.

Posted: Sun Jan 07, 2007 6:39 am
by Ralph
However, your code requires one to Enter y or n. Merely pressing y or n does not make alldigit$ have anything, yet. For INPU, one must always do an Enter to get the data visible on the screen to the variable. And, the user may enter an uppercase letter, so you have to consider that. Also, with INPUT, the user may enter more than one letter, say no, or yes, and that will be wrong. With the INKEY$ used as I did, as soon as one presses any key, the program proceeds to see if it is either an n or N or y or Y, all of which are correct entries, and one cannot enter more than one key at a time. Think about these things.

Personally, I use INPUT only when I need the user to enter more than one keystroke; otherwise, I use INKEY$.

Posted: Mon Jan 08, 2007 2:24 am
by bigbluehacker
You are ABSOLUTELY CORRECT in every regard concerning input and inkey$. My code actually says "press y or n and enter". And it must be lower case and one character or the program will erase the screen and reprint the prompt. The original erased the screen and printed "ERROR" then printed the prompt. I haven't figured out how to put the error message in yet, but I'm continuing to work on it. I may change it to INKEY$ later but during the early writing it's easier for me to copy and paste segments that are the same and there are so many requirements to input numbers that I'm trying to be consistent at this point. My pea-size brain requires that.

Posted: Mon Jan 08, 2007 8:10 pm
by Ralph
As to the lower case requirement, try:

Code: Select all

alldigit$ = LCASE$(alldigit$)
IF an$ <> "y" AND alldigit$ <> "n" THEN
  PRINT " You entered "; alldigit$; " Please enter y or n"
END IF

Posted: Wed Jan 17, 2007 2:01 am
by bigbluehacker
Thanks for your help. It does the job perfectly and even allowed me to clear the screen, print the error message and reprint the prompts.

Before I get too deep in my rewrite, I have another question: Does EXIT SUB risk generating an out of stack space error message if it is called many times and almost never reaches the END SUB instruction?

For example, if a GOSUB routine is exited with a GOTO before it reaches a RETURN (control is transferred to a different place in the code other than the place that called the GOSUB) the stack is not reduced and the stack is increased again when the GOSUB is called again. Soon there is no stack space left for additional calls. I eliminated the problem in my original program by changing all GOSUBs to GOTOs and all RETURNs to GOTOs, thus creating no new stacks. (That was before I learned I could use RETURN to transfer control to a different place) That's why I have so many GOTOs that I'm trying to avoid in the rewrite. Does EXIT SUB have the same or similar problem?

Posted: Wed Jan 17, 2007 2:17 am
by Ralph
Hopefully, someone more knowledgeable than I will answer that question. But, if not, you can use a simple stratagy, as follows:

Code: Select all

GOSUB Calculate
...
...
...
Calculate:
bla, bla, bla
'I want to quit the subroutine here, so:
IF I$ = "Y" THEN GOTO CalculateEnd 'instead of IF I$ = "Y" THEN GOTO XY
bla, bla, bla
...
CalculateEnd:
RETURN 'this is the end of the subroutine Calculate
The above ASSURES that you exit the subroutine with the RETURN.

Posted: Fri Jan 19, 2007 9:02 am
by Dr_Davenstein
No. EXIT SUB will not generate a stack overflow error. In many cases, it can even stop you from runing into that problem. I wouldn't suggest trying to go heavy on recursion with QB though. It runs out of stack space very quickly, for the standards of today.

Posted: Fri Jan 19, 2007 4:31 pm
by Ralph
Dr_:

Could you expand some on your "I wouldn't suggest trying to go heavy on recursion with QB though." Would you please post a simple case of the recursion you mentioned? I ask this, so as to avoid the problem, myself.

And, while you're at it, I would be very happy if you would explain to me just how to get rid of a repeating key, after holding it down. Yes, I am talking about how to clear the keyboard buffer, so that, as soon as I lift my finger from the key, the buffer is clear, and, in the case of a moving sprite, it immediately stops. (I've had this explained to me once, but... :oops: ...I've forgotten how.

Posted: Sat Jan 20, 2007 12:01 am
by Dr_Davenstein
Sure. ;)

This is an example of what I mean by heavy recursion. See how the floodfill sub calls itself? It overloads the stack very, very fast. Try increasing the radius of the circle. It should run in QB, but I can't be positive. I wrote the code using FB with the -lang QB switch. Please tell me if it does. :)

Code: Select all

DEFINT A-Z
CONST False=0, True = NOT False, ScreenWidth= 640, ScreenHeight = 480

Declare Sub FloodFill(BYVAL X, BYVAL Y, BYVAL Col)

Screen 12


Circle(320,240),10,4
Print Fre(-1)
FloodFill 320,240,14
Print Fre(-1)
Sleep


SUB FloodFill(BYVAL X, BYVAL Y, BYVAL Col)
    If Point(X,Y)>0 Then Exit Sub
    Pset(X,Y),Col
    FloodFill X+1,Y,Col
    FloodFill X,Y+1,Col
    FloodFill X-1,Y,Col
    FloodFill X,Y-1,Col
End Sub

About your other question, I can't remember. Sorry. It's been a couple of years since I've actually used QB itself. I do remember that I used ONKEY before though. There are also some interrupt tricks, but I haven't messed wth DOS interrupts for that same span of time. However, if you look in Ralph Brown's interrupt list, you should be able to find a little snippet, or at the least the right interrupt to poke and clear the keyboard buffer. ;)

Posted: Sat Jan 20, 2007 5:30 am
by Ralph
Dr_:
Ran your code in QuickBASIC 4.5, Got an error message,
"Expected: variable or BYVAL or SEG or )"
and the first BYVAL on the line
SUB FloodFilll (BYVAL X. BYVAL Y, BYVAL Col)
is highlighted.

As to clearing the keyboard buffer, I somehow got rid of my problem, but, I'm not sure how, so, I haven't really solved it for the next time! :(

Posted: Sat Jan 20, 2007 5:33 am
by Dr_Davenstein
Oops! Just remove the Byval keywords. I forgot that QB doesn't support Byval/Byref. Sorry about that. :oops:

I'm glad you solved your other problem, but I wish you had an explanation! Maybe you had too many applications running before or something? :lol:

Posted: Sat Jan 20, 2007 6:55 am
by Ralph
Dr_:
The program ran fine (I added a SLEEP in the SUB). I saw the red circle being filled with a curve, starting from the cente, going one radius to the right, going 1/4 circle along the bottom, then reversing, then down again, then it started up on the left side, was coming down, and..."Out of string space". But, the fre just showed one value, at the top, as 352872. Seems to me that memory isn't the problem...

I next ended up with inserting two new lines in the SUB, just before the last FloodFill X, Y - 1, Col
The lines I added are
PRINT FRE(-1)
SLEEP

That let me see the filling-in of the circle, and got 8 free memory reports from the first of the two, new lines, with the free memory remaining as 352840 each time. No additional use of memory. Then, "Out of stack space." After all, the pre-reserved memory for the stacks are not part of the free memory, so, that doesn't change.

But, I see your point, as to running out of stack space with this system of recursive calling. I would never have thought of it, myself!

Posted: Sat Jan 20, 2007 7:05 am
by Dr_Davenstein
Hmmm... interesting. That could mean one of two things. Either FB is returning the stack space along on top of the ram when you call Fre(-1), or it's a bug. I'll have to ask around about this. Thanks, Ralph! :D