Как перебрать структуру CHAR_INFO без использования stati c int - PullRequest
0 голосов
/ 09 апреля 2020

При использовании for-l oop для перебора структуры CHAR_INFO (windows .h) мне кажется, что я могу использовать только static int, например:

Рабочий код:

const int MAP_SIZE = 45;
CHAR_INFO map[MAP_SIZE];
static int TILE_CENTER = 22;

for (static int j = 0; j < 45; j++) {
   map[j].Char.UnicodeChar = (j == TILE_CENTER ? tiles[0].getAsciiChar() : L'▓');
   map[j].Attributes = 0x20;
}

Это дополнительное решение не является чистым решением, но всякий раз, когда я использую неподписанное или обычное int, происходит сбой программы, без ошибок компилятора (это было бы здорово), она просто вылетает.

Код, который вылетает:

const int MAP_SIZE = 45;
CHAR_INFO map[MAP_SIZE];

const int TILE_CENTER = 22;

for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 9; j++) {
        map[j + (i * 9)].Char.UnicodeChar = (j == TILE_CENTER ? tiles[0].getAsciiChar() : L' ');
        map[j + (i * 9)].Attributes = 0x20;
    }
}

Я пытался создать итератор типа CHAR_INFO, но без успеха.

Есть ли способ избежать использования static int в этом случае?

Минимальный воспроизводимый пример

(скомпилировано с g ++)

#include "windows.h"

int main(void) {
    while (true) {
        const int MAP_SIZE = 45;
        CHAR_INFO map[MAP_SIZE];

        int TILE_CENTER = 22;

        for (int j = 0; j < 45; j++) {
            map[j].Char.UnicodeChar = (j == TILE_CENTER ? 'X' : L' ');
            map[j].Attributes = 0x20;
        }

        COORD coordinateBufferSize;
        COORD topLeftCoordinate;
        PSMALL_RECT srcWriteRect;

        coordinateBufferSize.Y = 5;
        coordinateBufferSize.X = 9;

        topLeftCoordinate.Y = 0;
        topLeftCoordinate.X = 0;

        srcWriteRect->Top = 4;
        srcWriteRect->Left = 10;
        srcWriteRect->Bottom = 8;
        srcWriteRect->Right = 18;

        HANDLE oldScreenBuffer = GetStdHandle(STD_OUTPUT_HANDLE);
        HANDLE newScreenBuffer = CreateConsoleScreenBuffer(
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            CONSOLE_TEXTMODE_BUFFER,
            NULL);

        BOOL succes = WriteConsoleOutputW(
            newScreenBuffer,                    // The new ScreenBuffer
            map,                                // The char array we want to display
            coordinateBufferSize,               // 
            topLeftCoordinate,
            srcWriteRect
        );

        SetConsoleActiveScreenBuffer(newScreenBuffer);
    }


    return 0;
}

Ошибка, которую я получаю при отладке:

Program received signal SIGSEGV, Segmentation fault.
0x00401491 in main () at mre.cpp:25
25              srcWriteRect->Top = 4;

1 Ответ

1 голос
/ 09 апреля 2020

Тем временем я нашел ответ:

Проблема была в типе PSMALL_RECT, который я использовал для переменной srcWriteRect. Очевидно, это указывало на недоступность памяти и сбой программы.

Тип должен быть SMALL_RECT, и любые указатели должны быть сделаны для указателя на эту переменную.

Рабочий пример (с измененным кодом )

#include "windows.h"

int main(void) {
    while (true) {
        const int MAP_SIZE = 90;
        CHAR_INFO map[MAP_SIZE];

        int TILE_CENTER = 22;

        for (int j = 0; j < 45; j++) {
            map[j].Char.UnicodeChar = (j == TILE_CENTER ? 'X' : L' ');
            map[j].Attributes = 0x20;
        }

        COORD coordinateBufferSize;
        COORD topLeftCoordinate;
        SMALL_RECT srcWriteRect;

        coordinateBufferSize.Y = 5;
        coordinateBufferSize.X = 9;

        topLeftCoordinate.Y = 0;
        topLeftCoordinate.X = 0;

        (&srcWriteRect)->Top = 4;
        (&srcWriteRect)->Left = 10;
        (&srcWriteRect)->Bottom = 8;
        (&srcWriteRect)->Right = 18;

        HANDLE oldScreenBuffer = GetStdHandle(STD_OUTPUT_HANDLE);
        HANDLE newScreenBuffer = CreateConsoleScreenBuffer(
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            CONSOLE_TEXTMODE_BUFFER,
            NULL);

        BOOL succes = WriteConsoleOutputW(
            newScreenBuffer,                    // The new ScreenBuffer
            map,                                // The char array we want to display
            coordinateBufferSize,               // 
            topLeftCoordinate,
            &srcWriteRect
        );

        SetConsoleActiveScreenBuffer(newScreenBuffer);
    }


    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...