I'm into my second day trying to resolve this issue after much searching. I am testing a method of taking input from a numeric keypad (includes * and #) and converting it to an integer to use as an array subscript. The code works in taking the input and adding each character to a string. Input is terminated with a '#'. What doesn't work is converting that string to an integer. Here is the relevant code (currently just being tested in setup() ):
char key;
String tapRelayStr;
int tapRelayInt = 7;
// Enter tap relay number and press #
while (key != '#') {
Serial.println("Now in while loop");
tapRelayStr.concat(key);
key = keypad.getKey();
}
tapRelayStr.trim();
Serial.print("tapRelayStr is: "); Serial.println(tapRelayStr);
Serial.print("Existing value of tapRelayInt: "); Serial.println(tapRelayInt);
tapRelayInt = tapRelayStr.toInt(); // ***** THIS DOESN'T SEEM TO WORK AS EXPECTED
Serial.print("tapRelayInt after .toInt is: "); Serial.println(tapRelayInt);
//digitalWrite(taps[tapRelayInt], LOW);
}
Here's the output when a '5' is entered followed by '#':
.
.
.
Now in while loop
tapRelayStr is: 5
Existing value of tapRelayInt: 7
tapRelayInt after .toInt is: 0
I declared tapRelayInt = 7 to see if tapRelayStr.toInt() changes the value in any way. It does. It sets tapRelayInt to 0. This is what the .toInt function is supposed to do when it's not given a numeric string. As you see, I've trimmed tapRelayStr just in case, but that's not the issue here. Does anyone know what is the problem? It's driving me nuts. Thanks! --Todd
This tutorial shows you how to input character strings (C-strings) from a keypad without using String objects, which cause program malfunctions and even crashes on AVR-based Arduinos.
while ( key != '#' ) { //
if ( key >= '0' && key <= '9' )
{
tapRelayStr.concat(key);
Serial.print("tapRelayStr is now: "); Serial.println(tapRelayStr);
}
key = keypad.getKey();
}
And you should always initialize local variable to a known value (unless you don't care about the garbage that it may contain), for example char key = NO_KEY;. If you don't initialize this variable, it may very well contain the garbage value # and your code will not work as expected
@guix suggestion should help, getKey() returns a value of 0 (the actual value of 0, not a '0' character) when no key is pressed, that is getting added onto your String, and toInt will terminate when it sees a character that is not part of a number. You can print the length of the String to see that it exceeds the actual number you are entering.
Well, that works! Keypad input works just as I intended. Many thanks!
I'm at a loss, though, as to the reason why adding the if from '0' to '9' clause made the tapRelayStr.toInt statement play nice. As far as I could tell, there already were no characters outside that range, and I trimmed off any leading or trailing blanks or nulls. What am I missing here?
Okay, I didn't know getKey() did anything at all unless there was a pending keypad event. I guess tapRelayStr.trim() doesn't strip off the 0 values? If not, I guess I can test for them if needed with the .length() function? Many thanks!
I think david_2018's point just sank in. The if clause you suggested kept any zero characters returned from keypad.getKey() from getting added to tapRelayStr (and therefore causing tapRelayStr.toInt() to return 0 from a string that doesn't begin with a number character). Is that right?
Regarding atoi(), is it better to use than toInt() because atoi() doesn't care about leading whitespace (including zero characters)? And also because trim() doesn't remove leading zero characters?
If you didn't press any key for 4 seconds then you pressed key 7, your String contained this : \0\0\0\07, so trim and toInt stopped right at the beginning of the String, because those functions saw a \0 and that is (normally) the end of String, as well as the end of a C-string (null-terminated char array), hence why toInt returned 0 and not 7.
The fact that you can print the String and it shows ____7 ( _ being blank spaces that can't be displayed here ) is strange to me, I would expect the String to be printed as empty.
And atoi works with null-terminated char arrays, not with Strings
I'm told that when getKey() (from the keypad.h library) is called it returns a NULL if there's no keypad input, so each time through my while loop with no input a NULL is added to the string I built using concat(). It shouldn't do that, but there you have it. @guix's solution was to use an if statement to keep all characters except 0-9 from being appended to the string. I will be looking into using c-strings instead of Arduino's String class for future projects, but in this particular case that would not have helped.
As for common sense in writing code, if there isn't a library header for that I can include (i.e., CommonSense.h) then I'm screwed. Anyway, common sense won't help me unless it's also employed by the writers of the libraries I use.
If a null is input, there is no reason to add it to the C-string, unless you intend to terminate the C-string at that point and move on to some other action, like printing the string.
If you don't know how to avoid adding the null, post the code as it now stands and forum members can show you how.
Thanks. As you can see earlier in the thread, @guix already suggested using a conditional to keep everything except 0-9 out of the string. Had I know about the silly NULLs, I would have figured that out myself.