Символы перекрываются, когда они изменили цвет и напечатаны задом наперед
Как вы можете видеть, верхние темные X вырезаны, хотя для них есть место.
Это происходит потому, что они изменили цвет и печатаются в обратном направлении (справа налево).
Это ошибка, неисправный код, плохая настройка в моей системе или (я сомневаюсь в этом), как это должно быть?
Вот код, который генерирует этот вывод:
#include <Windows.h>
#include <iostream>
void moveTo(int x,int y){
COORD kord={x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),kord);
}
void setColor(WORD attributes){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes);
}
void main(){
for(int i=9;i+1;i--)
{
moveTo(i,0);
std::cout.put('X');
}
for(int i=-10;i;i++)
{
moveTo(i+10,1);
std::cout.put('X');
}
setColor(8);
for(int i=9;i+1;i--)
{
moveTo(i,2);
std::cout.put('X');
}
for(int i=-10;i;i++)
{
moveTo(i+10,3);
std::cout.put('X');
}
setColor(7);
for(int i=9;i+1;i--)
{
moveTo(i,4);
std::cout.put('X');
}
for(int i=-10;i;i++)
{
moveTo(i+10,5);
std::cout.put('X');
}
std::cin.get();
}
1 ответ
Это ошибка в Windows.
Как упоминалось в сообщении Hans Passant:
Я тоже репро, VS2008 на Win7. Классный баг. Изменение шрифта консоли исправляет это.
Давайте использовать эту изоляцию от ошибок. Я распознаю этот шрифт как Petite Terminal, что подразумевает, что вы, скорее всего, настроили этот проект как консольное приложение Win32. Дополнительная репродукция с GCC подтверждает эту гипотезу, и мы предположим, с практической точки зрения, что все вы получали 32-битное консольное приложение, работающее внутри терминала Windows.
Возникает вопрос, почему он записывает ровно один дополнительный столбец пикселей в контексте шрифта терминала по умолчанию, цвет 8, и обратно, записывая в буфер экрана консоли.
В частности, давайте разберем эту проблему на составные части:
- Когда выдается запись, символ записывается в местоположение в терминальном массиве.
- Когда выбран цвет по умолчанию (7), пиксели не переполняются в другие буферы в массиве
- Когда выбран цвет 8, дополнительный столбец пикселей записывается в следующую область буфера, которая видна только тогда, когда текст читается в обратном направлении.
Из-за наличия переполнения в (3), это ошибка.
Цитируя Рэймонда Чена:
Модель рендеринга консоли предполагает, что каждый символ аккуратно вписывается в ячейку фиксированного размера. Когда новый символ записывается в ячейку, старая ячейка печатается с новым символом, но если старый символ имеет вылет или подвисание, эти дополнительные пиксели остаются позади, так как они "пролились" на требуемую ячейку и зараженные соседние ячейки. Точно так же, если соседний символ "перетек", эти "побочные пиксели" будут стерты.
Набор шрифтов, которые можно использовать в окне консоли, был обрезан до шрифтов, которые были протестированы и, как известно, приемлемо работают в окнах консоли. Для английских систем это привело нас к Lucida Console и Terminal.
...
"Ну, это глупо. Ты должен был помешать мне выбрать шрифт, который так явно приводит к бессмыслице".
И это то, что мы сделали.
Не то чтобы я обвинял Рэймонда в этом, но он авторитетно иллюстрирует это как "не может случиться".
Выбор и тестирование консольных шрифтов для Windows должны были это поймать. Тот факт, что это вообще проблема, является отклонением.