C++ C++;sscanf焊缝未按预期工作
我目前正在和Arduino Uno一起为学校做项目,遇到了C sscanf功能的问题。下面的代码正在解析通过串行接口发送到Arduino的字符数组。每个数据块用空格分隔。我还检查了有关Stackoverflow的类似问题,但没有发现任何有用的信息C++ C++;sscanf焊缝未按预期工作,c++,arduino,arduino-c++,C++,Arduino,Arduino C++,我目前正在和Arduino Uno一起为学校做项目,遇到了C sscanf功能的问题。下面的代码正在解析通过串行接口发送到Arduino的字符数组。每个数据块用空格分隔。我还检查了有关Stackoverflow的类似问题,但没有发现任何有用的信息 char testInput[] = "t 1 3 65 1"; int registerIndex; int locoAddr; int locoSpeed; int locoDirect
char testInput[] = "t 1 3 65 1";
int registerIndex;
int locoAddr;
int locoSpeed;
int locoDirection;
if(sscanf(testInput, "t %d %d %d %d", ®isterIndex, &locoAddr, &locoSpeed, &locoDirection) != 4) {
return;
}
// print for demo:
Serial.print(registerIndex);
Serial.print(": ");
Serial.print("loco:");
Serial.print(locoAddr);
Serial.print(" speed:");
Serial.print(locoSpeed);
Serial.print(" direction:");
Serial.println(locoDirection);
// expected output: "1: loco:3 speed:65 direction:1"
// output: "-18248: loco:-18248 speed:-18248 direction:-18248"
sscanf函数返回预期的整数4,但不使用值填充变量,因此只打印默认值
我不知道这是什么问题。也许互联网上的某个人有一个解决方案
编辑1:为了更好地理解草图的复杂性,这可能有助于更好地理解代码:
我通常使用从Linux内核偷来的这个版本:
int ASCII_vsscanf(const char * buf, const char * fmt, va_list args)
{
const char *str = buf;
char *next;
char digit;
int num = 0;
int qualifier;
int base;
int field_width;
int is_sign = 0;
while(*fmt && *str) {
/* skip any white space in format */
/* white space in format matchs any amount of
* white space, including none, in the input.
*/
if (isspace(*fmt)) {
while (isspace(*fmt))
++fmt;
while (isspace(*str))
++str;
}
/* anything that is not a conversion must match exactly */
if (*fmt != '%' && *fmt) {
if (*fmt++ != *str++)
break;
continue;
}
if (!*fmt)
break;
++fmt;
/* skip this conversion.
* advance both strings to next white space
*/
if (*fmt == '*') {
while (!isspace(*fmt) && *fmt)
fmt++;
while (!isspace(*str) && *str)
str++;
continue;
}
/* get field width */
field_width = -1;
if (isdigit(*fmt))
field_width = skip_atoi(&fmt);
/* get conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
*fmt == 'Z' || *fmt == 'z') {
qualifier = *fmt++;
if (unlikely(qualifier == *fmt)) {
if (qualifier == 'h') {
qualifier = 'H';
fmt++;
} else if (qualifier == 'l') {
qualifier = 'L';
fmt++;
}
}
}
base = 10;
is_sign = 0;
if (!*fmt || !*str)
break;
switch(*fmt++) {
case 'c':
{
char *s = (char *) va_arg(args,char*);
if (field_width == -1)
field_width = 1;
do {
*s++ = *str++;
} while (--field_width > 0 && *str);
num++;
}
continue;
case 's':
{
char *s = (char *) va_arg(args, char *);
if(field_width == -1)
field_width = INT_MAX;
/* first, skip leading white space in buffer */
while (isspace(*str))
str++;
/* now copy until next white space */
while (*str && !isspace(*str) && field_width--) {
*s++ = *str++;
}
*s = '\0';
num++;
}
continue;
case 'n':
/* return number of characters read so far */
{
int *i = (int *)va_arg(args,int*);
*i = str - buf;
}
continue;
case 'o':
base = 8;
break;
case 'x':
case 'X':
base = 16;
break;
case 'i':
base = 0;
case 'd':
is_sign = 1;
case 'u':
break;
case '%':
/* looking for '%' in str */
if (*str++ != '%')
return num;
continue;
default:
/* invalid format; stop here */
return num;
}
/* have some sort of integer conversion.
* first, skip white space in buffer.
*/
while (isspace(*str))
str++;
digit = *str;
if (is_sign && digit == '-')
digit = *(str + 1);
if (!digit
|| (base == 16 && !isxdigit(digit))
|| (base == 10 && !isdigit(digit))
|| (base == 8 && (!isdigit(digit) || digit > '7'))
|| (base == 0 && !isdigit(digit)))
break;
switch(qualifier) {
case 'H': /* that's 'hh' in format */
if (is_sign) {
signed char *s = (signed char *) va_arg(args,signed char *);
*s = (signed char) ASCII_simple_strtol(str,&next,base);
} else {
unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
*s = (unsigned char) ASCII_simple_strtoul(str, &next, base);
}
break;
case 'h':
if (is_sign) {
short *s = (short *) va_arg(args,short *);
*s = (short) ASCII_simple_strtol(str,&next,base);
} else {
unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
*s = (unsigned short) ASCII_simple_strtoul(str, &next, base);
}
break;
case 'l':
if (is_sign) {
long *l = (long *) va_arg(args,long *);
*l = ASCII_simple_strtol(str,&next,base);
} else {
unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
*l = ASCII_simple_strtoul(str,&next,base);
}
break;
case 'L':
if (is_sign) {
long long *l = (long long*) va_arg(args,long long *);
*l = ASCII_simple_strtoll(str,&next,base);
} else {
unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
*l = ASCII_simple_strtoull(str,&next,base);
}
break;
case 'Z':
case 'z':
{
size_t *s = (size_t*) va_arg(args,size_t*);
*s = (size_t) ASCII_simple_strtoul(str,&next,base);
}
break;
default:
if (is_sign) {
int *i = (int *) va_arg(args, int*);
*i = (int) ASCII_simple_strtol(str,&next,base);
} else {
unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
*i = (unsigned int) ASCII_simple_strtoul(str,&next,base);
}
break;
}
num++;
if (!next)
break;
str = next;
}
return num;
}
有限但对我来说足够小和好。“每个数据块都用空格隔开。”尝试在格式规范的边缘放一个空格,因为
“t%d%d%d%d”
。无法通过将代码段复制到C程序中来进行复制,该程序使用fprintf
@WeatherVane输出提供的代码示例不起作用。提供的输入的第一个字符是“t”,后跟空格。在switch语句中使用了“t”来确定在调用sscanf之前它是什么类型的输入。请不要责怪Arduino。99.9999%的人拥有代码或理解。由于Serial.print
被重载,可以使用char*
或int
参数,这显然与C无关。应该删除C标记。C++是一种不同的语言。请停止在C++
主题中使用名称C
。