This Nick Gammon blog shows different approaches to text input. Be sure to check out the State Machine part:
Nick is a master of simple, common sense and to the point explanations.
Another way of processing incoming data, without blocking, is to set up a "state machine". Effectively this means looking at each byte in the input stream, and handling it depending on the current state.
As an example, say you had this coming into the serial port:
R4500S80G3
Where Rnnn is RPM, Snnnn is speed, and Gnnnn is the gear setting.
The state machine below switches state when it gets a letter "R", "S" or "G". Otherwise it processes incoming digits by multiplying the previous result by 10, and adding in the new one.
When switching states, if first handles the previous state. So for example, after getting R4500 when the "S" arrives, we call the ProcessRPM function, passing it 4500.
This has the advantage of handling long messages without even needing any buffer, thus saving RAM. You can also process message as soon as the state changes, rather than waiting for end-of-line.
But also check out the last sketch on that page:
How to send and receive numbers
To send a number (greater than 0 to 9) from one Arduino to another reliably you need to do a couple of things.
Send some sort of "start number" delimiter (in this example, the "<" character).
"Print" the number, which turns it into a string of ASCII characters.
Send some sort of "end number" delimiter (in this example, the ">" character).
Example sketch, sending 10 random numbers out the serial port:
Note that instead of buffering all the input and only then evaluating it, this way the evaluation is done and ready when the delimiter/end-of-number character is received, and there is no need to use string manipulation and commands at all. Your code starts out on top and stays on top, only 1 char after-the-fact at any time.
These sketches can have other tasks added without any need to weave the new code into the existing code. The new is put in loop() before or after the existing part. The existing code won't block the new code and the new code should not block execution either. You can in practice have multiple programs "run at the same time".
More on that from the Maestro himself:
When you combine this lesson with the ones above, you pretty much have the key to multitasking Arduino without wasting RAM.
Let's look at an analogy. Say you want to cook breakfast. You need to cook:
Coffee - takes 1 minute
Bacon - takes 2 minutes
Eggs - takes 3 minutes
Now a seasoned cook would NOT do this:
Put coffee on. Stare at watch until 1 minute has elapsed. Pour coffee.
Cook bacon. Stare at watch until 2 minutes have elapsed. Serve bacon.
Fry eggs. Stare at watch until 3 minutes have elapsed. Serve eggs.
The flaw in this is that whichever way you do it, something is going to be cooked too early (and get cold).
In computer terminology this is blocking. That is, you don't do anything else until the one task at hand is over.
What you are likely to do is this:
Start frying eggs. Look at watch and note the time.
Glance at watch from time to time. When one minute is up then ...
Start cooking bacon. Look at watch and note the time.
Glance at watch from time to time. When another minute is up then ...
Put coffee on. Look at watch and note the time.
When 3 minutes are up, everything is cooked. Serve it all up.
In computer terminology this is non-blocking. That is, keep doing other things while you wait for time to be up.