I've spent several hours reading up on the right way to handle text in my sketches, and I'll admit, even though i've seen some excellent write-ups on the topic, when I put the methods into practice, it just doesn't seem to work consistently for me. For example, I have a little project that uses a 16 x 2 LCD screen that has an i2c interface. And when I tried to implement chars etc. i got mixed results.
So in my efforts to try and handle text properly with the Arduino, I wrote a method that looks like this (I'll include an example of how I use it as well):
void lcdOut (const char msg[], const int len, const int lin, const int pos) {
int line = lin - 1;
int cap = len - 1;
lcd.setCursor(pos, line);
for (int x = 0; x < cap; x++) {
lcd.write((char) msg[x]);
}
}
void doStuff() {
int num = 5;
char msg[16];
sprintf(msg,"Send %i Pencils",num);
lcdOut(msg, sizeof(msg), 1, 0); // The 1, 0 means print on line one starting at the left most position
}
Whats frustrating about this NON String way of doing things, is that sometimes it will display my text just fine, while other times, it just throws garbage onto the display ... and when that happens, I get frustrated and go back to Strings. HOWEVER, I'm kind of backed into a corner right now, because I have a rather large program teetering on max resource consumption and now even String printing to the LCD is buggy - omitting characters from the String or replacing them with symbols ... just buggy crap like that.
I need to get a grip on using chars and being memory and resource conscious but im at a loss on how to wrap my head around all of it.
Would someone critique the above example and tell me what I'm doing wrong? Might be a good place to start moving forward.
How many characters do you think you can store in msg?
Regards,
Ray L.
You know what, I normally declare it with 16 elements since each line on the LCD can hold 16 characters ... thats an oversight in my example, my bad. If I am allowed to edit my post, I'll correct it.
EasyGoing1:
You know what, I normally declare it with 16 elements since each line on the LCD can hold 16 characters ... thats an oversight in my example, my bad. If I am allowed to edit my post, I'll correct it.
OK, so you did not post actual, tested code. That just wastes our time...
void lcdOut (const char msg[], const int len, const int lin, const int pos) {
Why are you using const in all the argument types? The first one makes sense. It says that the function will not alter the contents of the array that is passed by address. The caller might care about that.
The others say that the function will not alter the values that are passed by value. The caller won't give a rats ass what the function does with the value that it receives.
PaulS:
Why are you using const in all the argument types?
The answer might make you twitch a little ...
I was under the impression that constants get stored in memory differently (more efficiently?) and i've been trying to squeeze as much as I can out of this little Nano ... If my impression is wrong, please let me know.
RayLivingston:
OK, so you did not post actual, tested code. That just wastes our time...
Regards,
Ray L.
Please, don't let an amateur like myself waste your time. I certainly don't wish to be in anyone's debt... from now on, you can just ignore my posts ...as I certainly don't wish to be a burden.
Robin2:
I use the cplusplus website for reference about C/C++ cstring functions
...R
Robin,
I spent the last couple of hours reading various things on that site, and the strcat function looked promising to me, so I decided to experiment with it but to no avail. Any char array I built with that function would produce nothing on my LCD display.
However, I decided to give the sprintf function another go, and after trying it various ways, I finally was successful. Here is the code that actually works:
void showTime() {
readTime();
int huor = (int) now.hour();
int mnt = (int) now.minute();
char apm[1] = {"A"};
if (huor > 12) {
huor = huor - 12;
apm[0] = "P";
}
if (huor == 0){huor = 12;}
char timeMsg[6];
sprintf(timeMsg,"%02i:%02i%s",huor,mnt,apm);
lcdnm(timeMsg,sizeof(timeMsg), 1, 10);
}
void lcdnm(const char msg[], int len, int ln, int pos) {
int line = ln - 1;
lcd.setCursor(pos, line);
for (int x = 0; x < len; x++) {
lcd.write((char) msg[x]);
}
}
I am going to carefully go through this code and convert all my Strings to char arrays and test often ... hopefully i'll have some leaner code soon.
The A in this string is followed in the array of chars by a character zero that signals the end of the string to functions that use it. So, the array needs to have at least 2 elements in it to accommodate the 2 characters. Under some circumstances you may get away with it as it is but in practice the terminating zero added automatically by the initialisation of the string will be written to a memory location that may contain another variable. At best this will lead to unpredictable results
In practice you are better off doing this
char apm[] = {"A"};
and letting the compiler decide how many elements the array will have.
PaulS:
The caller won't give a rats ass what the function does with the value that it receives.
The caller won't, but the programmer would certainly like to know if their code is altering a variable that they never intended to be altered (by accidentally using = instead of ==). This is why I make everything const unless I specifically need it to not be const. It makes code more self-documenting and less prone to bugs.
This is why I make everything const unless I specifically need it to not be const. It makes code more self-documenting and less prone to bugs.
That tells me that you understand the meaning, and value, of the const keyword. I was rather hoping that OP would also learn the meaning, and value, of the const keyword, and be able to say that he/she was aware of what it did, and was using it for good reason.
PaulS:
I was rather hoping that OP would also learn the meaning, and value, of the const keyword, and be able to say that he/she was aware of what it did, and was using it for good reason.
I'm here to learn ... am I to understand that making all of the passed variables CONST is not a bad idea unless I intend to modify those variables after they are passed?