Please take a look at following example (I have Java background):
const char* BT_ADDRESS = "abcd,ef,ghijkl";
void bar(const char* string) {
...
}
void foo() {
bar("AT+BIND=" + BT_ADDRESS);
bar("AT+LINK=" + BT_ADDRESS);
}
How to achieve this with "Arduino-C++" so BT_ADDRESS only has to be entered at one location?
2 Answers 2
There is, as you may expect with C, many different ways of doing this.
The simplest is probably to use, instead of a const variable, a preprocessor macro.
In C you can concatenate string literals like this:
print("AT+BIND=" "abcd,ef,ghijkl");
Note the lack of anything but spaces between the strings - they are concatenated together. You can even do it on separate lines - it's a technique that is great for incredibly long strings.
Now you can, of course, replace one of those with a preprocessor macro:
#define BT_ADDRESS "abcd,ef,ghijkl"
print("AT+BIND=" BT_ADDRESS);
print("AT+LINK=" BT_ADDRESS);
The preprocessing replaces BT_ADDRESS with the string literal "abcd,ef,ghijkl" and all is well.
Other options, depending on what print
does, is to expand it to take two const char *
parameters and deal with them both separately. For instance, you might have:
void print(const char *command, const char *data) {
Serial.print(command);
Serial.println(data);
}
print("AT+BIND=", BT_ADDRESS);
If you don't know how many parameters you may want to pass you could use variadic arguments:
#include <stdarg.h>
void print(int count, ...) {
va_list args;
va_start args, count);
for (int i = 0; i < count; i++) {
const char *arg = va_arg(args, const char *);
Serial.print(arg);
}
va_end(args);
}
print(2, "AT+BIND=", BT_ADDRESS);
Yet another option is to pre-format the data into a single string using the various string operators. For example:
int len = strlen("AT+BIND=") + strlen(BT_ADDRESS);
char temp[len + 1]; // Be sure to keep space for the terminating NULL.
strcpy(temp, "AT+BIND=");
strcat(BT_ADDRESS);
print(temp);
I could go on all night with different options... The first one using the preprocessor is probably easiest though.
Get rid of strange print()
and use standard stdout
, fprintf()
and %
format tokens.
#include <stdio.h>
#include <Stream.h>
// printf to file support http://arduino.cc/playground/Main/Printf
// we need fundamental FILE definitions and printf declarations
// apparently it eats 1k FLASH by saves to much copy&paste and hopefully even FLASH
// create a output function
// This works because Serial.write, although of
// type virtual, already exists.
static int stream_putchar (char c, FILE *stream) {
((Stream*)(stream->udata))->write(c);
return 0;
}
void SetupFileStream(FILE* file, Print* stream) {
fdev_setup_stream(file, stream_putchar, NULL, _FDEV_SETUP_WRITE);
file->udata = stream;
}
#ifdef UDRE0
// non interrupt transmit function
static int uart_putchar (char c, FILE *stream) {
volatile byte *ucsrna = (byte*)(stream->udata);
while ( !bitRead( ucsrna[0], UDRE0) ) {;} // wait for transmit buffer is empty
ucsrna[&UDR0-&UCSR0A] = c;
return 0;
}
void SetupUartStream(FILE* file, volatile byte *ucsrna) {
fdev_setup_stream(file, uart_putchar, NULL, _FDEV_SETUP_WRITE);
file->udata = (void*) ucsrna;
}
#endif
#define INFO(fmt, args...) \
fprintf_P(stderr, PROGSTR("INFO: " fmt), ## args);
// create a FILE structure to reference our UART output function in main project file
static FILE myStdOut = {0};
void setup() {
....
Serial.begin(19200);
SetupUartStream(&myStdOut, &UCSR0A); // when debugging in AvrStudio then debugger is saturated by debug messages in user data empty interrupt handler if used buffered stream output
// The uart is the standard output device STDOUT
stdout = &myStdOut;
stderr = stdout;
...
}
....
const char* BT_ADDRESS_RAM = "abcd,ef,ghijkl";
const char* PROGMEM BT_ADDRESS_FLASH = "abcd,ef,ghijkl";
INFO("AT+BIND=%s", BT_ADDRESS_RAM);
INFO("AT+BIND=%S", BT_ADDRESS_FLASH);
-
print
was just an example name of a method.Thomas S.– Thomas S.2015年10月13日 05:01:10 +00:00Commented Oct 13, 2015 at 5:01 -
If
print()
is just example and you need concatenated string (not streamed output) then you can use standardsprintf(), strcat()
or so. Because you have initialized variableconst char*
you must do in runtime,bar("AT+LINK=" + BT_ADDRESS)
is attempt to do it in compilation time.TMa– TMa2015年10月13日 07:25:15 +00:00Commented Oct 13, 2015 at 7:25 -
Concatenating at compilation time (where possible) is what I need.Thomas S.– Thomas S.2015年10月13日 10:11:53 +00:00Commented Oct 13, 2015 at 10:11
-
Then you can use:
#define BT_ADDRESS "abcd,ef,ghijkl"
bar("AT+BIND" BT_ADDRESS);
But you should clarify what means entered at one location, because it can mean to avoid copy pasting or to save FLASH memory avoiding duplicate strings there.TMa– TMa2015年10月13日 13:02:45 +00:00Commented Oct 13, 2015 at 13:02
print
does.