Parsing strings

I am using an ArduinoBoardEthernet for an application that accepts arbitrary length data over an http POST.
the data is an arbitrary number of 'alarm=minute,hour,dayofweek,day,month,pin,on,duration&...'
where minute (etc) are numbers in their normal range or an X to designate 'any' .
the code I am using parses each alarm (from the post string) fine.
where I am struggling is parsing the comma delimited inner alarm string into its components (which must then be translated in single byte length - the duration is always 120 or below - and then written to EEPROM).
I have tried using sscanf but get garbage. likewise strtok, and even manual iteration.

the latest iteration of the code I am using follows (for completeness I am posting the complete segment)

 if ( 0 == strcmp(value, "sched") ){
       Serial << "processing sched action" << "\n";
       int e = 0;
       int j = 0;
       char minute, hour, day, month, dayOfWeek, pin, on, duration; 
       char *result;
       char *delim = ",";
       do{
         repeat = server.readPOSTparam(name, 6, value, 20);
         if (0 != strcmp (name, "alarm" )) continue;
         Serial << "\nalarm:" << value << "\n"; 
         uint8_t i = 0;
         for(int i = 0; i < 8; i++){
           char buff[4];
           for(j = 0; e<3; e++){
             if (',' == value[ (i*8) + j]) break;
             buff[e] = value[i];    
           }
           Serial << "\n" << buff << "\n";
           switch (i){
             case 0: minute = atoi(buff);break;
             case 1: hour = atoi(buff); break;
             case 2: dayOfWeek = atoi(buff); break;
             case 3: day = atoi(buff); break;
             case 4: month = atoi(buff); break;
             case 5: pin = atoi(buff); break;
             case 6: on = atoi(buff); break;
             case 7: duration = atoi(buff); break;
           }
         }
             
         Serial << "\nWriting alarm: " << minute << ":" << hour << ":" <<dayOfWeek << ":" << day << ":" << month << ":" << pin << ":" << on << ":" << duration << "\n"; 
       
         if(e < 1023){
           EEPROM.write(e, minute);
           e++;
           EEPROM.write(e, hour);
           e++;
           EEPROM.write(e,dayOfWeek);
           e++;
           EEPROM.write(e,day);
           e++;
           EEPROM.write(e,month);
           e++;
           EEPROM.write(e,pin);
           e++;
           EEPROM.write(e,on);
           e++;
           EEPROM.write(e,duration);
           e++;
         }
       }while (repeat && 0 != strcmp(name,"alarm"));
       if(e < 1023){
         EEPROM.write(e,'|');
       }
     }

in the serial console I get the following

processing sched action
duration=2&alarm=15%2CX%2CX%2CX%2CX%2C2%2C1%2C2
alarm:15,X,X,X,X,2,1,2

11)8alarm

11)8alarm

,,,8alarm

XXX8alarm

,,,8alarm

XXX8alarm

,,,8alarm

XXX8alarm

Writing alarm: :::::::

and using this variant (just posting the relevant bits)

sscanf(value, "%d,%d,%d,%d,%d,%d,%d,%d", &minute, &hour, &dayOfWeek, &day, &month, &pin, &on, &duration);
Serial << "\nWriting alarm: " << minute << ":" << hour << ":" <<dayOfWeek << ":" << day << ":" << month << ":" << pin << ":" << on << ":" << duration << "\n";

I get the following output

processing sched action
duration=2&alarm=15%2CX%2CX%2CX%2CX%2C2%2C1%2C2
alarm:15,X,X,X,X,2,1,2

Writing alarm: :::½::::5

so in both cases it seems that the webduino code is capturing the alarm properly and decoding it properly. the alarm: ... line is exactly the representation that I want.

So I guess where I am going wrong is my approach to parsing this csv into bytes for writing to the EEPROM.

Any help with a solution or better approach would be much appreciated.

thanks
Justin

The problem is that you use a wrong data type for minute, hour etc. When you parse the string "15,X...", minute will have a binary value of 15 (hex 0xf) which is some non-printable ascii character.
use uint8_t instead of char. (Int or short should also work).

uint8_t minute, hour, day, month, dayOfWeek, pin, on, duration;

Use some special short value (e.g., 255) for 'any' instead of 'X'. If you fix the data types you should be able to use also the simpler sscanf variant .

(Edit: short => uint8_t)

Thank you for the reply.

declaring the variables as you suggest (using uint8_t) and using sscanf with the following code

if ( 0 == strcmp(value, "sched") ){
       Serial << "processing sched action" << "\n";
       int e = 0;
       int j = 0;
       uint8_t minute, hour, day, month, dayOfWeek, pin, on, duration; 
       char *result;
       char *delim = ",";
       do{
         repeat = server.readPOSTparam(name, 6, value, 30);
         if (0 != strcmp (name, "alarm" )) continue;
         Serial << "\nalarm:" << value << "\n"; 
        
         sscanf(value, "%d,%d,%d,%d,%d,%d,%d,%d", &minute, &hour, &dayOfWeek, &day, &month, &pin, &on, &duration);
         Serial << "\nWriting alarm: " << minute << ":" << hour << ":" << dayOfWeek << ":" << day << ":" << month << ":" << pin << ":" << on << ":" << duration << "\n"; 
       
         if(e < 1023){
           EEPROM.write(e, minute);
           e++;
           EEPROM.write(e, hour);
           e++;
           EEPROM.write(e,dayOfWeek);
           e++;
           EEPROM.write(e,day);
           e++;
           EEPROM.write(e,month);
           e++;
           EEPROM.write(e,pin);
           e++;
           EEPROM.write(e,on);
           e++;
           EEPROM.write(e,duration);
           e++;
         }
       }while (repeat && 0 != strcmp(name,"alarm"));
       if(e < 1023){
         EEPROM.write(e,'|');
       }
     }

I get the following debug output

processing sched action
duration=2&alarm=30%2C255%2C255%2C255%2C255%2C2%2C1%2C2
alarm:30,255,255,255,255,2,1,2

Writing alarm: 30:255:0:255:255:2:1:2

so, this is a big step forward, but something is still odd with the parsing of the third variable. Why might this being interpreted as 0 and not 255?

I'll guess that the format string does not match the data type. "%d" probably expects a 16 bit integer and uint8_t is 8 bits. I'm not sure what is the correct format string in the Arduino for uint8_t. Try to change uint8_t to short or int. It should work as well, although it consumes a few bytes more ram.

Changing to short works. Which I find bizarre given that the value being passed is identical to the previous and following 255 which is correctly parsed by sscanf into the corresponding uint8_t placeholder.
Ram is at a premium for me in this app so if anyone can help with why I need a short for this particular 255 and uint8_t for the others that would e most helpful.
Thank you pekkaa for your help so far.

"%hhd" seems to work for uint8_t.
The bizarre behavior was probably result of overflow in sscanf (using 8bit variables where 16 bit variables where expected).