Есть ли эквивалент TryParse в C ++ (gcc)? - PullRequest
1 голос
/ 26 декабря 2011

Есть ли эквивалент TryParse в C ++ (gcc)?

Я хотел бы проанализировать строку, которая может содержать (+31321), и сохранить ее как долго.Я знаю, что номера телефонов хранятся в виде строк и совпадают строки, но для своих нужд я хотел бы хранить их как можно дольше, и иногда они могут содержать плюсы (+).Что бы разобрать это в C ++?

Ответы [ 4 ]

3 голосов
/ 26 декабря 2011

Проблема с strtoul () и семьей - нет реального способа проверить на неудачу.
Если он не может выполнить синтаксический анализ, он возвращает 0 без установки errno (который устанавливается только при переполнении).

усиление лексического каста

#include <boost/lexical_cast.hpp>


int main()
{
    try
    {
        long x = boost::lexical_cast<long>("+1234");
        std::cout << "X is " << x << "\n";
    }
    catch(...)
    {
        std::cout << "Failed\n";
    }
}

Делаем это используя потоки

int main()
{
    try
    {
        std::stringstream stream("+1234");
        long x;
        char test;

        if ((!(stream >> x)) || (stream >> test))
        {
            // You should test that the stream into x worked.
            // You should also test that there is nothing left in the stream
            //    Above: if (stream >> test) is good then there was content left after the long
            //           This is an indication that the value you were parsing is not a number.
            throw std::runtime_error("Failed");
        }
        std::cout << "X is " << x << "\n";
    }
    catch(...)
    {
        std::cout << "Failed\n";
    }
}

Использование scanf:

int main()
{
    try
    {
        char integer[] = "+1234";
        long x;
        int  len;

        if (sscanf(integer, "%ld%n", &x, &len) != 1 || (len != strlen(integer)))
        {
            // Check the scanf worked.
            // Also check the scanf() read everything from the string.
            // If there was anything left it indicates a failure.
            throw std::runtime_error("Failed");
        }
        std::cout << "X is " << x << "\n";
    }
    catch(...)
    {
        std::cout << "Failed\n";
    }
}
2 голосов
/ 26 декабря 2011

На самом деле, перед тем, как преобразовать строку в число, числа должны быть "нормализованы" в общем формате. Это требует удаления всех символов и замены их соответствующим представлением.

Но вы должны быть очень внимательны при представлении телефонных номеров (которые НЕ являются числами: они не подвергаются обычной арифметике) в виде строки: числа, начинающиеся с одного или нескольких нулей, не совпадают с теми, у которых удалены нули:

00 является типичной заменой +, но перед номером 00 (или +) должен стоять префикс 00c, где c - код страны.

Вам необходимо выполнить некоторую предварительную обработку, чтобы прийти к единообразному строковому представлению перед преобразованием, в противном случае вы рискуете "псевдонимом" разных вещей.

2 голосов
/ 26 декабря 2011

+31321 может быть проанализировано как long с обычными операторами извлечения потока.

#include <iostream>
#include <sstream>
int main()
{
    std::istringstream s("+31321");
    long n;
    s >> n;
    std::cout << n << '\n';
}

демо: http://ideone.com/4rmlp

Хотя анализ фактического номера телефона (с круглыми скобками, тире, добавочными номерами и т. Д.) Может быть не таким простым.

1 голос
/ 26 декабря 2011

оператор извлечения ввода >> (я надеюсь, это приемлемое имя) применяется и возвращает поток &, который имеет оператор bool, что означает, что извлечение было успешно предпринято.Например, из ответа Cubbi:

...
    std::istringstream s("+31321");
    long n;
    if (s >> n)
      std::cout << n << '\n';
....

Это, конечно, будет успешно выполнено, учитывая соответствующее содержание s.

Несколько иное (проще, но не безопасный тип) также семейство scanfимеет практические инструменты, доступные в c ++, а также c.Конечно, вы могли бы написать пример следующим образом:

...
    long n;
    if (sscanf("+31321", "%d", &n) == 1)
      std::cout << n << '\n';
...

Подмножество регулярных выражений делает это довольно мощным: например, для сопоставления разделенных запятой мультиполей с усечением левого пробела:

   if (sscanf("a,b,c", " [^,], [^,], [^,]", a,b,c) == 3) ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...