read word in a string

Example string : The quick brown fox jumps 25F times over the lazy dog.
String may varying like : “ The lazy grey fox jumps 25R times over the quick dog” Or “ The fox jumps ABC times over the cat”……
The part ‘fox jumps xxx times’ is always repetitive AND present , only xxx can vary between 000 and 999 and can be a mix of 3 numbers and/or 3 characters . It is the ‘xxx’ part I need…..
Question 1: how to search for ‘fox’.
Question 2: how to read (or print) the characters from position 8 to 10 (skip the word ‘ jumps ’) following the word ‘fox’ ( in these 3 example strings the result is ‘25F’ or ‘25R’ or ‘ABC’ )
Thanks for helping me learning Arduino Uno

Example string : The quick brown fox jumps 25F times over the lazy dog.
String may varying like : " The lazy grey fox jumps 25R times over the quick dog" Or " The fox jumps ABC times over the cat"……

Are you working with a c-string null terminated character array or is it a String object?

an example with c-Strings and pointers

char message[] = "The jumps fox quick fox jumps brown fox jumps 34F times over the lazy dog";
const char* lookingFor1 = "fox jumps ";
const char* lookingFor2 = " times";

char nbTimes[4] = "";

bool getNbTimes(char * const nbPtr)   // nbPtr needs to hold at least 4 bytes
{
  bool inputOK = false;
  char * part1Ptr = strstr(message, lookingFor1) + strlen(lookingFor1);
  if (part1Ptr) {
    while (part1Ptr) {
      char * part2Ptr = strstr(part1Ptr, lookingFor2);
      if (part2Ptr) {
        if ((part2Ptr - part1Ptr) == 3) {
          inputOK = true;
          strncpy(nbPtr, part1Ptr, 3);
          nbPtr[3] = '\0';
        } else Serial.println(F("nb of times is too long (more than 3 characters)"));
      } else Serial.println(F("no trailing ' times' in message after 'fox jumps '"));
      if (!inputOK) part1Ptr = strstr(part1Ptr, lookingFor1) + strlen(lookingFor1);
      else break;
    }
  } else Serial.println(F("no 'fox jumps ' in message"));

  return inputOK;
}

void setup() {
  Serial.begin(115200);

  if (getNbTimes(nbTimes)) {
    Serial.print(F("found the number of times: '"));
    Serial.print(nbTimes);
    Serial.println(F("'"));
  } else {
    Serial.println(F("no luck"));
  }
}

void loop() {}

the code first looks for the substring "fox jumps ", and if found looks for a following " times" and if found checks if there are exactly 3 characters in between and if so you win otherwise no luck. if there is an issue in the match of "fox jumps ", then it tries to go to the next one

PS: your specification

xxx can vary between 000 and 999 and can be a mix of 3 numbers and/or 3 characters

does not make sense, if you allow any 3 characters chances are it won't be between 000 and 999...

Best to use cstrings

void setup() {
Serial.begin(9600);
char message[] = "The quick brown fox jumps 25F times over the lazy dog";
char * pointer= strstr(message,"jumps ");
if (pointer != NULL) {
  char substring[4]={0}; //3 characters plus zero terminating byte
  memcpy(substring,pointer+6,3); //point to character after the blank in "jumps ", copy next 3
  Serial.println(substring);
}
}

void loop() {}

step 1) Put received characters into a buffer, until you receive a newline ('\n'). Ignore any carriage returns ('\r').
step 2) Use strtok to parse off a single word from the buffer, terminated by a space, since all words appear to be separated by spaces
step 3) Compare the current word to your "key", apparently "fox".
step 4) If the word does not match "fox", then go to step 2.
step 5) If the word does match "fox", use strtok to get the next word, and compare it to "jumped".
step 6) If the word does not match "jumped", go to step 3
step 7) If the word does match "jumped", use strtok to get the next word, and pass it to atoi, to convert to an int.
step 8) Go to step 1

jremington:
Best to use cstrings
..

what if you have

char message[] = "The jumps fox quick fox jumps brown fox jumps 34F times over the lazy dog";

We can all fabricate sequences that won't work, but that is really not helpful.

The OP wrote:

The part 'fox jumps xxx times' is always repetitive AND present , only xxx can vary between 000 and 999 and can be a mix of 3 numbers and/or 3 characters . It is the 'xxx' part I need…..

I assumed, based on the OPs description, that the sequence "fox jumps xxx" uniquely identifies the sequence of tokens to be parsed. If not, the above process is easy enough to modify to suit, once the ACTUAL sequence is accurately defined. But I'm not going to just guess.

c-strings is not the way to go.
Use either Arduino Strings or SafeStrings. (SafeStrings have a richer function set) either are much simplier to code and safer to use then c-strings

To answer your questions using Arduino Strings

Question 1: how to search for 'fox'.

String input = "The quick brown fox jumps 25F times over the lazy dog"
int indexOfFox = input.indexOf("fox")
if (indexOfFox >= 0) {
  Serial.println("found fox");
}

Question 2: how to read (or print) the characters from position 8 to 10 (skip the word ' jumps ') following the word 'fox' ( in these 3 example strings the result is '25F' or '25R' or 'ABC' )

int indexOfFox = input.indexOf("fox")
  if (indexOfFox >= 0) {
    Serial.println("found fox");
    int idxAfterJumps = indexOfFox + 4 + 6;
    String result = input.substring(idxAfterJumps ,idxAfterJumps+3); 
    // the end index is not included in the substring returned
    Serial.println(result);
  }

Output is

found fox
25F
1 Like

@drmpf

C strings do work, you have two codes above to prove it so they are one way to go (and the SafeString stuff you are proudly bragging about in every possible post is based on cStrings too...)

The c-strings code works, but it is very fragile and prone to programmer error.
It does not handle changes in data sizes.
See this forum post for a text book case of why you should not use c-strings
https://forum.arduino.cc/index.php?topic=730965.0

Also the difference between your c-string code and my SafeStrings code, is that the SafeString methods add all the extra buffer length checks that your code (and everyone elses c-string code) omits. That is why SafeString is called 'safe'.

In this case 'standard' Arduino Strings are the easiest and safest to use, but for more extensive text processing or if you are process the char* return from a library or you are doing text to number conversions, SafeStrings have extra useful methods.

drmpf:
Also the difference between your c-string code and my SafeStrings code, is that the SafeString methods add all the extra buffer length checks that your code (and everyone elses c-string code) omits.

you probably did not read the code I posted above. There is no buffer length check to do because there is no need to do so.

Anyway I’m not starting a discussion again - the fact is cStrings are ONE possible solution to OP’s question, and two codes were posted demonstrating this. It should be enough proof it’s possible without adding bloated libraries nor risks.

You seem to have missed the point that my solution code only uses functions from the Arduino Language Reference.

Did you look at Use of string char causes Arduino code to restart - Programming Questions - Arduino Forum ?
You simplistic code without any buffer checks only works until the OP changes something and stuffs it up.

30 years of security hacks has shown even experienced programmers stuff up c-string buffers.

Arduino users should stick with Arduino Strings in the first instance.

I'm not sure what gives you any authority to speak on behalf of "Arduino users" and what they should do.

You keep bringing up irrelevant arguments

  • Buffer overflow attacks for code injection and gaining code execution privileges does not apply to this.

  • The documentation offers the readString() method for example. So if it's in the documentation why did I see you offer alternative ways of receiving incoming data into a String?

  • the String library uses cStrings and so does your library - so if they are good for Arduino and yourself, shouldn't they be good for anyone?

  • if I remember correctly, you were the one to explain that the Arduino Strings have bugs and thus should be dropped in favour of your SafeStrings?

The bottom line is you keep advertising for your library in every possible post and fail to recognise that other approaches are also legit, sometimes as simple or simpler, deliver faster code for a fraction of the memory which is a scarce resources in micro-controlers.

So there is value in being aware of alternatives. It's not a one size fits all, there are different ways and they are all valid as long as they don't bring bugs. That's what Arduino users should know.

PS: done here. bye

Did you look at Use of string char causes Arduino code to restart - Programming Questions - Arduino Forum ?
Your simplistic code without any buffer checks only works until the OP changes something and stuffs it up.

Arduino Strings adds the buffer checks to the c-string methods it uses so it avoids problems and makes the sketches more reliable.
Arduino Strings are the only text manipulation methods documented in the Arduino Reference Language, so yes Arduino CC expects Arduino users will use Arduino Strings in the first instance.

I think @drmpf is well intentioned, but has to accept that canned convenience libraries aren’t the answer to ‘everything’.

Sure - it’s easy to use Strings or safestrings, but for a hardcore programmer, it’s usually preferable to get as low-level as possible... for speed and code size. Adding either usually adds reliability risks.

In C languages, they’re useful, like training wheels, but not teaching good coding habits.

vandenr:
Example string : The quick brown fox jumps 25F times over the lazy dog.
String may varying like : “ The lazy grey fox jumps 25R times over the quick dog” Or “ The fox jumps ABC times over the cat”……
The part ‘fox jumps xxx times’ is always repetitive AND present , only xxx can vary between 000 and 999 and can be a mix of 3 numbers and/or 3 characters . It is the ‘xxx’ part I need…..
Question 1: how to search for ‘fox’.
Question 2: how to read (or print) the characters from position 8 to 10 (skip the word ‘ jumps ’) following the word ‘fox’ ( in these 3 example strings the result is ‘25F’ or ‘25R’ or ‘ABC’ )
Thanks for helping me learning Arduino Uno

Thank to everyone , 'problem' is solved by 'try and error' using a lot of example sketches.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.