I'm trying to convert a sketch from 0018 to 0021. 0021 has a built in string function replacing the WString library. I get a compile error at the n = atoi(readString); line in the code below. Anybody know what is changed to cause the compile error?
// zoomkat 7-30-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// http://arduino.cc/en/uploads/Tutorial/String.zip for WString.h
//#include <WString.h> //provides easy string handling
String readString = String(100);
#include <Servo.h>
Servo myservo; // create servo object to control a servo
void setup() {
Serial.begin(9600);
myservo.attach(9);
}
void loop() {
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
readString += c;}
//readString.append(c); } //makes the string readString
}
if (readString.length() >0) {
Serial.println(readString);
int n;
n = atoi(readString); //convert string to number
//myservo.writeMicroseconds(n);
myservo.write(n);
readString="";
}
}
int n;
char carray[6];
readString.toCharArray(carray, sizeof(carray));
n = atoi(carray);
Regards,
Dave
Footnote:
For some reason, the authors of the WString stuff now supplied in the Arduino core libraries chose not to define a function that allows direct access to the char array that holds the string data. The current version of getBytes() does something completely different than that function did in the old external WString library.
As an experiment I added the following to the public section of Wstring.h:
const char * c_str() const {return _buffer;}
Then I was able to do stuff like:
int n;
n = atoi(readString.c_str());
Can anyone think of a good reason not to have a member function that returns a (read-only) pointer to the data array? I mean, it's good enough for the C++ std::string class. Why isn't it good enough for us?
I mean, really, making the user declare an array and then have a member function that does a strncpy to it when all we really want to do is to read the contents of the string data array? Really!
Making a new array seems to work, so beow is the updated code.
// zoomkat 10-4-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// for 0019 and later
String readString = String(100);
#include <Servo.h>
Servo myservo; // create servo object to control a servo
void setup() {
Serial.begin(9600);
myservo.attach(9);
}
void loop() {
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
readString += c;} //makes the string readString
}
if (readString.length() >0) {
Serial.println(readString);
int n;
char carray[6];
readString.toCharArray(carray, sizeof(carray));
n = atoi(carray);
myservo.writeMicroseconds(n);
//myservo.write(n);
readString="";
}
}
Crap like this is why us old timers claim that C++ is unsuitable for small microcontrollers. It's not that C++ is inherently less efficient, it's just that somehow silly inefficiencies get propagated anyway. "I'll just make a copy of my string so that I can convert it to a number." Grr.
The author(s) of the Arduino String class didn't put an "easy-access" member function, and instead, used the copy-the-string-data-to-an-array thingie. I showed how easy (almost painless, right?) it is to add something that I consider safe and useful.
I, personally, might not use the String class or any class or other function that uses dynamic memory allocation in a "serious", "big-time" project on a system with such limited resources as an ATmega328p. Good old strcpy and strcat with arrays of chars was good enough for Brian Kernighan, and it's good enough for me. We don't need no stinkin' String class.
For me the point is not whether it is "efficient" or not, it's just that, in small embedded systems, I like to have a feeling, up front, that I know what is going on in the program. I think it's easier to do in C than in C++. (And it's definitely easy to let it get away when classes use dynamic memory allocation.) So I typically write as if it were "mostly C" and not C++. But that's just me. I'm funny that way.
On the other hand...
Chacun à son goût!
Regards,
Dave
**Footnote:**I do use things like the built-in Serial class and the LiquidCrystal class and other derivatives of the Print class (why would I not do that?), so I can't say that my programs are "pure C." But...
I agree with you 100%. I use as little C++ as possible on the Arduino platform. Just the way I was brought up, I guess.
The problem is that beginners don't know the difference between C++ and C. They don't know the difference between String's and Wstring's and NUL-terminated strings. So they try to use the String class and run into problems like this.
The "solution" seems pretty simple. Add some more methods (overhead) to the string class. ConvertToInt() and ConvertToFloat() seem like reasonable candidates, and would avoid the need to copy the string.
Yep. And keep on adding methods until you've duplicated the existing functionality in the str*() functions. Then just sit back and wait until someone asks "How can I reduce the size of the String class?"