Issue with char array pointers

Please help me.
My boss is breathing fire down my neck.
We make the only device in the world that improves power from a solar panel by 10 percent or more. (ultrasolar.com)
My task is to provide remote command, control, and sensing of our device.
I need to address possibly thousands of our devices at many locations.
I have my code working, but I am having problems with char arrays.
I include code stripped down to the offending routines, keeping all defines and declarations.
I assume my issue has to do with pointers, makes me feel like a real newbe.

I set up a button to enter my command parcer (ParseCommand) in main loop.
As you can see in ParseCommand I set RF24_RecBuff (data radio receive buffer) with address, command, and argument.
My goal is to strip the address, and send the command, and argument to the command interpeter if device address is satisfied.
The first button press AFTER A RESET works fine.
I see RF24_RecBuff gets reduced to the first token after the first token.
All additional button presses results are as “*** second button press ***”.
RF24_RecBuff does not get set to “11 qb on” on any other than the first button press, only gets set to “11”.
My question is why?

Please help me, the back of my neck is getting burned. (and the bosses breath isn’t so great either)

Below is my serial monitor diagnostic output.

Version 1.0.0 BETA 03-01-2021
Exiting Setup

button down // *** first button press ***
button up
Exiting loop

Entering ParseCommand
RF24_RecBuff before tokenizing = 11 qb on // address, command, argument
RF24_RecBuff after tokenizing RecID = 11 // only address
RF24_RecBuff after tokenizing Cmd = 11 // only address
RF24_RecBuff after tokenizing Arg = 11 // only address
RecID = 11 // address
Cmd = qb // command
Arg = on // argument
CommandLine = // after clearing command line
CommandLine = qb on // after building command line, command, argument, exactly what I want

button down // *** second button press ***
button up
Exiting loop

Entering ParseCommand
RF24_RecBuff before tokenizing = 11 // only address, should be “11 qb on”
RF24_RecBuff after tokenizing RecID = 11 // only address
RF24_RecBuff after tokenizing Cmd = 11 // only address
RF24_RecBuff after tokenizing Arg = 11 // only address
RecID = 11 // address
Cmd = // no command
Arg = // no argument
CommandLine = // after clearing command line
CommandLine = // after building command line, nothing

Remote_QB_Minimum.ino (15.4 KB)

If I compiled your code, would it show me the problem?
Paul

Maybe post in gigs, and offer some kind of reward?

I assume that the command should come from Serial as an input somehow.

However, to fix the immediate problem, replace this:

  char* RF24_RecBuff = "11 qb on";

with this:

strcpy(RF24_RecBuff ,"11 qb on");

That'll make it work, even if it is somewhat meaningless.

Paul_KD7HB:
If I compiled your code, would it show me the problem?
Paul

Yes.
Also a ham, kd6kca.

wildbill:
I assume that the command should come from Serial as an input somehow.

However, to fix the immediate problem, replace this:

  char* RF24_RecBuff = "11 qb on";

with this:

strcpy(RF24_RecBuff ,"11 qb on");

That'll make it work, even if it is somewhat meaningless.

Thanks!
Will give it a try.
Can you tell me why RF24_RecBuff is un-settable after the first tokenizing?

Ed

This:

char* RF24_RecBuff = "11 qb on";

Says declare a local char pointer and point it to an area of memory where "11 qb on" was initialized at startup.

The first time you called ParseCommand, you used strtok to tokenize it and that wrote some nulls on the only copy of that string in memory so that on subsequent calls, it no longer contains "11 qb on", as you observe.

strcpy copies the string to your global buffer so it can damage it parsing without impacting the original.

In modern C/C++ standards, a string like that is supposed to be left untouched. When I learned C, I believe I was free to mess with string constants in RAM and as you see with your code, you can still do so, but some time (in the nineties?) that behavior became non kosher or strictly speaking, undefined.

wildbill:
This:

char* RF24_RecBuff = "11 qb on";

Says declare a local char pointer and point it to an area of memory where "11 qb on" was initialized at startup.

The first time you called ParseCommand, you used strtok to tokenize it and that wrote some nulls on the only copy of that string in memory so that on subsequent calls, it no longer contains "11 qb on", as you observe.

strcpy copies the string to your global buffer so it can damage it parsing without impacting the original.

In modern C/C++ standards, a string like that is supposed to be left untouched. When I learned C, I believe I was free to mess with string constants in RAM and as you see with your code, you can still do so, but some time (in the nineties?) that behavior became non kosher or strictly speaking, undefined.

strcpy(RF24_RecBuff ,"11 qb on"); worked!
I receive my char array from a nRF24L01 data radio.
I will try to implement this change to strcpy the data received array to a new parser array.
This saves my backside. (and back of my neck!)
Thanks a lot!
Ed 2.0 KD6KCA

If you are making a commercial device check out my SafeString library that handles char with the safety of Strings.
It has extensive debugging and checks for buffer overflows and missing null terminators what will come back to bite you later in the field.
strcpy is a well know source of program failures

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.