Используя GlibC, какой аналог _snscanf () из Windows? - PullRequest
1 голос
/ 23 февраля 2012

Я начал просматривать примеры cURL в C. При компиляции ftpuploadresume.c я получаю неопределенную ошибку ссылки:

/* _snscanf() is Win32 specific */
r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);

Я просто хочу знать, что является альтернативой _snscanf для glibc.

Ответы [ 2 ]

3 голосов
/ 23 февраля 2012

Если вы используете строки с нулевым символом в конце, вы можете совершенно безопасно использовать sscanf() без второго аргумента (длины). Вы могли бы и на Windows тоже. Если вы не знаете, что строка завершена нулем, но знаете, как долго это происходит, добавьте терминатор нуля. (Если вы не знаете, какова длина строки и не знаете, завершена ли она нулем, ничто не безопасно!)

Если у вас есть компилятор C99, вы можете автоматически выполнить необходимые изменения:

#define _snscanf(data, length, format, ...) scanf(data, format, __VA_ARGS__)

Осторожно!

Обратите внимание на комментарий от namey & mdash; за что спасибо.

Посмотрите справочные страницы Microsoft по _snscanf(). Примеры не являются убедительными; вы получите те же результаты даже без указания длины. Тем не менее, похоже, что @namey верен в целом. Многое будет зависеть от контекста, в котором оно используется. Если указанный length на самом деле strlen(data), то разница не будет иметь значения. Если указанная длина больше этой, разница, вероятно, не будет иметь значения. Если длина меньше длины данных, разница может иметь большое значение.

Лучшей функцией обложки может быть:

int _snscanf(const char *input, size_t length, const char *format, ...)
{
    char *copy = malloc(length + 1);
    if (copy == 0)
        return 0;
    memmove(copy, input, length);
    copy[length] = '\0';
    va_list args;
    va_start(args, format);
    int rc = vsscanf(copy, format, args);
    va_end(args);
    free(copy);
    return rc;
}
0 голосов
/ 29 апреля 2015

Если вы уверены , что строка, переданная _snscanf, является допустимой строкой с нулевым символом в конце, вы можете просто использовать sscanf (3) с %n например

 int pos = -1;
 int limit = size * nmemb;
 r = sscanf(ptr, "Content-Length: %ld\n%n", &len, &pos);
 if (r>0  &&  pos >= limit) {
    r = 0;  
    len = -1;
 }

Спецификация преобразования %n устанавливает указанное целое число в текущее смещение сканирования.Поэтому мы используем sscanf, он может сканировать за предел, но в этом случае мы отклоняем сканирование (установив r = 0).Конечно, мы должны признать, что len мог быть установлен.

Кстати, мое решение не GNU glibc , оно должно работать с другими POSIX-совместимыми libc-s, такими как MUSL-Libc

...