C++ C++;sscanf焊缝未按预期工作

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

我目前正在和Arduino Uno一起为学校做项目,遇到了C sscanf功能的问题。下面的代码正在解析通过串行接口发送到Arduino的字符数组。每个数据块用空格分隔。我还检查了有关Stackoverflow的类似问题,但没有发现任何有用的信息

    char testInput[] = "t 1 3 65 1";

    int registerIndex;
    int locoAddr;
    int locoSpeed;
    int locoDirection;

   if(sscanf(testInput, "t %d %d %d %d", &registerIndex, &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:为了更好地理解草图的复杂性,这可能有助于更好地理解代码:

  • .ino文件中的循环调用static Commander::process()
  • 指挥官::_readLine(…);被调用并从串口读取数据
  • 还进行了一些验证,但在这种情况下应该无关紧要
  • 指挥官::parseCommand(command);使用命令调用
  • 寄存器->设置油门(命令);当命令以“t”开头时调用。寄存器是易变的,所以我可以在中断时调用它
  • 在PackageRegisterList::setThrottle中,是位于的sscanf方法

  • 我通常使用从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