[SOLVED] Sscanf() not saving sting sections to variables

You can ask if needed. But perhaps you need some basic C++ knowledge first.

I hope you know that I gave a full working example with sscanf() with the fixed 10 parameters and a check if sscanf() was successful and even a link to a simulation where you can see it working with a single click of a button to start the simulation.

So I ran a test program and the sscanf() feature seems to be working but I still cant save strings. The test run is working well when I remove the "device" portion and just deal with integers and floats. I'm using the same method for the string as in the simulation and I cant figure out what im doing wrong

test sketch below:


char message[] = "1,0,0,0,0.000000,0.000000,0.00,-252,14.41,1100.00";
char str2[7];
int id = 0;
int hourRead = 0;
int minRead = 0;
int secRead = 0;
float latRead = 0.0;
float lonRead = 0.0;
float altRead = 0.0;
int sensorRead = 0;
float voltRead = 0.0;
float percRead = 0.0;
float percReadTru = 0.0;

void setup() {

  Serial.begin(115200);

}

void loop() {
  Serial.println(message);
  if(sscanf( message, "%s,%d,%d,%d,%d,%f,%f,%f,%d,%f,%f", str2, &id, &hourRead, &minRead, &secRead, &latRead, &lonRead, &altRead, &sensorRead, &voltRead, &percRead) == 11)
  {
    showData();
  }



  // ----------------------------------------------------------
  // Test sscanf with integer
  // ----------------------------------------------------------
  Serial.print("Can I parse a integer ? ");
  int i;
  if ( sscanf( "91", "%d", &i) == 1)
  {
    Serial.print( "Yes, it is: ");
    Serial.print( i);
  }
  else
  {
    Serial.print( "No");
  }
  Serial.println();


  // ----------------------------------------------------------
  // Test sscanf with float
  // ----------------------------------------------------------
  Serial.print("Can I parse a float ? ");
  float f;
  if ( sscanf( "123.456", "%f", &f) == 1)
  {
    Serial.print( "I don't know, the value is: ");
    Serial.print( f);
  }
  else
  {
    Serial.print( "No");
  }
  Serial.println();



  Serial.print("Can I parse a string ? ");
  char str1[6];
  if ( sscanf( "Sketch", "%s", str1) == 1)
  {
    Serial.print( "yes you can parse a string: ");
    Serial.print( str1);
  }
  else
  {
    Serial.print( "No");
  }
  Serial.println();

}
void showData() {
  Serial.print("  Device: ");
  Serial.println(str2);
 
  Serial.print("  ID: ");
  Serial.println(id);

  Serial.print("  Time: ");
  Serial.print(hourRead);
  Serial.print(":");
  Serial.print(minRead);
  Serial.print(":");
  Serial.println(secRead);

  Serial.print("  Location: ");
  Serial.print(latRead, 6);
  Serial.print(", ");
  Serial.println(lonRead, 6);

  Serial.print("  Altitude: ");
  Serial.println(altRead);

  Serial.print("  Sensor Reading: ");
  Serial.println(sensorRead);

  Serial.print("  Voltage: ");
  Serial.println(voltRead);

  Serial.print("  Battery: ");
  Serial.print(percRead);
  Serial.println("%");
}

this is my output in the serial monitor:

1,0,0,0,0.000000,0.000000,0.00,-252,14.41,1100.00
Can I parse a integer ? Yes, it is: 91
Can I parse a float ? I don't know, the value is: 123.46
Can I parse a string ? yes you can parse a string: Sketch 

I tried it without the string and it works in both this simulation and in actually reading LoRa data.

This is the sketch without the "device" string added in:


char message[] = "1,0,0,0,0.000000,0.000000,0.00,-252,14.41,1100.00";
int id = 0;
int hourRead = 0;
int minRead = 0;
int secRead = 0;
float latRead = 0.0;
float lonRead = 0.0;
float altRead = 0.0;
int sensorRead = 0;
float voltRead = 0.0;
float percRead = 0.0;
float percReadTru = 0.0;

void setup() {

  Serial.begin(115200);

}

void loop() {
  Serial.println(message);
  if(sscanf( message, "%d,%d,%d,%d,%f,%f,%f,%d,%f,%f", &id, &hourRead, &minRead, &secRead, &latRead, &lonRead, &altRead, &sensorRead, &voltRead, &percRead) == 10)
  {
    showData();
  }



  // ----------------------------------------------------------
  // Test sscanf with integer
  // ----------------------------------------------------------
  Serial.print("Can I parse a integer ? ");
  int i;
  if ( sscanf( "91", "%d", &i) == 1)
  {
    Serial.print( "Yes, it is: ");
    Serial.print( i);
  }
  else
  {
    Serial.print( "No");
  }
  Serial.println();


  // ----------------------------------------------------------
  // Test sscanf with float
  // ----------------------------------------------------------
  Serial.print("Can I parse a float ? ");
  float f;
  if ( sscanf( "123.456", "%f", &f) == 1)
  {
    Serial.print( "I don't know, the value is: ");
    Serial.print( f);
  }
  else
  {
    Serial.print( "No");
  }
  Serial.println();



  Serial.print("Can I parse a string ? ");
  char str1[5];
  if ( sscanf( "Sketch", "%s", str1) == 1)
  {
    Serial.print( "yes you can parse a string: ");
    Serial.print( str1);
  }
  else
  {
    Serial.print( "No");
  }
  Serial.println();

}
void showData() {
  Serial.print("  ID: ");
  Serial.println(id);

  Serial.print("  Time: ");
  Serial.print(hourRead);
  Serial.print(":");
  Serial.print(minRead);
  Serial.print(":");
  Serial.println(secRead);

  Serial.print("  Location: ");
  Serial.print(latRead, 6);
  Serial.print(", ");
  Serial.println(lonRead, 6);

  Serial.print("  Altitude: ");
  Serial.println(altRead);

  Serial.print("  Sensor Reading: ");
  Serial.println(sensorRead);

  Serial.print("  Voltage: ");
  Serial.println(voltRead);

  Serial.print("  Battery: ");
  Serial.print(percRead);
  Serial.println("%");
}

and this is the output from the serial monitor:

1,0,0,0,0.000000,0.000000,0.00,-252,14.41,1100.00
  ID: 1
  Time: 0:0:0
  Location: 0.000000, 0.000000
  Altitude: 0.00
  Sensor Reading: -252
  Voltage: 14.41
  Battery: 1100.00%
Can I parse a integer ? Yes, it is: 91
Can I parse a float ? I don't know, the value is: 123.46
Can I parse a string ? yes you can parse a string: Sketch

What do you mean that you can't save strings ?
Can you remove everything else that is not needed.
If you want to read a string before a comma, then there must be something to read.

A zero-terminated string has a byte at the end that is zero.
That means the string "Hi" is three bytes. The string "Sketch" is 7 bytes.
If you make an array for the text "Sketch", then make it 20, 30 or 40 bytes.

Using %s is not what you want, it will read characters until a white space, and you don't have any white space in your message.. Try with %[^,] instead, it will read characters until ,. See scanf - C++ Reference

2 Likes

Thank you @guix I forgot about the limited posibilities of white-space characters.

@currydem23 to make up for forgetting that, I made a working sketch for you.

// A message without CR or LF at the end
char message[] = "Apple,Oak,Silk,1kg,1,0,0,0,0.000000,0.000000,0.00,-252,14.41,1100.00";


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

  char fruit[40] = "";   // initialize as empty string
  char tree[40] = "";
  char fabric[40] = "";
  char weight[40] = "";
  int id = 0;
  int hourRead = 0;
  int minRead = 0;
  int secRead = 0;
  float latRead = 0;
  float lonRead = 0;
  float altRead = 0;
  int sensorRead = 0;
  float voltRead = 0.0;
  float percRead = 0.0;

  if( sscanf( message, "%[^,],%[^,],%[^,],%[^,],%d,%d,%d,%d,%f,%f,%f,%d,%f,%f", fruit, tree, fabric, weight, &id, &hourRead, &minRead, &secRead, &latRead, &lonRead, &altRead, &sensorRead, &voltRead, &percRead) == 14)
  {
    Serial.print("  fruit: ");
    Serial.println( fruit);

    Serial.print("  tree: ");
    Serial.println( tree);

    Serial.print("  fabric: ");
    Serial.println( fabric);

    Serial.print("  weight: ");
    Serial.println( weight);

    Serial.print("  ID: "); 
    Serial.println(id);

    Serial.print("  Time: "); 
    Serial.print(hourRead); 
    Serial.print(":"); 
    Serial.print(minRead); 
    Serial.print(":"); 
    Serial.println(secRead);

    Serial.print("  Location: "); 
    Serial.print(latRead); 
    Serial.print(", "); 
    Serial.println(lonRead);

    Serial.print("  Altitude: "); 
    Serial.println(altRead);

    Serial.print("  Sensor Reading: "); 
    Serial.println(sensorRead);

    Serial.print("  Voltage: "); 
    Serial.println(voltRead);

    Serial.print("  Battery: "); 
    Serial.print(percRead); 
    Serial.println("%");
  }
  else
  {
    Serial.println( "Can not parse");
  }
}

void loop() 
{
}

The sketch in Wokwi: https://wokwi.com/arduino/projects/316158266414465601

1 Like

It's also a good idea to limit the amount of characters to be read, for example if size of str2 is 7, you want to read max 6 characters, with %6[^,]. If there are more than 6 characters to be read, sscanf will fail, instead of writing outside of the array.. :slight_smile:

2 Likes

@Koepel @guix Thank you guys so much, that solved me issue. Also I did make my array 30 bytes.

1 Like