Looking for save SRAM memory i developed a function to work with all my char arrays in PROGMEM because I have not found anything like in the web and i need to store all my strings in PROGMEM without move it to to arrays or something complicated and annoying.
The nearest approach i found: PROGMEM and F() macro as parameters for function - Programming Questions - Arduino Forum but i need a function using a char array. I prefer use char arrays to program. For me is easy to work with it.
My function:
char * progmemToString(const __FlashStringHelper *ifsh) {
static char stringTMP[50]; // I use 50 because is my longest string + 1
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
byte n = 0;
while ( pgm_read_byte ( p ) != NULL )
stringTMP[n++] = pgm_read_byte (p++);
stringTMP[n] = '\0';
return ( stringTMP );
}
My only doubt is with stringTMP: there is a safer way to use a char array without declaring its size? I know actually i am loosing 50 bytes of SRAM declaring stringTMP[50].
My purpose is use the F() function in all the program. Arduino only allow to use F() with classes that allow print, like Serial.print. When i call a routine/function with a string parameter in F() format i receive a compiler error: " cannot convert 'char*' to 'const __FlashStringHelper*' ". To solve it i have just to overload my routine/function like this:
And now i can write a program with things like this: compare( "My text" ); or like that: compare( F("My text") );
For me is the simpliest way to work with strings and move it to PROGMEM and the only way i found without move my strings in the program..
I used this method in a huge program with a variety of routines/functions without problem and found is consistent. Only has one failure: if i call a routine with F() as a parameter and within the routine i call another routine with another F() as a parameter, the arduino goes totally crazy. One arduino program memory killed testing it.
What do you think? Is a correct mode to work with PROGMEM or is it dangerous?
AWOL:
Any good reason for not using strcpy_P, strncpy_P etc?
IT WORKS !!!!!! XD XD XD You are the best. It's a clean and simple solution XD
char * progmemToString(const __FlashStringHelper *ifsh) {
static char stringTMP[50]; // I use 50 because is my longest string + 1
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
strcpy_P(stringTMP, (char*)p);
return ( stringTMP );
}
The only doubt i have is the control of the length of the string. robtillaart solved before but it's impossible to apply with strcpy_P. Maybe strcpy_P prevents this fail?
The only doubt i have is the control of the lenght of the string robtillaart commented before.
Which is why AWOL also suggested strncpy_P.
Looking at info of strncpy_P strncpy_P uses the lenght of the string as parameter.
I don't have the lenght of the string when using F(), but i'm thinking if i use the maximum legth of stringTMP (actually 49) and strncpy_p fills it with nulls between the progmem string and its end, sounds interesting.
So, the code is:
char * progmemToString(const __FlashStringHelper *ifsh) {
static char stringTMP[50]; // I use 50 because is my longest string + 1
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
strncpy_P(stringTMP, (char*)p, 49);
return ( stringTMP );
}
My answer is option 2: i'm trying to make sure that i don't write beyond the end of the destination array stringTMP
Then, pYro_65's answer is what you need.
My question was designed to get you to research what strXXX functions had strXXX_P versions.
Applying str function to this problem is AWOL's idea a few time ago (A really good idea XD). I have not yet had time to process the implications and the ramifications. You 're right. I need to think about that.
Anyway, i think there is 2 options now. One option is left the last code i posted, with strcpy_P and the other option is change it with this line
strncpy_P( stringTMP, (char*)p, strlen_P(p) );
The question is: The legth control is necessary or the first option serves well its purpose, filling automatically the rest of the destination array with nulls? Maybe i need to think about speed or having trouble with large strings in PROGMEM larger than 49 chars and add more lines to control it. Pros and cons, mmmm.....