Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
string slicing using len()
#1
I didn't understand why a piece of my program didn't work as expected. I suspected something was wrong with the for-next loop. I tried some tests, simplified versions of the problem, and finally find out the following:

Code:
dim text as string dim i as ubyte let text="hello world!" cls print "Fine:" for i = 0 to len(text)-1 print i,text(to i) next i pause 0 cls print "All texts are complete!:" for i = 0 to len(text)-1 print i,; let text = text(to len(text)-1) print text next i stop
It was a surprise. The second loop prints the same original text every time.

I tried the equivalent code in Sinclair Basic, and of course it worked as expected:
Code:
10 LET A$="hello world!" 20 FOR I=0 TO LEN(A$)-1 30 PRINT I,; 40 LET A$=A$(TO LEN(A$)-1) 50 PRINT A$ 60 NEXT I 70 STOP

Then I tried it without the loop:

Code:
dim text as string let text="hello world!" cls print text let text = text(to len(text)-1) print text let text = text(to len(text)-1) print text let text = text(to len(text)-1) print text let text = text(to len(text)-1) print text let text = text(to len(text)-1) print text let text = text(to len(text)-1) print text let text = text(to len(text)-1) print text stop
And the problem remained.
Then I hardcoded some slicing values:
Code:
dim text as string let text="hello world!" print text let text = text(to 10) print text let text = text(to 9) print text let text = text(to 8) print text let text = text(to 7) print text let text = text(to 6) print text let text = text(to 5) print text stop
And it worked fine.

Is there something I'm missing in my code or is it a compiler issue?
Reply
#2
It happens string slicing starts from 0 (not from 1). So it ranges from 0 to LEN(a$)-1.
If you want your program work OK, you should do:
Code:
let a$="hello world" let l=len(a$)-1 for i = 1 to l: let a$=a$(to len(a$) - 2) print i, a$ next i

Notice also that FOR upper limit is evaluated ON EACH iteration (like C). So if len(a$) changes, the loop will shorten. So better use a temporary var l to store initial LEN(a$).

Arrays subscripts starts from 0 to N-1 (like in C). But this behavior can be changed using --sinclair or --array-base switch.

NOTE: I'm planning (for compatibility) an --string-base (so LEN and string-slicing will work exactly as in Sinclair BASIC, by specifying --string-base=1). Also with FOR, stating --constant-for etc...
Reply
#3
boriel Wrote:Notice also that FOR upper limit is evaluated ON EACH iteration (like C). So if len(a$) changes, the loop will shorten. So better use a temporary var l to store initial LEN(a$).

I learned it while debugging. It's an important difference with Sincllar Basic.

boriel Wrote:Arrays subscripts starts from 0 to N-1 (like in C). But this behavior can be changed using --sinclair or --array-base switch.

I forgot it! Thanks. One of my tests used "-2" intead of "-1" because of that. Anyway, the problem arises when trying to remove the last char of the string. Then "-2" cannot be used. I tried the following expression:

Code:
let text=text( to len(text)-2+(len(text)=1))

It doesn't work because

Code:
(len(text)=1)

doesn't return "1" when true, as I expected (Sinclair Basic does).

I opened a new thread about this different issue.
Reply
#4
A new compiler version (r1564) has been uploaded. It allows you to use --string-base parameter to tell the compiler which is the 1st base-index position in strings:
Code:
./zxb.py --string-base=1 ...
The same applies for array (--array-base). So if you want arrays to start at index 1, use --array-base=1.
Also using --sinclair enables all this compatibilities with a single parameter.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)