使用sscanf c++检查格式并获取数字

Check format and get numbers with sscanf c++

本文关键字:获取 数字 格式 检查 sscanf c++ 使用      更新时间:2023-10-16

我需要检查一个字符数组中是否有特定的简单格式,并同时获取其中两个数字的值。消息格式为:开始编号END。我所能想到的就是:

int x,y;
if ( sscanf(buffer, "START %d %d END", &x, &y) != 2) 
    return false;
...
...
...
return true;

但这当然是成功的,即使在结局完全不同之后,因为数字是得到的。最好的方法是什么?谢谢你的建议。

尝试

int x, y;
size_t pos = -1;
char str[4];
if (sscanf(buffer, "START %d %d %3s%zn", &x, &y, str, &pos) != 3 || strcmp(pos, "END") || pos != strlen(buffer)) 
    return false;
//...
return true;

我一直觉得使用sscan()和类似的函数很麻烦。尽管其他解决方案要优雅得多,但我更喜欢基于strtok()的更简单、更易于维护的代码。这里有一个小程序可以进行实验:

#include <cstdio>
#include <cstring>
int main()
{
    char buf[250];
    const char* delimiters=" n";
    while(fgets(buf,250,stdin)!=nullptr){
        // fgets() reads the newline...
        printf("%s",buf);
        // Tokenize the buffer using 'delimiters'.  The nullptr will re-use the same buffer.
        char* pBegin = strtok(buf,delimiters);
        char* pNumb1 = strtok(nullptr,delimiters);
        char* pNumb2 = strtok(nullptr,delimiters);
        char* pEnd   = strtok(nullptr,delimiters);
        // Protect our strcmp from a nullptr(missing data) and do some validity tests.
        if((pEnd!=nullptr)&&(strcmp(pBegin,"BEGIN")==0)&&(strcmp(pEnd,"END")==0)){
            printf("  Begin = '%s'n",pBegin); 
            printf("  Numb1 = '%s'n",pNumb1); 
            printf("  Numb2 = '%s'n",pNumb2); 
            printf("  End   = '%s'n",pEnd); 
        }else{
            printf("  Error!n");
        }
    }
}

以及一些测试数据(末尾有一些空行):

BEGIN 106 635 END
BEGIN 107 636 END
BEGaN 108 637 ENDING
BeGIN 115 644 End
BEGIN 116 645 END
BEGIN 117 646 END of it all
BEgIN 128 657 END
BEGIN 129 658 END
BEGIN 130 659 Finish
131 660 END
BEGIN 662 END
BEGIN 136 665 
BEGIN 136 
BEGIN 

这将是输出。。。

BEGIN 106 635 END
  Begin = 'BEGIN'
  Numb1 = '106'
  Numb2 = '635'
  End   = 'END'
BEGIN 107 636 END
  Begin = 'BEGIN'
  Numb1 = '107'
  Numb2 = '636'
  End   = 'END'
BEGaN 108 637 ENDING
  Error!
BeGIN 115 644 End
  Error!
BEGIN 116 645 END
  Begin = 'BEGIN'
  Numb1 = '116'
  Numb2 = '645'
  End   = 'END'
BEGIN 117 646 END of it all
  Begin = 'BEGIN'
  Numb1 = '117'
  Numb2 = '646'
  End   = 'END'
BEgIN 128 657 END
  Error!
BEGIN 129 658 END
  Begin = 'BEGIN'
  Numb1 = '129'
  Numb2 = '658'
  End   = 'END'
BEGIN 130 659 Finish
  Error!
131 660 END
  Error!
BEGIN 662 END
  Error!
BEGIN 136 665 
  Error!
BEGIN 136 
  Error!
BEGIN 
  Error!
  Error!

在检查了C标准后,我很惊讶没有可移植的方法来检测这一点。

在Linux上设置errno,您也可以使用ferror。在Windows上也设置了errno,但MSDN没有提到ferror


你可以这样做来代替一个混乱但可移植的解决方案:

int x,y;
char d;
if ( sscanf(buffer, "START %d %d EN%c", &x, &y, &d) != 3 || 'D' != d)
    return false;