sscanf issue - Some matches others not

Hey guys,

Attached is an example sketch of an issue I'm having with sscanf.
I've got a date string "18/01/28,21:36:20+44"
I'm trying to use sccanf to split the date/time so I can use it to sync with the time lib.

Example is attached. However:

#include <SoftwareSerial.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) ; // wait until Arduino Serial Monitor opens

  Serial.println("Begin");
  
  char buffer[23];
  
  int yr;
  int mh;
  int dy;
  int hr;
  int mn;
  int sd;

  int results;

  strcpy(buffer,"18/01/28,21:36:20+44");

  Serial.println(buffer);
  results = sscanf(buffer,"%d[^/]/%d[^/]/%d[^/],%d[^:]:%d[^:]:%d[^:]", &yr, &mh, &dy, &hr, &mn, &sd);
  Serial.print("Split occurred: ");
  Serial.println(results);

  Serial.println(yr);
  Serial.println(mn);
  Serial.println(dy);
//
  Serial.println("");
//
  Serial.println(hr);
  Serial.println(mn);
  Serial.println(sd);

}

void loop() {
  // put your main code here, to run repeatedly:

}

Output

Begin
18/01/28,21:36:20+44
Split occurred: 1
18
36
14386

21
36

I'm certain its in the modifiers I'm using in sscanf's string, but from what I can tell this is correct
%d - Get int
[^/] - Search until /

What am I missing?

sscanf_issue.ino (768 Bytes)

I am 99% sure that sscanf() is not used to split string.

Look at strtok() to split string.

I hope i'm correct in saying this, but: sscanf manual

Couple of issues. It looks like the single '/' characters are causing problems. You've also mixed up mh & mn, illustrating nicely how longer variable names help. Try this:

#include <SoftwareSerial.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) ; // wait until Arduino Serial Monitor opens

  Serial.println("Begin");

  char buffer[23];

  int yr;
  int mh;
  int dy;
  int hr;
  int mn;
  int sd;

  int results;

  strcpy(buffer, "18//01//28,21:36:20+44");

  Serial.println(buffer);
  results = sscanf(buffer, "%d//%d//%d,%d:%d:%d", &yr, &mn, &dy, &hr, &mh, &sd);
  Serial.print("Split occurred: ");
  Serial.println(results);

  Serial.println(yr);
  Serial.println(mn);
  Serial.println(dy);
  //
  Serial.println("");
  //
  Serial.println(hr);
  Serial.println(mh);
  Serial.println(sd);

}

void loop() {
  // put your main code here, to run repeatedly:

}
%d[^/]/%d[^/]/%d[^/],

The ^/ before the , should be ^, I guess

Nope :frowning:

  results = sscanf(buffer,"%d//%d//%d,%d:%d:%d", &yr, &mh, &dy, &hr, &mn,

Well yes about the mix up with mh and mn - fixed that - getting tired.

This only creates one split...

Begin
18/01/28,21:36:20+44
Split occurred: 1
18
0
0

0
0
0

You aren't "splitting" a string, you are interpreting a string of characters and returning those interpreted values to variables.

The result of 1 indicates that only the first variable (yr=18) was returned before a format error was encountered.

The construction // is wrong: there are no "escape characters" in sccanf.

#include <SoftwareSerial.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) ; // wait until Arduino Serial Monitor opens

  Serial.println("Begin");

  char buffer[23];

  int yr;
  int mh;
  int dy;
  int hr;
  int mn;
  int sd;

  int results;

  strcpy(buffer, "18/01/28,21:36:20+44");

  Serial.println(buffer);
  results = sscanf(buffer, "%d/%d/%d,%d:%d:%d", &yr, &mn, &dy, &hr, &mh, &sd);
  Serial.print("variables returned: ");
  Serial.println(results);

  Serial.println(yr);
  Serial.println(mn);
  Serial.println(dy);
  //
  Serial.println("");
  //
  Serial.println(hr);
  Serial.println(mh);
  Serial.println(sd);

}

void loop() {
  // put your main code here, to run repeatedly:

}

Thankyou, that makes a huge difference. Allthough I thought I had tried that earlier on. And turns out I had, but it didn't work on fona.get time.

 //
  // fona.getTime fills f_buffer with 23 bytes of chars
 fona.getTime(f_buffer, 23);  // make sure replybuffer is at least 23 bytes!
 // This is used in our example above
 strcpy(f_buffer,"18/01/29,05:36:49+44");

Both serial.println the same. but the fona example returns 0 matches.
THAT has me totally lost..

Does'ntstrcpy(f_buffer,"18/01/29,05:36:49+44");overwrite whatfona.getTime(f_buffer, 23);placed in f_buffer?

Jacques

Sorry, I should have been more clear.

In my example (Attached) this string works:

  results = sscanf(buffer,"%d/%d/%d,%d:%d:%d", &yr, &mh, &dy, &hr, &mn, &sd);

OUTPUT:

Begin
18/01/28,21:36:20+44
variables returned: 6
28
1
18

21
36
20

But in the below code (My Actual program), it does not:

void syncDate() {
  // Sync the date from the FONA
  // read the time
  // Time = "18/01/28,21:36:20+44"

  char buffer[23];
  fona.getTime(buffer, 23);  // make sure replybuffer is at least 23 bytes!
  
  int yr = 0;
  int mh = 0;
  int dy = 0;
  int hr = 0;
  int mn = 0;
  int sd = 0;

  int results = 0;
  
  results = sscanf(buffer,"%d/%d/%d,%d:%d:%d", &yr, &mh, &dy, &hr, &mn, &sd);
  
  Serial.print("variables returned: ");
  Serial.println(results);

  Serial.println(yr);
  Serial.println(mh);
  Serial.println(hr);
  Serial.println(mn);
  Serial.println(sd);
  
  setTime(hr, mn, sd, dy, mh, yr);
  if(timeStatus()!= timeSet) {
    Serial.println("Unable to sync with the RTC");
  }else{
    Serial.println("RTC has set the system time");
  }
}
variables returned: 0
0
0
0
0
0
RTC has set the system time
Date: 0:0 31/12/1999

The only major difference is that one is coming from "fona.getTime" and the other from "strcpy".
Both are char arrays of 23 chars. Both are in the same format...
All variables are declared and initialised., but one matches 6 times, the other none.
Neither fona.getTime or strcpy can be passed by reference (I don't believe) so I don't think its that either.

I'm lost.

Cheers Guys.

sscanf_issue.ino (772 Bytes)

add some more debug like a print statement to see what buffer looks like when you print it.

  char buffer[23];
  fona.getTime(buffer, 23);  // make sure replybuffer is at least 23 bytes!

  Serial.println(buffer);
"18/01/29,23:10:59+44"
variables returned: 0
0
0
0
0
0
RTC has set the system time

Sorry, that was taken out because I have confirmed that's not the issue

Does fona.GetTime return "18/01/29,23:10:59+44" or 18/01/29,23:10:59+44? Since you say that you need 23 characters to store it, I suspect the former. Your sscanf pattern has nothing in it to account for the leading double quote. Try passing sscanf &buffer[1].

wildbill:
Does fona.GetTime return "18/01/29,23:10:59+44" or 18/01/29,23:10:59+44?

I think no quotes... but it does return success...

boolean Adafruit_FONA::getTime(char *buff, uint16_t maxlen) {
  getReply(F("AT+CCLK?"), (uint16_t) 10000);
  if (strncmp(replybuffer, "+CCLK: ", 7) != 0)
    return false;

  char *p = replybuffer+7;
  uint16_t lentocopy = min(maxlen-1, strlen(p));
  strncpy(buff, p, lentocopy+1);
  buff[lentocopy] = 0;

  readline(); // eat OK

  return true;
}

maybe try:

if (fona.getTime(buffer, 23))  // check for response...
{
  // do your parsing
}

I wouldn't really expect quotes, but if the results in reply #11 are literally what the Arduino produced then they're there.

That is a very good point. I will have to test and get back to you. I'm not 100% sure, but I believe without quotes.

I am trying to understand sscanf...

results = sscanf(buffer,"%d/%d/%d,%d:%d:%d", &dy, &mh, &yr, &hr, &mn, &sd);

Serial.print("Split occurred: ");
Serial.println(results);

Serial.println(dy);
Serial.println(mn);
Serial.println(yr);
//
Serial.println("");
//
Serial.println(hr);
Serial.println(mn);
Serial.println(sd);

delivers this result:
Begin
30/01/19,21:36:20+44
Split occurred: 6
30
36
19

21
36
20

Month is filled with min (36), anyone ideas? :slight_smile:

You have used mh to store month, but printed mn (minutes) twice.