Jump to content
IGNORED

Getting substrings in IntyBASIC - is there a way to do this?"


Recommended Posts

Hey all,

 

Is there a (preferably clean) way to get a substring out of a string in IntyBASIC? I don't know if it's just a notation thing or what, but if it's in the manual I'm missing it.

 

I'm hoping to implement a thin font implementation sort of similar to what GroovyBee posted a while back and it would be convenient for me to pass an entire string to a printing routine and pick it apart two letters at a time.

 

Thanks a bunch!

Link to comment
Share on other sites

Is there a (preferably clean) way to get a substring out of a string in IntyBASIC? I don't know if it's just a notation thing or what, but if it's in the manual I'm missing it.

 

 

Depends on what you mean. There's no clean way to get a substring out of a string, at least in the sense of getting a substring out of PRINT AT 0, "THIS IS MY STRING".

 

However - you can cheat by encoding your strings as DATA statements. Put a label on them, and then you can address into the DATA statement however you like. For example:

label1:  
DATA "THIS IS MY STRING"
label2:
DATA "AND THIS IS ANOTHER"

Then you can address label1 or label 2 like an array: label1(5) points to the i in IS, for example. label2(12) points to the a in ANOTHER. Etc.

 

 

If you REALLY want to get clever, you can encode 2 letters in a single 16-bit word, and pick them apart 2 letters at a time that way. This saves ROM space (not usually a concern for most games) but can get complicated if you need to address an odd-numbered character.

Link to comment
Share on other sites

 

Depends on what you mean. There's no clean way to get a substring out of a string, at least in the sense of getting a substring out of PRINT AT 0, "THIS IS MY STRING".

 

However - you can cheat by encoding your strings as DATA statements. Put a label on them, and then you can address into the DATA statement however you like. For example:

label1:  
DATA "THIS IS MY STRING"
label2:
DATA "AND THIS IS ANOTHER"

Then you can address label1 or label 2 like an array: label1(5) points to the i in IS, for example. label2(12) points to the a in ANOTHER. Etc.

 

 

If you REALLY want to get clever, you can encode 2 letters in a single 16-bit word, and pick them apart 2 letters at a time that way. This saves ROM space (not usually a concern for most games) but can get complicated if you need to address an odd-numbered character.

 

Okay! As I suspected. Thank you so much.

Link to comment
Share on other sites

On a related note, I noticed there is a LEN function to get the length of strings, but when I tried to use it a while ago, I didn't even get the program through the compiler. I didn't find any example of a program using that function, but perhaps I missed something obvious. So if anyone has a working example of when LEN can be used, I'd be grateful (although I solved my problem in a different way).

Link to comment
Share on other sites

On a related note, I noticed there is a LEN function to get the length of strings, but when I tried to use it a while ago, I didn't even get the program through the compiler. I didn't find any example of a program using that function, but perhaps I missed something obvious. So if anyone has a working example of when LEN can be used, I'd be grateful (although I solved my problem in a different way).

 

Wow, I have literally never noticed this. I don't use DEF FN very much, and I'm not even sure I see the connection. Anyways, this works:

 

PRINT AT 0, <3>len("TEST")

 

It prints 004 which is what you'd expect. I find the use a bit dubious though. Strings like this are hard-coded into the program, so I'd never waste cycles on calculating length.

 

I find myself going full C-style with variable string data - encoding them in arrays, and then writing a quick cheater function to check their length. null-terminated and everything. I've used it to center names on the screen etc, but for longer strings this concept can have trouble scaling.

Link to comment
Share on other sites

 

Wow, I have literally never noticed this. I don't use DEF FN very much, and I'm not even sure I see the connection. Anyways, this works:

 

PRINT AT 0, <3>len("TEST")

 

It prints 004 which is what you'd expect. I find the use a bit dubious though. Strings like this are hard-coded into the program, so I'd never waste cycles on calculating length.

 

I find myself going full C-style with variable string data - encoding them in arrays, and then writing a quick cheater function to check their length. null-terminated and everything. I've used it to center names on the screen etc, but for longer strings this concept can have trouble scaling.

 

It's for macro usage, DZ-Jay was playing with auto-centering strings.

Link to comment
Share on other sites

IIRC, I tried using it with DATA statements and sending the label as the argument, but the compiler wouldn't let it. Now, if it only (?!) works with inline strings, it seems cumbersome if you possibly need the same literal string twice: first to calculate how long it is, then to actually display it. But if that is the intended use, I won't question it any more, just so I know what it can be used for.

Link to comment
Share on other sites

Strings like this are hard-coded into the program, so I'd never waste cycles on calculating length.

Thats not correct. The string length is evaluated at compile time and not run time. IntyBASIC uses the string length directly and discards the string's contents.

 

Currently, the biggest problem with IntyBASIC strings is that the string delimiter has not yet been defined. As soon as a method for that becomes standard, then more advanced string manipulation functions can be implemented.

Link to comment
Share on other sites

IIRC, I tried using it with DATA statements and sending the label as the argument, but the compiler wouldn't let it. Now, if it only (?!) works with inline strings, it seems cumbersome if you possibly need the same literal string twice: first to calculate how long it is, then to actually display it. But if that is the intended use, I won't question it any more, just so I know what it can be used for.

 

If you need a fast string length function that works with data statements I can put one together in assembler.

Link to comment
Share on other sites

 

Wow, I have literally never noticed this. I don't use DEF FN very much, and I'm not even sure I see the connection. Anyways, this works:

 

PRINT AT 0, <3>len("TEST")

 

It prints 004 which is what you'd expect. I find the use a bit dubious though. Strings like this are hard-coded into the program, so I'd never waste cycles on calculating length.

 

I find myself going full C-style with variable string data - encoding them in arrays, and then writing a quick cheater function to check their length. null-terminated and everything. I've used it to center names on the screen etc, but for longer strings this concept can have trouble scaling.

 

 

 

It's for macro usage, DZ-Jay was playing with auto-centering strings.

 

I came in to answer this, but you covered it pretty well. :)

 

I wanted to center strings for the default SDK title screen, using macros. It is very convenient to be able to get the length of a literal string for many things during pre-processing.

 

Someday, I'll release SDK v2 (including Mac edition), and it will all make sense. :)

 

-dZ.

Link to comment
Share on other sites

Thats not correct. The string length is evaluated at compile time and not run time. IntyBASIC uses the string length directly and discards the string's contents.

 

Currently, the biggest problem with IntyBASIC strings is that the string delimiter has not yet been defined. As soon as a method for that becomes standard, then more advanced string manipulation functions can be implemented.

 

That's easy:

 

I vote for Pascal-style strings (with length prefix). :thumbsup: It was good enough for Dr. Wirth, it's good enough for IntyBASIC. ;)

 

Hmm... Then again... C-style strings (with null-char delimiter) is very useful and common, and used even in old Macro Assemblers. :thumbsup: C keeps the gears of the world turning, so it should be good even for IntyBASIC.

 

Oh, dammit! I don't know. :lol:

Edited by DZ-Jay
  • Like 1
Link to comment
Share on other sites

Hmm... Then again... C-style strings (with null-char delimiter) is very useful and common, and used even in old Macro Assemblers. :thumbsup: C keeps the gears of the world turning, so it should be good even for IntyBASIC.

You can't use a C style delimiter in IntyBASIC because the compiler converts the strings at compile time (it subtracts 32 from each ASCII code for you). That makes space (ASCII 32) the NUL terminator :(.

 

Edit: For a small resource language like IntyBASIC, the Pascal way makes much more sense to me.

Edited by GroovyBee
Link to comment
Share on other sites

Edit: For a small resource language like IntyBASIC, the Pascal way makes much more sense to me.

 

Agreed. I don't see strings going over the 255 limit, especially since there isn't even enough screen space for a string that long! Besides, strings can then be mutable, concatenated in-place, byte-addressable, indexed, and support all those other neat features that Pascal had -- and most of it comes for free.

 

-dZ.

Edited by DZ-Jay
Link to comment
Share on other sites

Hm, can one define string constants and use those within the program? Then it would just be a matter of changing the content at one location in case you want to update the string.

 

For my own use, I use DATA statements with strings and then the magic (I hope!!) numbers -1 for line break and -2 for end of string, or if it was the other way around. Then I print the strings one character at a time until I hit a magic number, which in this case would be an extended string delimiter. If you're going to use a length prefix, doesn't it make the LEN function rather pointless, or would it just be syntactic sugar to extract the prefix from the string structure? The latter would make it very fast indeed, but the programmer needs to keep the string length updated? I'll admit it was 22+ years ago since I touched any form of Pascal so I might not remember exactly how it was done.

Link to comment
Share on other sites

Thats not correct. The string length is evaluated at compile time and not run time. IntyBASIC uses the string length directly and discards the string's contents.

 

Perhaps this is semantics, but how is that not correct?

 

PRINT AT 0,"TEST STRING" - this length is already determined by the time you compile your code. It cannot change. It might as well be hard-coded into your program, and therefore calculating it serves no purpose. Just set the length yourself as a CONST.

 

Link to comment
Share on other sites

You can't use a C style delimiter in IntyBASIC because the compiler converts the strings at compile time (it subtracts 32 from each ASCII code for you). That makes space (ASCII 32) the NUL terminator :(.

 

 

Which is why I do it the ugly way - count backwards from the end until you find the first non-space character, and that's your length. Everything else is essentially null-terminated (perhaps with several nulls).

 

It precludes using strings that you intentionally WANT to have spaces at the end, but that's not a common concern for me.

 

It's ugly, and hacky, but it covers off the vast majority of string use cases.

Link to comment
Share on other sites

PRINT AT 0,"TEST STRING" - this length is already determined by the time you compile your code. It cannot change. It might as well be hard-coded into your program, and therefore calculating it serves no purpose. Just set the length yourself as a CONST.

Thats not what you said before :P. Yep! The string length is computed for you and used at compile time. The reason not to use a constant is that if you make changes to the text you need to manually update the constants (which is a PITA). You might as well avoid that extra work and let intyBASIC do it for you.

Link to comment
Share on other sites

 

Perhaps this is semantics, but how is that not correct?

 

PRINT AT 0,"TEST STRING" - this length is already determined by the time you compile your code. It cannot change. It might as well be hard-coded into your program, and therefore calculating it serves no purpose. Just set the length yourself as a CONST.

 

 

The length is computed at compile time by IntyBASIC, but what if you need that value yourself? In my case, I wanted to align text horizontally on the screen. Specifically, I was looking to center the text on a line. I wanted to do this multiple times, and wanted to provide a handy macro for it, so that users could customize the default SDK title screen to say whatever they wanted.

 

It turned out that, since strings are not supported as a data type in IntyBASIC, there was no easy way to know the length of a string. Sure, I could count the characters myself and store them in another constant -- and as a matter of fact, that's what I had to do before the LEN() function was implemented -- but then so will everyone else who makes a change for their own title screen.

 

In fact, since I wanted to create a custom title screen based on the project name argument provided to the "INTYNEW" script of the SDK, I had to come up with a convoluted Batch script routine to count the characters in a script argument!

 

Talk about ugly:

 

 

@ECHO OFF
REM * =========================================================== *
REM * This script is placed into the public domain by its author. *
REM * All copyrights are hereby relinquished on the routines and  *
REM * data in this file.   -- James Pujals (DZ-Jay), 2015         *
REM * =========================================================== *

REM StrLen() Function Script (_strlen.bat)
REM   Created by:   DZ-Jay
REM   Last updated: 07/23/2015

REM ========================================
REM Initialize Local Variables
REM ========================================
SET _INSTR=%~n1

	CALL :STRLEN %~n2% _INSTR
	IF ERRORLEVEL 1 GOTO ERROR
	GOTO END

:STRLEN <OUTSTR> <INSTR>
(
    SETLOCAL EnableDelayedExpansion
    SET "S=!%~2!#"
    SET "LEN=0"
    FOR %%P IN (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
        IF "!S:~%%P,1!" NEQ "" (
            SET /A "LEN+=%%P"
            SET "S=!S:~%%P!"
        )
    )
)
(
    ENDLOCAL
    SET "%~1=%LEN%"
    EXIT /B
)

:ERROR
	SET _INSTR=
	ECHO An error occurred getting the length of the string.
	EXIT /B 1

:END
	REM Clean Up
	SET _INSTR=
 

 

 

 

All that, just to be able to inject a constant assignment into the output stream of the new project *.BAS file.

 

It's silly, since that's precisely what computers, compilers, and pre-processors are for. So, I asked Oscar for the function available to a macro and he implemented it.

 

Now, I can just call LEN() from the within the IntyBASIC macro, using the string as an argument, and bob's your uncle. :)

 

Easy, peacy.

Link to comment
Share on other sites

So I suppose neither of these two cases can be made to work with this LEN function right now?

 

 

CONST MYSTRING = "HELLO WORLD"
PRINT <>LEN(MYSTRING)

 

 

PRINT <>LEN(stringdata)
 
stringdata:
  DATA "HELLO WORLD"

 

I kind of understand the current use case, but it confused me a bit that strings appear to need to be inlined and duplicated for each occurrence.

Link to comment
Share on other sites

So I suppose neither of these two cases can be made to work with this LEN function right now?

Correct! When the IntyBASIC string length/terminator is defined the len command could be made to work with inline strings then.

 

I kind of understand the current use case, but it confused me a bit that strings appear to need to be inlined and duplicated for each occurrence.

They are duplicated in the source code, but only one is present in the binary.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...