如果您可以假设从rx_buffer 解析的字符串的最大长度,sscanf() 是一个简单有效的解决方案。
如果rx_buffer可以有任意长度,您可以使用库函数解析它,例如strtod()、strtol()、strspn()、strcspn()和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;
}
这显然既不简单也不好看。
如果您的目标是带有 GNU libc 的 linux 系统,您可以使用他们的 sscanf() 实现的扩展:m 前缀在 % 和 s 之间提供了一个简单、漂亮和有效的解决方案:
#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;
}