Широкая версия _memccpy - PullRequest
2 голосов
/ 13 марта 2020

Я должен объединить широкие строки в стиле C, и, исходя из моих исследований, кажется, что что-то вроде _memccpy является наиболее идеальным (во избежание проблема Шлемиеля ). Но я не могу найти версию с широким характером. Существует ли что-то подобное?

1 Ответ

3 голосов
/ 13 марта 2020

Существует ли нечто подобное?

Стандартная библиотека C не содержит широкоформатную версию Microsoft _memccpy(). Кроме того, он не содержит _memccpy(), хотя POSIX определяет функцию memccpy(), для которой MS 10101 * моделируется.

POSIX также определяет wcpcpy() (широкая версия stpcpy()), который копирует широкую строку и возвращает указатель на конец результата. Это не так полнофункционально, как memccpy(), но этого будет достаточно, чтобы избежать проблемы Шлемеля, если только библиотека Microsoft C предоставит версию.

Однако вы можете использовать swprintf() для объединения широких строк, не страдая от проблемы Шлемеля, с дополнительным преимуществом, что это равно в стандартной библиотеке, начиная с C99. Он не обеспечивает поведение остановки memccpy после копирования указанного пользователем (широкого) символа, но возвращает количество записанных широких символов, что эквивалентно возвращению указателя на конец результата. Кроме того, он может напрямую объединять произвольное фиксированное количество строк в одном вызове. swprintf имеет значительные накладные расходы, однако.

Но, конечно, если накладные расходы на swprintf отталкивают вас, написать свой собственный довольно легко. Результат может быть не таким эффективным, как хорошо отлаженная реализация от поставщика библиотеки, но мы говорим о проблеме масштабирования, поэтому вам в основном нужно побеждать на уровне сложности асимптотики c. Простой пример:

/*
 * Copies at most 'count' wide characters from 'src' to 'dest', stopping after
 * copying a wide character with value 0 if that happens first. If no 0 is
 * encountered in the first 'count' wide characters of 'src' then the result
 * will be unterminated.
 * Returns 'dest' + n, where n is the number of non-zero wide characters copied to 'dest'.
 */
wchar_t *wcpncpy(wchar_t *dest, const wchar_t *src, size_t count) {
    for (wchar_t *bound = dest + count; dest < bound; ) {
        if ((*dest++ = *src++) == 0) return dest - 1;
    }
    return dest;
}
...