Это улучшение ответа Роба , потому что это правильный ответ (и я разочарован, что он не был принят).
Вам нужно изменить массив, на который ctype
смотрит, чтобы решить, что такое разделитель.
В простейшем случае вы можете создать свой собственный:
const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};
На моей машине '\n'
равно 10. Я установил для этого элемента массива значение разделителя: ctype_base::space
. ctype
, инициализированный foo
, будет разделять только '\n'
, а не ' '
или '\t'
.
.
Теперь это проблема, потому что массив, переданный в ctype
, определяет больше, чем просто разделитель, он также определяет буквы, числа, символы и некоторый другой мусор, необходимый для потоковой передачи. ( Ben Voigt * ответ 1022 * касается этого.) Поэтому мы действительно хотим изменить a mask
, а не создавать его с нуля.
Это можно сделать так:
const auto temp = ctype<char>::classic_table();
vector<ctype<char>::mask> bar(temp, temp + ctype<char>::table_size);
bar[' '] ^= ctype_base::space;
bar['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
bar[':'] |= ctype_base::space;
A ctype
, инициализированный bar
, будет разделять на '\n'
и ':'
, но не ' '
или '\t'
.
Вы собираетесь настроить cin
или любой другой istream
, чтобы использовать свой пользовательский ctype
, например:
cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));
Вы также можете переключаться между ctype
с, и поведение изменится в середине потока:
cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));
Если вам нужно вернуться к поведению по умолчанию, просто сделайте это:
cin.imbue(locale(cin.getloc(), new ctype<char>));
Живой пример