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)