If you can assume a maximum length for the strings to parse from rx_buffer, sscanf() is a simple an effective solution.
If rx_buffer can have an arbitrary length, you could parse it using library functions, such as strtod(), strtol(), strspn(), strcspn() and strndup():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct context {
float a;
int b;
char *string1;
int c;
char *string2;
};
// return the number of fields parsed
int parse_response(struct context *cp, const char *rx_buffer) {
//sscanf(rx_buffer, "%f %d %s %d %s", &a, &b, string1, &c, string2);
const char *src = rx_buffer;
char *p;
size_t n;
cp->a = strtod(src, &p);
if (p == src)
return 0;
cp->b = strtol(src = p, &p, 10);
if (p == src)
return 1;
src = p + strspn(p, " \t\r\n\f\v");
n = strcspn(src, " \t\r\n\f\v");
if (n == 0)
return 2;
if ((cp->string1 = strndup(src, n)) == NULL)
return -1;
src += n;
src += strspn(src, " \t\r\n\f\v");
cp->c = strtol(src, &p, 10);
if (p == src)
return 3;
src = p + strspn(p, " \t\r\n\f\v");
n = strcspn(src, " \t\r\n\f\v");
if (n == 0)
return 4;
if ((cp->string2 = strndup(src, n)) == NULL)
return -1;
return 5;
}
This is obviously neither simple nor nice.
If your target is a linux system with the GNU libc, you could use an extension of their sscanf() implementation: the m prefix between % and s provides a simple, nice and effective solution:
#include <stdio.h>
// return the number of fields parsed
int parse_response(const char *rx_buffer) {
float a;
int b, c;
char *string1 = NULL, *string2 = NULL;
int n = sscanf(rx_buffer, "%f %d %ms %d %ms", &a, &b, &string1, &c, &string2);
if (n == 5) {
// all fields parsed correctly, handle values
...
}
free(string1);
free(string2);
return n;
}
strtod,strtol, andstrchr.