Pages: 1 [2] 3   Go Down
Author Topic: Having trouble "inserting" new characters to a String object.  (Read 11839 times)
0 Members and 1 Guest are viewing this topic.
Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm loath to say but if you have RAM to waste then maybe stick with Strings but I dunno if you have that.

I never liked Strings. They are not transparent while char arrays and string.h functions are totally transparent to me.
Strings copy themselves and delete the old copy. Oh, is that your heap? Stomp, stomp, stomp. Hope you gots lots!

With a char array I am dealing with an ARRAY.
If I need to insert a string within a string I first check if I have room in the array and if so, I memmove() the end to make space in the middle then strncpy() the inserted section since strncpy() does not put a terminating zero at the end of the copied section. And that's it.
But I can do the same without using ANY string.h functions. I simply copy the end of the array string back to where I want to insert the new section with a for-loop the use another for-loop to set the bytes I want inserted into place. I treat the array as an array and I don't need no stinking functions I don't know about!

All a char array C string is is a sequence of ASCII chars with a terminating zero (NULL) at the end in a char array.
That is the big hard secret of c strings. Nothing else. You allocate buffers up front and they stay put.
If you want to learn something hard that is well worth the lesson, learn about pointers and referencing until you see it's just how the compiler deals with addresses and realize that storage is all about data and addresses.

I do confess to having a head start before I ever got to C. I semi-learned 3 different assemblers and Forth and the simplicity of view never left.
I can give you hand breaking into string.h commands if you want. PM me. There's really a few basics with variations you can tell by the name, like string copy strcpy() vs strncpy(). The memxxx() functions alone are worth the trip.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50154
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Any suggestions before I'm lost between stars and ampersands ???
A string is a NULL terminated ARRAY of chars. No pointers needed. No need to pass be reference.

There is a VERY close relationship between pointers and arrays, so if passing an array using a pointer makes more sense, or is what the called function expects, just pretend that the pointer and the array are the same thing.

The only real difference between a pointer and an array is that an array always has space allocated. A pointer may or may not point to allocated space.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


I'm wondering though...
Since adding this byte type variable to a string object did not work, why would adding it to a char array work?
Should I be looking at some sort of conversion needed, other than a simple casting?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50154
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Since adding this byte type variable to a string object did not work, why would adding it to a char array work?
You haven't proven that it didn't. Anonymous output is not convincing.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Since adding this byte type variable to a string object did not work, why would adding it to a char array work?
You haven't proven that it didn't. Anonymous output is not convincing.

Well, I kinda proved it myself smiley but if you insist, will bring the exhibits to the court in the afternoon (my time... BTW, you sir must be an early riser...)
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50154
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but if you insist, will bring the exhibits to the court in the afternoon
Please do. Chars CAN be added to Strings (as long as the allocation succeeds).
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If the allocation doesn't succeed on an Arduino then expect a reset very soon?
It's not like you have an OS to try exceptions with.

The String should be able to insert chars after copying itself bigger to hold them.

The difference to using a char array is that the array has a fixed size and does not copy itself "for you".
That's what I mean by transparent and clean.

UNO has 2K RAM for heap and stack.
Using Strings on an UNO is like running a Monster Truck in a half acre lot. Sure, you can even turn completely around but wow, what a show eh?
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I have modified the code a bit, so here is the serial output:

Code:
Entering decode function
Reserving for dMessage: 24
Received pdu: D4F29C0E6AA3DDF976181486BF416928FAED2EBB00
of size: 42
Constructed and now parsing encoded byteith hex value: 0
Finished decoding char, created byte with DEC value: 0
Constructed and now parsing encoded byteith hex value: BB
Finished decoding char, created byte with DEC value: 46
Inserting it at dMessage, possition: 22
Constructed and now parsing encoded byteith hex value: 2E
Finished decoding char, created byte with DEC value: 101
Inserting it at dMessage, possition: 21
Constructed and now parsing encoded byteith hex value: ED
Finished decoding char, created byte with DEC value: 110
Inserting it at dMessage, possition: 20
Constructed and now parsing encoded byteith hex value: FA
Finished decoding char, created byte with DEC value: 111
Inserting it at dMessage, possition: 19
Constructed and now parsing encoded byteith hex value: 28
Finished decoding char, created byte with DEC value: 104
Inserting it at dMessage, possition: 18
Constructed and now parsing encoded byteith hex value: 69
Finished decoding char, created byte with DEC value: 80
Inserting it at dMessage, possition: 17
Finished decoding char, created byte with DEC value: 105
Inserting it at dMessage, possition: 16
Constructed and now parsing encoded byteith hex value: 41
Finished decoding char, created byte with DEC value: 32
Inserting it at dMessage, possition: 15
Constructed and now parsing encoded byteith hex value: BF
Finished decoding char, created byte with DEC value: 111
Inserting it at dMessage, possition: 14
Constructed and now parsing encoded byteith hex value: 86
Finished decoding char, created byte with DEC value: 112
Inserting it at dMessage, possition: 13
Constructed and now parsing encoded byteith hex value: 14
Finished decoding char, created byte with DEC value: 97
Inserting it at dMessage, possition: 12
Constructed and now parsing encoded byteith hex value: 18
Finished decoding char, created byte with DEC value: 32
Inserting it at dMessage, possition: 11
Constructed and now parsing encoded byteith hex value: 76
Finished decoding char, created byte with DEC value: 97
Inserting it at dMessage, possition: 10
Constructed and now parsing encoded byteith hex value: F9
Finished decoding char, created byte with DEC value: 109
Inserting it at dMessage, possition: 9
Finished decoding char, created byte with DEC value: 121
Inserting it at dMessage, possition: 8
Constructed and now parsing encoded byteith hex value: DD
Finished decoding char, created byte with DEC value: 110
Inserting it at dMessage, possition: 7
Constructed and now parsing encoded byteith hex value: A3
Finished decoding char, created byte with DEC value: 104
Inserting it at dMessage, possition: 6
Constructed and now parsing encoded byteith hex value: 6A
Finished decoding char, created byte with DEC value: 109
Inserting it at dMessage, possition: 5
Constructed and now parsing encoded byteith hex value: E
Finished decoding char, created byte with DEC value: 32
Inserting it at dMessage, possition: 4
Constructed and now parsing encoded byteith hex value: 9C
Finished decoding char, created byte with DEC value: 116
Inserting it at dMessage, possition: 3
Constructed and now parsing encoded byteith hex value: F2
Finished decoding char, created byte with DEC value: 115
Inserting it at dMessage, possition: 2
Constructed and now parsing encoded byteith hex value: D4
Finished decoding char, created byte with DEC value: 101
Inserting it at dMessage, possition: 1
Finished decoding char, created byte with DEC value: 84
Inserting it at dMessage, possition: 0
Finished constructing dMessage!!
Char at possition 0: dMessage:

And here is the code section of interest:

Code:
String decodeMessage (String eMessage, int messageLenght) {    // Gets the PDU and the lenght, returns the decoded Message.
Serial.println();
Serial.println(F("Entering decode function"));

String dMessage;
Serial.print(F("Reserving for dMessage: "));
Serial.println(messageLenght+1);
dMessage.reserve(messageLenght+1);
//dMessage = "";// First try
//char tempoString [25]; // Another try
byte newByte = 0;
byte originalByte = 0;
int counter = 1;
int currentPosition = messageLenght;

// Convert the received string Hex representation to actual bytes starting from the last 2 hex chars of the string.
unsigned int ln, hn;
Serial.print(F("Received pdu: "));
Serial.println(eMessage);
Serial.print(F("of size: "));
Serial.println(eMessage.length());

for (int j = eMessage.length()-1; j >=0 ; j=j-2) {
if (eMessage.charAt(j) > '9') {
ln = eMessage.charAt(j) - 'A' + 10;
} else {
ln = eMessage.charAt(j) - '0';
}

if (eMessage.charAt(j-1) > '9') {
hn = eMessage.charAt(j-1) - 'A' + 10;
} else {
hn = eMessage.charAt(j-1) - '0';
}

originalByte = (hn << 4) | ln;
Serial.print(F("Constructed and now parsing encoded byteith hex value: "));
Serial.println(originalByte,HEX); //Got the original byte.

for (int i = 7; i>=0; i--) {  //Start the newByte construction. Add 7 bits of each original byte.
//newByte = newByte | (bitRead(originalByte, i) >> counter); //This did not work, never figured out why....

bitWrite(newByte, 7-counter, bitRead(originalByte, i));  
counter++;
if (counter == 8) {  // We have filled up the byte. Lets close it, add it to the string and start with a new newByte.
Serial.print(F("Finished decoding char, created byte with DEC value: "));
Serial.println(newByte, DEC);  // Seems all right. the Values I get for all the new bytes created is the message I'm expecting.

if (newByte>0) {
Serial.print(F("Inserting it at dMessage, possition: "));
Serial.println(currentPosition);
dMessage.setCharAt(currentPosition, newByte);
}  //First try

// dMessage += newByte; //another try
// strcat(tempoString, newByte);  //yet another try

delay(100);
currentPosition--; // Go one char back on the dMessage.
newByte = 0; counter = 1;
}
}
//}
}
// Serial.println(tempoString);
Serial.println(F("Finished constructing dMessage!!"));
Serial.print(F("Char at possition 0: "));
delay(100);
Serial.println(dMessage.charAt(0));
delay(200);
Serial.print(F("dMessage: "));
delay(200);
Serial.println(dMessage);
delay(100);
Serial.println("\r\n");

delay (300);
return dMessage;
}

If you don't like the delays just ignore them,  smiley-money  they do not change anything.

At the end of the function,  I'm trying to print the char at position 0 of the String. It behaves like it is deleting the line feed of the println statement. As you see on the output, the next message :dMessage: " gets  printed right beside, with no line feed.... The same is true for characters in every position of the String.

So I guess that proves that the String is not getting populated. I assume you can do setCharAt() at a String which is not really initiallized. As you see in the code, I'm declaring the string and reserving space for it with the reserve() method, but other than the setCharAt(), theres no other  initiallization happening to it... Could this be the issue... ????

And to extend my question. Since the String does not get populated, would this be the same for the char array?

Edit: And to address the memory issue, it does not seem that the arduino runs out of memory, at least not yet. It does not reset, it just keeps running the rest of the code, scanning all the rest SMS memory of the phone, finds the rest of the Messages and does the same procedure. I have another 2  messages on the SIM and all get read and decoded... I guess if I was running out of memory this would not happen.... But on the other side, I have yet to experience such a thing so as to know how it looks like smiley
 
« Last Edit: April 16, 2014, 11:34:28 am by nikosk » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Using Strings on an UNO is like running a Monster Truck in a half acre lot. Sure, you can even turn completely around but wow, what a show eh?


This ought to have been on TV!!!!!!!!  smiley-grin

Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Considering how many people come here for help with Strings, we have enough drama already.
But lately a few of the old heads have left so you don't get the consensus of experience we used to.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50154
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Serial.println(dMessage.charAt(0));
Add , HEX to the end of this, to see what value it really holds.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll be damned!!!!!

Just tried to add each char to a traditional char array and guess what... it works just fine....
Now on to refresh on how to send char arrays back and forth between functions...

BTW had a very very very brief look at the implementation of some of Strings method. My poor C and C++ knowledge is leading me to think that when declaring the String without initializing it, there is an internal integer named len which gets 0. This len does not get changed when you reserve space. And method setCharAt() does a simple check to see if the position you are writing to is within this very len of the string. If not it does nothing.... Which seems to be my case.

Edit: and just to confirm myself, I got the String to initialize using: String dMessage = "                 " (23 spaces) and now this works fine as well...
« Last Edit: April 16, 2014, 02:52:32 pm by nikosk » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Considering how many people come here for help with Strings, we have enough drama already.
But lately a few of the old heads have left so you don't get the consensus of experience we used to.


Well, I'm not regular here, but there are times that I do a lot of reading of this forum and I can say that there are thread from certain people that are just impossible to cope with... They are talking....machine code.... not English...

Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll be damned!!!!!

Just tried to add each char to a traditional char array and guess what... it works just fine....
Now on to refresh on how to send char arrays back and forth between functions...

When you declare an array, the name is a pointer (read: address) to the base of the array.

char buffer[ 40 ]; // buffer is now a char * (* means pointer) to element buffer[0].
                             // it can be used in any function where a char * arg is needed.

char *cptr; // this is a 'bare' pointer to type char

cptr = buffer; // cptr points to buffer[ 0 ]
cptr = &buffer[ 5 ]; // the & is the address-of operator. cptr now points to buffer[ 5 ]
cptr += 20; // cptr now points to buffer[ 25 ]

strcpy( buffer, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ); // filling up buffer

cptr = strchr( buffer, 'S' ); // cptr now points to the first letter S in buffer
byte idx = cptr - buffer; // idx = 18 and buffer[ 18 ] == 'S'

idx = *( cptr ); // now idx == 'S' == 65 + 18...... the * says give me the value at the address of the pointer

Pointers is like indexes only free from the names of arrays. This makes them extremely versatile and useful in functions that work on arrays, char arrays or any other kind of array. The function doesn't need to know what array it is working with and it can return a pointer without regard to array indexes.

Here is more reason to learn the use and power of pointers, you can make a pointer to anything including functions. You can even make an array of function pointers that changes dynamically during run time and have the same control structures run different functions or sets of functions using those pointers. But only if you see a need or algorithmic shortcut of course. But you get none of this, can't even think in these terms unless you learn pointers. IMO pointers are behind almost half if not more than half of C.

Multidimension pointers for multidimension arrays are just pointers to arrays of pointers, etc. Take a while to soak that in when you're ready, some practice here and there and it won't be any more confusing than the rest of C.

So, no pressure. Whenever you're ready there's a really good and worthwhile step in your coding education. Working with char array strings will help you understand pointers and pointers will help you with strings.

C++ String Objects OTOH, don't teach you much about these though you can point inside of the mystery box String Object. And then you add 1 char to the String and the box moves and your old pointer is useless... which is how I feel about "please insulate me from the realities of my hardware and my code that I'm too lazy or stupid to learn" C++ String Objects.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

apologies for not replying earlier. Preperations for the Easter, kept me away for favorite hobbies.

Let me thanks all those who participated and help!

GoforSmoke, thank you for the trouble you got into writting all these! I'll read them carefully at the first chance I get. I'm seeing different pointers declaration from time to time for example char *something  or char * something (without and with a space before the variable name) and it gets confusing...

Found also this excellent (I believe so) tutorial here: http://pw1.netcom.com/~tjensen/ptr/pointers.htm
Now all I got to do is find time to read everything!

Thanks again

Happy Easter everyone!!!!
Logged

Pages: 1 [2] 3   Go Up
Jump to: