Sscanf проблема? - PullRequest
       10

Sscanf проблема?

0 голосов
/ 11 марта 2011
long ip2long( char *ip )
{
    long ip2long = 0;

    char B1[4], B2[4], B3[4], B4[4];
    int D1, D2, D3, D4 = 0;

    sscanf(ip, "%s.%s.%s.%s", B1, B2, B3, B4);

    D1 = atoi(B1);
    D2 = atoi(B2);
    D3 = atoi(B3);
    D4 = atoi(B4);

    if(D1 > 255 || D2  > 255 || D3 > 255 || D4 > 255)
        return 0;

    ip2long = D1*256*256*256+D2*256*256+D3*256+D4;

    return ip2long;
}

входные данные: 127.1.1.2

Почему D1 == 127, а D2, D3 и D4 == 0?

--- ОБНОВЛЕНИЕ --- Теперь код

unsigned long ip2long( char *ip )
{
    unsigned long ip2long = 0;
    unsigned int D1, D2, D3, D4 = 0;

    sscanf(ip, "%u.%u.%u.%u", &D1, &D2, &D3, &D4);

    if(D1 > 255 || D2  > 255 || D3 > 255 || D4 > 255)
        return 0;

    ip2long = D1*256*256*256+D2*256*256+D3*256+D4;

    return ip2long;
}

Ди в порядке, но есть и другие проблемы: результат для 127.1.1.2 - 2130772226 вместо 2130772225, а для 195.98.157.132 - -1016947324 ... Почему?

--- Обновление 2 --- Вот и все,% d прочитал% u.

Kornel Kisielewicz спасибо за сообщение о функции inet_addr:)

PS извините за мой плохой английский = \

Вопрос закрыт.

Ответы [ 3 ]

7 голосов
/ 11 марта 2011

Как отмечает fizzer, %s потребляет всю строку - в этом случае опасно копируя ее после конца S1.Был бы большой ключ, если бы результат sscanf () сравнивался с 4!Не думайте, что все будет работать, особенно при анализе входных данных извне программы.atoi игнорирует конечный мусор, поэтому даже при строковом формате %[^.], который останавливается через определенный промежуток времени, он будет обрабатывать значения мусора, такие как 192,3.2x.3.1, игнорируя предложения ,3 и x.

fizzer о("...%d...", &D1...) - хорошее начало, но вы все равно должны сравнить результат с 4, иначе некорректные строки, такие как "hello", просто оставят D1, D2, D3 и D4 без изменений.Отрицательные значения будут приняты.Обратите внимание, что только D4 установлен на 0 - другие значения не зависят от конечного значения = 0 в этой строке и могут содержать старые значения мусора из стека, которые могут пройти или не пройти через более позднюю проверку по 255.

В общем:

unsigned long ip2ulong(char *ip)
{
    unsigned u1, u2, u3, u4;
    return sscanf(ip, "%u.%u.%u.%u", &u1, &u2, &u3, &u4) == 4 &&
           u1 <= 255 && u2 <= 255 && u3 <= 255 && u4 <= 255
           ? u1*256*256*256 + u2*256*256 + u3*256 + u4 : 0;
} 
5 голосов
/ 11 марта 2011

% s поведение жадное - оно читает столько, сколько может. Вместо этого вы можете использовать% d для чтения чисел.

Однако есть ли причина, по которой вы не используете функцию inet_addr? Он доступен на POSIX и Windows .

5 голосов
/ 11 марта 2011

Первый% s потребляет весь ввод, затем atoi преобразует только начальные цифры. Вместо этого используйте% d и передайте & D1, & D2 и т. Д. Для соответствующих аргументов.

Затем рассмотрите возможность использования беззнаковых целочисленных значений для Di,% u для преобразования формата и длинных без знака для результата. Длинна может быть всего 32 бита, и результирующие различия знака могут быть удивительными.

...