petit chou Posted April 25, 2016 Share Posted April 25, 2016 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! Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 26, 2016 Share Posted April 26, 2016 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. Quote Link to comment Share on other sites More sharing options...
petit chou Posted April 26, 2016 Author Share Posted April 26, 2016 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. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted April 26, 2016 Share Posted April 26, 2016 Okay! As I suspected. Thank you so much. Yeah, if you were looking for RIGHT$, LEFT$, and MID$ functions, they are not implemented yet. -dZ. Quote Link to comment Share on other sites More sharing options...
carlsson Posted April 26, 2016 Share Posted April 26, 2016 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). Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
+nanochess Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
carlsson Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted April 27, 2016 Share Posted April 27, 2016 (edited) 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). 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. C keeps the gears of the world turning, so it should be good even for IntyBASIC. Oh, dammit! I don't know. Edited April 27, 2016 by DZ-Jay 1 Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted April 27, 2016 Share Posted April 27, 2016 (edited) Hmm... Then again... C-style strings (with null-char delimiter) is very useful and common, and used even in old Macro Assemblers. 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 April 27, 2016 by GroovyBee Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted April 27, 2016 Share Posted April 27, 2016 (edited) 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 April 27, 2016 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
carlsson Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted April 27, 2016 Share Posted April 27, 2016 As with Pascal you wouldn't need to update the string length yourself because the library functions would keep track of it for you. Currently, the len command is only useful when using def fn. Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted April 27, 2016 Share Posted April 27, 2016 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 . 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. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted April 27, 2016 Share Posted April 27, 2016 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. Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 27, 2016 Share Posted April 27, 2016 Now, I can just call LEN() from the within the IntyBASIC macro, using the string as an argument, and bob's your uncle. Interesting edge case. So do you basically end up with the string twice in the code? ie: PRINT AT 20,"STRING GOES HERE" length = len("STRING GOES HERE") 1 Quote Link to comment Share on other sites More sharing options...
carlsson Posted April 28, 2016 Share Posted April 28, 2016 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted April 28, 2016 Share Posted April 28, 2016 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. 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted April 28, 2016 Share Posted April 28, 2016 Maybe there is no "BASIC" analogy, but think of LEN() as a pre-processor directive or a macro. -dZ. Quote Link to comment Share on other sites More sharing options...
First Spear Posted April 29, 2016 Share Posted April 29, 2016 This is the best programming community and forum, ever. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.