How to pass string values to integers

Hi, I am trying to extract the parameters of a string that contains the date and time to integers to a structure, but I can only get the first variables, could someone tell me what is my error?

   struct fechaHora{
    uint16_t year;          
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
    bool valid;
};
  
  struct fechaHora dateTime;
  
  String bufferRX = $DT 20211028225443,V*46;

  dateTime.year = (bufferRX.substring(5, 8)).toInt();
  Serial.println(dateTime.year);
  
  dateTime.month = (bufferRX.substring(9, 10)).toInt();
  Serial.println(dateTime.month);
  
  dateTime.day = (bufferRX.substring(11, 12)).toInt();
  Serial.println(dateTime.day);
  
  dateTime.hour = (bufferRX.substring(13, 14)).toInt();
  Serial.println(dateTime.hour);
  
  dateTime.minute = (bufferRX.substring(15, 16)).toInt();
  Serial.println(dateTime.minute);
  
  dateTime.second = (bufferRX.substring(17, 18)).toInt();
  Serial.println(dateTime.second);
  
  dateTime.valid = bufferRX.substring(20);
  Serial.println(dateTime.valid);

Please post enough code to test.
What results are you getting?

Post a complete and verifiable code.

How does that compile without quotes?

String bufferRX = "$DT 20211028225443,V*46";

Not really a fan of the String Classfor arduino...

Here's my take on it:

struct fechaHora {
  uint16_t year;
  uint8_t month;
  uint8_t day;
  uint8_t hour;
  uint8_t minute;
  uint8_t second;
  char valid;
};


int str2num(char *str, const int len) {
  char temp[len + 1];

  memcpy (temp, str, len);
  temp[len] = '\0';

  return atoi(temp);
}

void setup() {
  struct fechaHora dateTime;

  char bufferRX[] = "$DT 20211028225443,V*46";

  dateTime.year = str2num(&bufferRX[4], 4);
  dateTime.month = str2num(&bufferRX[8], 2);
  dateTime.day = str2num(&bufferRX[10], 2);
  dateTime.hour = str2num(&bufferRX[12], 2);
  dateTime.minute = str2num(&bufferRX[14], 2);
  dateTime.second = str2num(&bufferRX[16], 2);
  dateTime.valid = bufferRX[19];

  Serial.println(dateTime.year);
  Serial.println(dateTime.month);
  Serial.println(dateTime.day);
  Serial.println(dateTime.hour);
  Serial.println(dateTime.minute);
  Serial.println(dateTime.second);
  Serial.println(dateTime.valid);
}

void loop() {
  //nothing here (for now!)
}

Hope that helps...

int mon, day, yr;
int hr, min, sec;

const char *s = "20211028225443";
sscanf (s, "%4d%2d%2d%2d%2d%2d", &mon, &day, &yr, &hr, &min, &sec);
3 Likes

Here is my code:

String bufferRX = "$DT 20211028225443,V*46";

struct fechaHora {
  uint16_t year;
  uint8_t month;
  uint8_t day;
  uint8_t hour;
  uint8_t minute;
  uint8_t second;
  bool valid;
};

void setup() {
  Serial.begin(115200);
  Serial.println("\n\r");
  
  struct fechaHora dateTime;
  
  dateTime.year = (bufferRX.substring(5, 8)).toInt();
  Serial.println(dateTime.year);

  dateTime.month = (bufferRX.substring(9, 10)).toInt();
  Serial.println(dateTime.month);

  dateTime.day = (bufferRX.substring(11, 12)).toInt();
  Serial.println(dateTime.day);

  dateTime.hour = (bufferRX.substring(13, 14)).toInt();
  Serial.println(dateTime.hour);

  dateTime.minute = (bufferRX.substring(15, 16)).toInt();
  Serial.println(dateTime.minute);

  dateTime.second = (bufferRX.substring(17, 18)).toInt();
  Serial.println(dateTime.second);

  dateTime.valid = bufferRX.substring(20);
  Serial.println(dateTime.valid);
}

void loop() {

}

and these are the results I get

21
0
8
2
4
3
1

Excellent reply. What value do you expect to get instead of those?

 2021 10 28   22:54:43
const char *bufferRX = "$DT 20211028225443,V*46";

struct fechaHora {
    int year;
    int month;
    int day;
    int hour;
    int minute;
    int second;
    bool valid;
};

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

    struct fechaHora dt;

    sscanf (bufferRX, "%*s %4d%2d%2d%2d%2d%2d",
        &dt.month, &dt.day, &dt.year, &dt.hour, &dt.minute, &dt.second);

    char s [80];
    sprintf (s, " %d %d %d   %2d:%2d:%2d",
        dt.month, dt.day, dt.year, dt.hour, dt.minute, dt.second);

    Serial.println (s);
}

void loop () {
}

You have been given a couple of alternatives but to answer your question, if you lookup the Arduino- reference for substring:

which means that in you code,

  1. you havebeen using the incorrect indexes and,
  2. you started with index is '1' instead of '0'!

IMHO your should be like this to have the desired output:

String bufferRX = "$DT 20211028225443,V*46";

struct fechaHora {
  uint16_t year;
  uint8_t month;
  uint8_t day;
  uint8_t hour;
  uint8_t minute;
  uint8_t second;
  bool valid;
};

void setup() {
  Serial.begin(115200);
  Serial.println("\n\r");

  struct fechaHora dateTime;

  dateTime.year = (bufferRX.substring(4, 8)).toInt();
  Serial.println(dateTime.year);

  dateTime.month = (bufferRX.substring(8, 10)).toInt();
  Serial.println(dateTime.month);

  dateTime.day = (bufferRX.substring(10, 12)).toInt();
  Serial.println(dateTime.day);

  dateTime.hour = (bufferRX.substring(12, 14)).toInt();
  Serial.println(dateTime.hour);

  dateTime.minute = (bufferRX.substring(14, 16)).toInt();
  Serial.println(dateTime.minute);

  dateTime.second = (bufferRX.substring(16, 18)).toInt();
  Serial.println(dateTime.second);

  dateTime.valid = bufferRX.substring(19);
  Serial.println(dateTime.valid);
}

void loop() {

}

Output:
2021
10
28
22
54
43
1

hope that helps....

Assigning a String to a bool is strange.
I would guess an empty String will also be considered true.

That won't even compile.

You're wrong.

String empty, withContent = "content";

void setup() {
  Serial.begin(115200);
  bool boolValue = empty;
  Serial.print(F("empty gives "));
  Serial.print(boolValue);
  boolValue = withContent;
  Serial.print(F(", content gives "));
  Serial.println(boolValue);
}
void loop() {}
empty gives 1, content gives 1

So all Strings are true. Not so useful.

It doesn't compile here.

Arduino: 1.8.16 (Windows 10), Board: "LOLIN(WEMOS) D1 R2 & mini, 80 MHz, Flash, Disabled (new aborts on oom), Disabled, All SSL ciphers (most compatible), 32KB cache + 32KB IRAM (balanced), Use pgm_read macros for IRAM/PROGMEM, 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600"

C:\Users\steve\Documents\Arduino\sketch_nov04c\sketch_nov04c.ino: In function 'void setup()':

sketch_nov04c:5:20: error: cannot convert 'String' to 'bool' in initialization

    5 |   bool boolValue = empty;

      |                    ^~~~~

      |                    |

      |                    String

sketch_nov04c:8:15: error: cannot convert 'String' to 'bool' in assignment

    8 |   boolValue = withContent;

      |               ^~~~~~~~~~~

      |               |

      |               String

exit status 1

cannot convert 'String' to 'bool' in initialization



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

The ESPs use a different compiler, and a different String library.

Since I never use Strings, I wouldn't have known.

I was under the impression that the IDE uses the GCC compiler for all boards?

I think it is one of the Arduino extensions to 'help' beginners by hiding error from them.

This points in that direction:

class String
{
	// use a function pointer to allow for "if (s)" without the
	// complications of an operator bool(). for more information, see:
	// http://www.artima.com/cppsource/safebool.html
	typedef void (String::*StringIfHelperType)() const;
	void StringIfHelper() const {}

Thanks for everyone's responses, it has been very illustrative, especially to Sherzaad, your both answers have helped me to understand my mistake, thank you