Во-первых, обратите внимание, что std::toupper
имеет неопределенное поведение, если оно обслуживается отрицательным значением, отличным от EOF
.И с большинством компиляторов char
является типом со знаком по умолчанию.На типичном 8-битном байтовом компьютере это означает, что если c
имеет значение, не входящее в диапазон ASCII (от 0 до 127), то оно будет отрицательным, и вы получите UB.
Простое решение что проблема заключается в приведении аргумента к unsigned char
:
auto to_upper( const char c )
-> char
{
using Byte = unsigned char;
return static_cast<char>( toupper( static_cast<Byte>( c ) );
}
Тем не менее эта функция по умолчанию будет работать только для символов ASCII, букв от A до Z, поскольку она предполагает указанную кодировкупо языку уровня C, и это "C"
по умолчанию, по существу, ограничено ASCII.Но, по крайней мере, это позволяет избежать неопределенного поведения.Итак, давайте притворимся, что ваш пример использует это,
for( auto& c : str ) c = to_upper( c );
Это основанный на диапазоне for
цикл , и он проходит через все элементы в str
, связывая ссылку c
для каждого элемента и выполнения тела цикла с этой привязкой в силу.Поскольку элементы str
относятся к типу char
, auto
будет выводиться как char
.Таким образом, это то же самое, что и запись for( char& c : str ) ...
.
. Таким образом, по умолчанию он прописывает все символы ASCII в str
.
В Windows, если языковой стандарт C был установлен с помощью setlocale( LC_ALL, "" )
,предполагаемой кодировкой будет Windows ANSI, и если str
содержит символы с этой кодировкой, to_upper
выполнит свою работу в верхнем регистре правильно.Это означает, что в Windows его можно использовать, например, в верхнем регистре норвежской строки, такой как "Blåbærsyltetøy"
, при условии, что в Windows используется локаль Windows ANSI Western.
В * nix это не помогаетвызовите setlocale
, потому что родной язык пользователя будет определять кодировку UTF-8, где каждый символ вне ASCII представлен в виде двух или более байтов> 127.