C ++控制台:解析METAR数据

时间:2018-08-10 09:46:47

标签: c++ console dev-c++

我正在开发我的第一个Web应用程序(天气可视化),该应用程序在后端需要一些轻量级的c ++。我使用wget下载原始文本,并使用c ++控制台解析数据,然后编写HTML。到目前为止效果很好。

METAR基本上是来自气象站的原始天气数据。 (时间,日期,条件,温度等)。我目前正在使用的是:

2018/08/10 08:09
KBAZ 100809Z AUTO 00000KT 10SM BKN012 26/23 A3002 RMK AO2 T02610233

我已经能够将每组数据存储到不同的变量中。我要解决的问题是上面的“ 26/23”,它是摄氏温度和露点。

到目前为止,我有一个名为tempAndDewpoint的字符串,其中存储了“ 26/23” ...我正在使用substr(0,2)返回名为温度的新字符串中的正温度。 (因为第一个数字是温度)。效果很好。

我的问题是,如果温度低于10,例如9,会发生什么?我再也不能使用substring(0,2)了,因为那会返回“ 9 /”作为当前温度。

我希望能找到一些指导,对于我来说,复制不太复杂。我什至不知道该问题的名字,因为我不确定这个问题的名字。当然一定很常见吗?

2 个答案:

答案 0 :(得分:1)

当心:METAR中的负温度以M为前缀。因此,这是有效的温度组:5 / M2或M8 / M12(负露点实际上是结冰点)。所以我不会在这里使用自定义解析器:

struct TTD {
    short int t;
    short int td;

    bool parse(const char *tempAndDewpoint) {
        const char *next;
        t = parse_partial(tempAndDewpoint, &next);
        if (*next != '/') return false;
        td = parse_partial(next + 1, &next);
        return (*next == '\0');
    }

private:
    static short int parse_partial(const char *beg, const char **next) {
        bool neg = false;
        short int val = 0;
        if (*beg == 'M') {
            neg = true;
            beg += 1;
        }
        while (*beg >= '0' && *beg <= '9') {
            val = val * 10 + (*beg -  '0');
            beg += 1;
        }
        *next = beg;
        if (neg) val = -val;
        return val;
    }

};

答案 1 :(得分:0)

简单的解决方案是根本不存储为字符串。将字符串分成两个独立的数字。如另一个答案中所述,您确实需要注意“ M”是负数的前缀,但没有读取内容来手工解析数字:

int parseNum(const std::string& str)
{
    size_t pos;
    int num;
    if (!str.empty() && str.front() == 'M')
    {
        num = -std::stoi(str.substr(1), &pos);
        if (pos != str.size() - 1)
        {
          throw std::invalid_argument("invalid input");
        }
    }
    else
    {
        num = std::stoi(str, &pos);
        if (pos != str.size())
        {
          throw std::invalid_argument("invalid input");
        }
    }
    return num;
}

size_t slash = tempAndDewpoint.find("/");
if (slash == std::string::npos)
{
  throw std::invalid_argument("invalid input");
}
int temp = parseNum(tempAndDewpoint.substr(0, slash));
int dew = parseNum(tempAndDewpoint.substr(slash + 1));