I'm attempting to send data from a serial connection to a GSM modem, but having problems. The string from rx looks like this:
1.0 2.0 3.0 4.0
Here's my code to replace the spaces and then I just want to pass the whole string on, regardless of what's inside (there could be negative values too).
data_current[data_index++] = ',';
char received = bike_port.read(); //bike
char test[32];
inData += received;
if (received == '\n')
{
String nospace = inData;
nospace.replace("\t",",");
debug_println("Data: ");
debug_println(nospace);
inData = ""; // Clear recieved buffer
delay(1000);
}
sprintf(test,32,"%d,%d,%d,%d",(String) nospace);
//strtok(received, tmp);
for (int i=0; i<strlen(test); i++) {
data_current[data_index++] = test[i];
}
I have also tried
sprintf(test,32,"%ld,(String) nospace);
What I get now is this error
cannot pass objects of non-trivially-copyable type 'class String' through '...'
Without the sprintf line I can successfully echo the string to debug_println (Serial Monitor). What am I doing wrong?
3 Answers 3
The basic problem here is that you're trying to pass a String
object to sprintf()
. That isn't possible because String
is a C++ class, and sprintf()
is a C variadic function. The only way to pass a string to it is as a char *
.
The rest of your call to sprintf()
doesn't seem to make sense either, although I suspect it's not what you actually want here. You'd normally use sprintf()
if you want to format several values into a string.
As you've suggested in the comments, adding the contents of nospace
to data_current
character-at-a-time would be the sensible approach. You could do it something like this:
for (int i = 0; i < nospace.length(); ++i) {
data_current[data_index++] = nospace[i];
}
Note that strlen()
won't work on nospace
because it's a String
object not a char
array.
This is all assuming that there's enough space in data_current
though. Without seeing the rest of your code, I can't tell you if it will definitely work or not.
Update:
As an alternative, you could use memcpy()
to do a block transfer:
memcpy(data_current + data_index, nospace.c_str(), nospace.length());
data_index += nospace.length();
I'm not sure there's much benefit to doing that though. It's hypothetically more efficient, but it probably won't make a noticeable difference unless your string is moderately long and it's being called very frequently. (It's trading-off the loop overhead against a function-call overhead.)
-
There should be enough space, if not, I know where to change it. But is there a way to add the whole content of nospace, not a character at a time? Because it then gets sent through GSM. I don't know what the exact character length will be, but I do know the maximum.Fid– Fid2015年07月16日 15:06:24 +00:00Commented Jul 16, 2015 at 15:06
-
@Fid You could use
memcpy()
in theory, although I don't know how much difference it will really make. I've updated my answer with details anyway.Peter Bloomfield– Peter Bloomfield2015年07月16日 15:59:04 +00:00Commented Jul 16, 2015 at 15:59 -
"But is there a way to add the whole content of nospace, not a character at a time?" Yes and no: Yes, you can express it that way in C++; adding strings translates into concatenation. No, because for most processors, and for AVR's in particular, it ultimately involves a character by character copy. In other words, write it however it reads best to you. It won't make much difference at run time.JRobert– JRobert2015年07月22日 14:39:05 +00:00Commented Jul 22, 2015 at 14:39
As a companion to Nick Gammon's excellent answer, here is a streaming version of that (assuming this is coming in one serial port and out another to the modem).
if (Serial.available()) {
int inByte = Serial.read();
if (inByte == ' ')
Serial1.write(',');
else
Serial1.write(inByte);
}
Let me get this straight. You want to change:
1.0 2.0 3.0 4.0
to:
1.0,2.0,3.0,4.0
Right?
How about:
char indata[32] = "1.0 2.0 3.0 4.0";
int len = strlen (indata);
for (int i = 0; i < len; i++)
if (isspace (indata [i]))
indata [i] = ',';
Serial.println (indata); // prints: 1.0,2.0,3.0,4.0
Only problem is that when I change "1.0 2.0 3.0 4.0" to the actual incoming read (bike_port.read()), than I get error ...
In that case, as Jake C said, modify the incoming byte like this:
char received = bike_port.read(); //bike
if (isspace (received))
received = ',';
-
This works wonderfully. Only problem is that when I change "1.0 2.0 3.0 4.0" to the actual incoming read (bike_port.read()), than I get error "array must be initialized with a brace-enclosed initializer".Fid– Fid2015年07月21日 16:00:10 +00:00Commented Jul 21, 2015 at 16:00
sprintf()
line doesn't seem to make sense. What are you trying to get it to do?