Fetch the value between a String

String sread = "R123G110B123"; //a string from processing by serial ;

i use indexOf to get the RGB's index number .
but how can i fetch the number between two index number quickly?
i can't find and method to do this in reference of Arduino website.

should i use substring and remove function to get this done? or some function will do this directly .
something like this :

String.fetch(index1,index2); :money_mouth_face:

Personally i use the serial peek function to locate the letters.

This is a snippit from a program I'm using to retrieve data from my greenhouse,
I removed most of it to keep it simple. rest is shown here : Arduino - DIY SCADA with Visual Studio - Bringing Redcraft into the real world ;) - YouTube

I peek for the letter "E" and in your case you would for R, then G, and finally B.
Then i read the content after that letter. In my case i do 2 reads because I'm retrieving
to values after the letter E.

finally clear the data,
and turn a LED on off depending on the value.

  if(Serial.available() > 0)
  {
    digitalWrite(LED2Pin, HIGH);
    
    while (Serial.peek() == 'E')
    {
      Serial.read();
      incomingByte[0] = Serial.parseInt();
      Serial.read();
      incomingByte[1] = Serial.parseInt();      
    }
    // clear data
    while (Serial.available() > 0) {
      Serial.read();
      }
       
      switch (incomingByte[0])
      {
        case 0:
        digitalWrite(LED1Pin, LOW);
        break;
        case 1:
        digitalWrite(LED1Pin, HIGH);
        break;
      }    
  } else {
    digitalWrite(LED2Pin, LOW);
  }

This is running in my "void loop ()"

It’s the mention of the word “string” that will put many off this question. String type variables have some nasty, memory wasting, issues on the arduino. char arrays are capable of being used wherever Strings are used and do not cause the same issues, so would therefore be the preferred choice of data type.

Personally I’m not very familiar with the techniques available for manipulating Strings (since I never use them). Now if you were usiing a char array to hold your “string” I’d suggest you write a function to do the job for you, something like this.

(untested)

int intAfterChar(char* rgbstring, char marker)
{
int value=0;
int n;

//first find the marker
while(rgbstring[n] != 0)
  {
   if( rgbstring[n] == marker)
    break;
   n++;
  }

//We've either found the marker
//or run out of characters
if( rgbstring[n] == 0 )
  return -1;

//step past the marker
n++;

while( rgbstring[n] >= '0' && rgbstring[n] <= '9' )
  {
   value *= 10;
   value += rgbstring[n]-'0';
   n++;
  }

return value;
}

Within your code you could call it something like this

char rgbstring[] ="R22G19B244";
int red = intAfterChar( rgbstring, 'R' );
int green = intAfterChar( rgbstring, 'G' );
int blue = intAfterChar( rgbstring, 'B' );

You could use a state machine and evaluate the serial data as it comes in character by character.
Nick Gammon shows that and more in the second link at the bottom of this post.

One big thing I find in most of the code floating around is a lack of error check and handling. The code expects perfect data every time so the interesting part for me is what happens when unexpected data arrives? Will it crash or will it pass along garbage output? Why? Because serial has no guarantees and when it's your butt or wallet on the line you may learn late to watch out! But that's just my view from having learned the hard way long ago.

Really, Nicks blogs are really good at explaining and getting people started on ways to write real time capable code. They are worth more than the time to go through them.

thank you for all replies~!

If you persist with the String class, and you have the indexOf() the R and the indexOf() the B, I can't imagine why you can't create a substring() using the position of the character after the R as the start position and the difference between the two positions as the length.

If you used a char array then you could have used sscanf

char str[] = "R123G110B123";

uint8_t R, G, B;

if ( sscanf( str, "R%hhuG%hhuB%hhu", &R, &G, &B ) == 3 )
{
    Serial.println( R );
    Serial.println( G );
    Serial.println( B );
}

guix:
If you used a char array then you could have used sscanf

That String class is looking less appealing all the time :slight_smile:

but how can i fetch the number between two index number quickly?

What do you find too be too slow? Below is a link to the String functions, and bottom is some serial test code that seems to be similar to what you want. Note that when sending a string of characters it is best to add a delimiter to distinguish the end of the data packet.

//zoomkat 11-12-13 String capture and parsing  
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data 

String readString; //main captured String 
String angle; //data String
String fuel;
String speed1;
String altidude;

int ind1; // , locations
int ind2;
int ind3;
int ind4;
 
void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 90,low,15.6,125*
  //or 130,hi,7.2,389*

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '*') {
      //do stuff
      
      Serial.println();
      Serial.print("captured String is : "); 
      Serial.println(readString); //prints string to serial port out
      
      ind1 = readString.indexOf(',');  //finds location of first ,
      angle = readString.substring(0, ind1);   //captures first data String
      ind2 = readString.indexOf(',', ind1+1 );   //finds location of second ,
      fuel = readString.substring(ind1+1, ind2+1);   //captures second data String
      ind3 = readString.indexOf(',', ind2+1 );
      speed1 = readString.substring(ind2+1, ind3+1);
      ind4 = readString.indexOf(',', ind3+1 );
      altidude = readString.substring(ind3+1); //captures remain part of data after last ,

      Serial.print("angle = ");
      Serial.println(angle); 
      Serial.print("fuel = ");
      Serial.println(fuel);
      Serial.print("speed = ");
      Serial.println(speed1);
      Serial.print("altidude = ");
      Serial.println(altidude);
      Serial.println();
      Serial.println();
      
      readString=""; //clears variable for new input
      angle="";
      fuel="";
      speed1="";
      altidude="";
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}