当数据行具有不同的有效格式时,如何在C ++中使用sscanf?

时间:2013-12-22 19:14:16

标签: c++ scanf

如何以这种格式sscanf字符串:name id str1 num1 str2 num2

注意:

  • 如果str1 =“NO”,则num1具有值
  • 如果str1 =“YES”,则num1没有值

实施例1:Ali 1 NO 200 NO 100

示例2:Ali 1 YES NO 100

char name [10];
char str1 [4];
char str2 [4];
int id, num1, num2;

 sscanf(inputString, "%s %d %s %d %s %d",
                            name,  &id, str1, &num1, str2, &num2 );

当str1 =“YES”时,我遇到str2没有采用正确值的问题!!

4 个答案:

答案 0 :(得分:4)

更改为:

char str1 [4];
char str2 [4];

允许3个字符加上NULL终止符。

答案 1 :(得分:3)

示例2具有与示例1不同的格式,并且出现问题。您可以将sscanf分成两部分,并检查str1是否为是。

答案 2 :(得分:3)

在读入字符数组时,您应始终指定可用空间量!读入字符数组的默认行为是强加任何限制。这显然是错误的默认值,因为它使缓冲区溢出非常类似。

此外,在阅读数据时,您应始终验证读取操作是否实际成功:您的第二行与您正在阅读的格式不匹配!在YES之后,根据格式预期整数。也就是说,你想要

if (6 == sscanf(inputString, "%10s %d %3s %d %3s %d",
                name, &id, str1, num1, str2, num2)) {
    // process the input upon success
}

我个人当然会使用std::istringstream

if (std::istringstream(inputString) >> std::setw(10) >> name >> id
        >> std::setw(3) >> str1 >> num1 >> std::setw(3) >> str2 >> num2) {
    // process the input upon success
}

要处理可选值,创建合适的conditional类型并创建合适的输入运算符将非常容易,例如:

template <int Size>
struct conditional_t {
    char* buffer;
    int*  value;
    conditional_t(char* buffer, int& value): buffer(buffer), value(&value) {}
};
template <int Size>
conditional_t<Size> conditional(char (&buffer)[Size], int& value) {
    return conditional_t<Size>(buffer, value);
}
template <int Size>
std::istream& operator>> (std::istream& in, conditional_t<Size> value) {
    if (in >> std::setw(Size) >> value.buffer && !strcmp(buffer, "NO")) {
        in >> *value.value;
    }
    return in;
}

// ...
if (std::istringstream(inputStream) >> std::skipws >> conditional(name, id)
        >> conditional(str1, num1) >> conditional(str2, num2)) {
    // ...
}

我认为这很好。

答案 3 :(得分:2)

只需拨打sscanf(),您就无法可靠地完成工作。您必须适应第三列中的值。因此,您需要执行以下操作:

char name [10];
char str1 [4];
char str2 [4];
int id, num1, num2;
int offset;

// %n conversion specifications do not count towards the return value
if (sscanf(inputString, "%9s %d %3s %n", name, &id, str1, &offset) != 3)
    ...report problem...
else
{
    if (strcmp(str1, "YES") == 0)
    {
        num1 = 0;  // Or other appropriate value
        if (sscanf(inputString+offset, "%3s %d", &str2, &num2) != 2)
            ...report problem...
    }
    else
    {
        if (sscanf(inputString+offset, "%d %3s %d", &num1, &str2, &num2) != 3)
            ...report problem...
    }
}

%n转换报告字符串中出现的偏移量。它不计入sscanf()的返回值。

你说你有很多变种需要处理。也许您的输入格式设计不合理,或者您需要一个更复杂的系统来识别数据的不同格式以及适用的格式。