B4R Question For-Next error after 16 cycle in JoinStrings

petr4ppc

Well-Known Member
Licensed User
Longtime User
Dear friend please for advice:

I have code:
B4X:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
For i = 0 To buffer.Length-1
Dim cbtx(1) As Byte
byteconvert.ArrayCopy2(buffer,i,cbtx,0,1)
receivebyte = byteconvert.StringFromBytes(cbtx)
allbytesasstringarehere= JoinStrings(Array As String(allbytesasstringarehere, receivebyte)) 
next

But I get this error after i=16 ("z") in word "xyz"


Please what can I do?
Everytime only 16 cycles of FOR-NEXT is processed and then I get this error.
Thank you
p4ppc
 

petr4ppc

Well-Known Member
Licensed User
Longtime User
i am working on int and I found, that if I
set
B4X:
#StackBufferSize: 2600
was
B4X:
#StackBufferSize: 600

then I can work with more longer string.

How I must set STACKBUFFERSIZE if I want work with array of 360 letter in the string? Please?
Thank you
p4ppc
 
Upvote 0

emexes

Expert
Licensed User
Spewin! I got most of the way through a reply whilst waiting at airport to collect son, but apparently got distracted and never clicked Post Reply button.

 
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
Emexes,

thank you very much for your answer and advice. I have tried to put FOR NEXT to new SUB routine,
but the stackbuffer have the same value.

Thanks for tip
B4X:
Log("stackbuffer:",StackBufferUsage)
It is very useful.

I understand it right that the solution how to secure function "join string" via FOR NEXT is with new sub routine? Because of memory?
I have realy the same Stackvalue in both variant.
Best regards
p4ppc
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
What are you actually trying to achieve with this code:
B4X:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
For i = 0 To buffer.Length-1
    Dim cbtx(1) As Byte
    byteconvert.ArrayCopy2(buffer,i,cbtx,0,1)    'get next byte from input
    receivebyte = byteconvert.StringFromBytes(cbtx)    'convert byte/character to string
    allbytesasstringarehere= JoinStrings(Array As String(allbytesasstringarehere, receivebyte))    'add to output string
next
It looks like you are chopping up the input string into individual characters that are then being joined back into a single output string.

Usually this would just be done by a single string/array copy that does the whole string all at once.

Is this purely to demonstrate the error?

There are far more efficient ways to process a string character-by-character, usually involving Dimming the output buffer to the final size, rather than having a whole heap of differently-sized intermediate strings.

So, just in case the original question was missed: what string operation(s) are you actually needing to do?
 
Upvote 0

emexes

Expert
Licensed User
what string operation(s) are you actually needing to do?
as in, why not use ByteConverter .StringFromBytes to do the whole string at once?
B4X:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
Dim allbytesasstringarehere As String = byteconvert.StringFromBytes(buffer)
 
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
EMEXES - EREL

Thank you very much for yours answer

- I am receiving standard serial data from AVR
- this bytes are reading in ESP - each byte
- Each byte is then compared with values in EEPROM and then I put the right values to the string

But as I wrote - I recognized that if the string is too long, ESP is restarted. It depend on #StackBufferSize...

I will try what Erel wrote:
You need to keep the For loop in the original sub and move the inner code to a different sub. This will allow the stack memory to be released after each iteration.

And thank you for your tip Emexes:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
Dim allbytesasstringarehere As String = byteconvert.StringFromBytes(buffer)

Best regards
p4ppc
 
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
Excuse me,

- If I have the string with right data I am sending them :

1) via serial back to AVR (this is most important)
and
2) I am working now on B4J app for second possibility = sending data via UDP. ESP to B4J

Best regards
p4ppc
 
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
Thank you very much for your advice, I will try this solution.
Best regards
p4ppc
 
Upvote 0

emexes

Expert
Licensed User
I will try this solution.
Super!

Part of me says: you're on the right track, I should leave you in peace.

Another part says: what was all that byte-string-shuffling about? makes me worry that whatever you are doing, you might be doing it the hard way.

You haven't told us what you are doing with this string so it is impossible to say more.
+1
 
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
Dear friends,

I am trying:
B4X:
Private Sub AppStart
    Serial1.Initialize(115200)
    Log(" ") : Log("AppStart")
    Queue.AddBytes("h")
    Queue.AddBytes("a")
    Queue.AddBytes("l")
    Queue.AddBytes("l")
    Queue.AddBytes("o")
    Queue.RemoveFirst
    Queue.AddBytes("h")
    Queue.AddBytes("o")
    Queue.AddBytes("w")
    Queue.AddBytes("a")
    Queue.AddBytes("r")
    Queue.AddBytes("e")
    Queue.AddBytes("y")
    Queue.AddBytes("o")
    Queue.AddBytes("u")  
   
    Dim str() As Byte = "Something #"
    For i = 1 To 10
        Queue.AddBytes(str)
        Queue.AddBytesToLastItem(NumberFormat(i, 0, 0))
    Next  
   
    Log("Size before dequeue: ", Queue.Size, " items")
    Do While Queue.Size > 0
        Log("1-",Queue.FirstItem)
        Queue.RemoveFirst
    Loop
   
    Log("Size after dequeue: ", Queue.Size, " items")
    Log("StackBufferUsage: ", StackBufferUsage)
End Sub

It looks perfect. What I need, because the StackBufferUsage is:312

Please how can I get with queue the string "hallo how are you" without JoinString function? I will send string via classic serial.

EMEXES - Thank you for your help and question, I am learning how to work with string and bytes and B4R. It something different, its very nic, but I am learning.

Thank you very much
Best regards
p4ppc
 
Upvote 0

miker2069

Active Member
Licensed User
Longtime User

Could you perhaps start with a predefine buffer of some size like buffer(32) as byte and just set each character at the appropriate index as necessary? You can then send the buffer and if you have more than 32 bytes of data to send you reset the buffer and fill it again, and send, and so on...
 
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
Miker,

please. If I will have for example buffer(5) as byte, then how I send string "hallo" via serial? I must then join eachbyte and it does it mean that I am returning back to problematic with memory...it is true? i need then send string "hallo" via serial...

I am trying your words, but I have mistake, I see nothing, please can you check my declaration?:

B4X:
Dim tmp(5) As Byte
Dim xbyte As Byte
xbyte=0

    Do While Queue.Size > 0
        xbyte=xbyte+1
        Log("X-",Queue.FirstItem)
        tmp(xbyte)=Queue.FirstItem     
        Queue.RemoveFirst   
    Loop

Log("tmp:",tmp) ' here is my string
 
Last edited:
Upvote 0

petr4ppc

Well-Known Member
Licensed User
Longtime User
Miker,

most often have string length <= 20
but sometimes the string can have length <=200
 
Upvote 0

emexes

Expert
Licensed User
[/QUOTE]
If you always use .AddBytesToLast then effectively the Queue will act like StringBuilder, adding bytes to a single Queue item, which you can access at any time using Queue.FirstItem(), or more likely something like:
B4X:
Queue.AddBytesToLast("H")
Queue.AddBytesToLast("a")
Queue.AddBytesToLast("l")
Queue.AddBytesToLast("l")
Queue.AddBytesToLast("o")
Queue.AddBytesToLast("!")

Dim bc As ByteConverter
Dim JoinedString As String = bc.StringFromBytes(Queue.FirstItem())    'might not need the ()
which sounds like what you want... except for:
B4X:
Queue.RemoveFirst
which will have the effect of removing the first item in the Queue, which is probably the (entire) string that you have been building up.

Why the .RemoveFirst???

The roll-your-own approach of Miker2069 is a quite reasonable solution too. You can write it to do just whatever you need it to do - no more, and no less. Cf the Queue module, which is more functional than you require because it written to cope with a wider variety of situations, and I think that this generality is causing confusion, eg concept of Queue being items, not bytes.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…