Hellloooo
I have a question! I want (when I write number on the serial monitor) the program to multiply the numbers. This is my code but I dont know what went wrong. Could someone help me please?
String number;
String message;
int total= 0;
void setup() {
int i;
Serial.begin (9600);
number = random (1, 500);
for (i=0; i <0; ++i)
total *=number [i];
}
void loop() {
if (Serial.available () >0)
{
char received = Serial.read ();
if (received == '\n')
{
Serial.println (total);
}
}}
Then you need parsing. There is a strong grammar defining operator precedence for example it is customary to agree that 4+58 is 44 and not 160, meaning it’s interpreted as 4+( 58 ). So you can’t read numbers and operations as they come, you need to look ahead. A tree structure can be useful
The program flow is completely wrong. You read in a value in loop() then you do nothing with it. Your attempt at calculation is all in setup() which only runs once BEFORE you have read any thing from Serial in loop().
And what does the random(1,500) have to do with what you say the program should do?
@Steve: I wanted the program to know the numbers 1-500, so thats why (1, 500). I didnt write it in loop, because I dont want it to repeat itself (I thought that what loop is for)
I didnt write it in loop, because I dont want it to repeat itself
well you want to repeat the maths every time you have something to calculate - so the loop would be the right place to do this.
you need to start by clarifying what you expect from the Serial monitor input, for example your use case could be:
user types number1 and validates
user types number2 and validates
=> you print the result of number1 * number2
or it could be
user types number1 operation number2 validates
=> you detect the numbers, detect the operation and print the result
or it could be any arbitrary operation on the line, something like
2 + (7*3) - 5 * (12 + (27/12 - 6)3248 / (3 + 1)) / 22
and then it's a bit more complicated
// https://forum.arduino.cc/?topic=733469#msg4935218
// modified from
// readStringUntil_nonBlocking.ino
// Reads chars into a String until newline '\n'
// https://www.forward.com.au/pfod/ArduinoProgramming/SoftwareSolutions/index.html
// Pros: Simple. Non-Blocking
// Cons: Does not return until the until_c char is found. i.e. no timeout or length limit
String input;
bool haveFirstNum = false;
int num1;
int num2;
void setup() {
Serial.begin(9600);
for (int i = 10; i > 0; i--) {
Serial.print(' '); Serial.print(i);
delay(500);
}
Serial.println();
Serial.println(F("modified from readStringUntil_nonBlocking.ino"));
Serial.println(F(" Enter 2 nums, one per line (terminated by newline)"));
input.reserve(20); // expected line size
}
// read Serial until until_c char found, returns true when found else false
// non-blocking, until_c is returned as last char in String, updates input String with chars read
bool readStringUntil(String& input, char until_c) {
while (Serial.available()) {
char c = Serial.read();
input += c;
if (c == until_c) {
return true;
}
}
return false;
}
void loop() {
if (readStringUntil(input, '\n')) { // read until find newline
Serial.print(F(" got a line of input '")); Serial.print(input); Serial.println("'");
// parse to int
input.trim();
int inputNum = input.toInt(); // a very poor conversion method
if (input == String(inputNum)) { // so check the result
// have valid int
Serial.println(inputNum);
if (!haveFirstNum) {
num1 = inputNum;
haveFirstNum = true;
} else {
num2 = inputNum;
Serial.print(F("Ans:")); Serial.println(num1*num2);
haveFirstNum = false;
}
} else {
Serial.print(F("Number :")); Serial.print(input); Serial.println(F(" is not a valid int"));
}
input = ""; // clear after processing for next line
}
}
My SafeString library has a more powerful SafeStringReader for reading/parsing inputs and much more robust text to number conversion methods.
int number;
int total = 0;
void setup()
{
Serial.begin (9600);
number = random (1, 500);
}
void loop()
{
if (Serial.available () > 0)
{
total = number * Serial.parseInt();
Serial.println(total);
}
}
C and C++ standard cString and String functions have long accepted that 00042 is a valid decimal input for an integer and its value should be 42 or trying to parse an integer from "0042abc" should also return 42 (and if the function is smart tells you there are trailing characters).
Why are you redefining what has been common practice (for almost half a century in the case of cString)?
The rationale for stoping the parsing at the first "non compatible" character is to support inline parsing of simple expressions without having to tokenise for example.
I'm not saying it's robust, I'm just saying this is the commonly agreed behavior and thus if you want to make this robust, don't do it by removing the expected outcome (applies to your sample code and your library if I remember correctly)
Not sure what you are objecting to here.
I am just applying stricter validation to the user's input.
My expected outcome for an input of "44abc" is an Error Message to the user.
If you want your program to accept "44abc" as a valid integer from your user you can use atoi() or a bare Arduino Strings toInt()
I don't want my programs to accept "44abc" or "123456789012345" as valid integers
It has never been common practice for a user input of "42abc" to be accepted as a valid integer by any program.
Neither S.toInt() nor atoi(cS) indicate to the program that there are any "non compatible" chars following.
So pretty useless on their own for handling user input or parsing integer fields.
C recognises this deficency and provides a 'better' function strtol()
if the function is smart tells you there are trailing characters
Yes SafeString toInt() is a smart function that function wraps up strtol() and handles the pointers and checks for "non compatible" chars following and alerts the user by returning false.
As for 00042, yes that should be valid and it is a valid integer under safeString's toInt().
However the simple Arduino String fix I implemented in the code in #7 fails for this case
If the OP wants a really robust validation of the input the he should use SafeString toInt()
Using atoi() or a bare Arduino String toInt() statement to convert an integer input is just sloppy in my book since simple more robust alternatives are available
i.e. If input is an Arduino String
input.trim();
int inputNum = input.toInt(); // a very poor conversion method
if (input == String(inputNum)) { // so check the result
// have valid int
} else {
// input not a valid int
}
OR if input is a SafeString
// trim() not need as SafeString toInt() allows for trailing white space
int inputNum
if (input.toInt(inputNum) {
// have valid int
} else {
// input not a valid int
}
Yes SafeString toInt() is a smart function that function wraps up strtol() and handles the pointers and checks for "non compatible" chars following and alerts the user by returning false.
that's my point.
I'm just saying I do not find smart at all to not handle toInt() in your class in the same way integer parsing has been done for ever elsewhere, whether its String.toInt(), atoi() or the better strtol(). This is breaking well known conventions and expectations. May be you could return false but still provide what you decoded...
With strtol() you still get 42 with this input "0042abc"
May be you could return false but still provide what you decoded...
Yes that is a possibility.
Do you have any example sketches where calling String("5abc").toInt() or String("5 3").toInt()
and returning 5 makes sense to the overall program and is a useful thing to do, other then just hiding a data error.
Any parsing that would not require tokenizing the input string because you know it’s well formed - like reading a number based CSV spreadsheet file or the output of a serial device
The goal is to involve as little substring or remove or whatever string operations as possible and handle the buffer in place like you would do with cString in the first place.
That would be true if you are using strtol() to parse a number from a char* and then saving the endPtr to continue other parsing.
Then returning 5 make sense, but that use case is not possible with atoi(), String toInt() or SafeString toInt()
I don't want my programs to accept "44abc" or "123456789012345" as valid integers
It has never been common practice for a user input of "42abc" to be accepted as a valid integer by any program.
Well, strtol() has been converting hex numbers such as 42abc since probably before 1970. Concerning validation, hierarchical validation is best, working on a string with well defined endpoints. The proper approach is programmatic, since validation needs vary, but since substrings may be context dependent, the validation could also require parsing. In this case, you wish to at least differentiate the 42 and the "abc" and, in your definition, flag the latter as an error. That is all fine, and there is no reason why it can't be implemented using the standard functions that were designed for that purpose, but a scheme is required to guide the parsing. Perhaps the discussion is about how to do that. But it's not a new topic.
Common practice is that base 10 is expected unless otherwise noted, hence my programs don't expect hex input when just asking for an integer.
If I was asking for a memory address that would be a special case and I would advise the user of the valid/expected input format. SafeString has a hexToLong() method to handle numbers in hex format.
validation could also require parsing
I agree entirely. SafeString toInt() / toLong() / hexToLong() / octToLong() / binToLong() / toFloat() / toDouble() are expected to be used at the bottom level after the higher level parsing has extracted a field that is expected to be a number and has identified the expected format for that field.
No argument about the efficiency of c-strings. But you have to be very careful when you program them and the resulting program is fragile. Not recommended. The Arduino Language Reference documents Strings for text manipulation for ease of use and reliability of the the resulting program.