Как заставить мой код идти вниз по списку команд, которые управляют машиной с числовым программным управлением

Я новичок в C++, и у меня есть проект, в котором я должен создать код, который понимает список команд, перечисленных в файле. Мой код успешно открывает файл, но я не уверен, следует ли он командам.

Я составил этот код, но я не уверен, что интерпретация моей команды неверна или мой вывод испорчен. Я продолжаю получать линию «разрезов» вместо дизайна.

подсказка выглядит следующим образом:

Станок с ЧПУ (ЧПУ) используется для создания металлических вывесок с помощью инструмента для лазерной резки.

Лазер находится в одном из двух состояний: включен или выключен.

Когда лазер включен, он режет металл и делает необходимый знак при движении.

Когда лазер выключен, лазер свободно перемещается, ничего не разрезая на куске металла.

Для этого задания вы напишете программу на C++ для управления движением станка с ЧПУ и моделирования того, что он вырезал бы в металлическом прямоугольнике.

  • Вы смоделируете металлический прямоугольник, создав массив m x n, инициализированный нулями.
  • Максимальное количество строк в массиве равно 10, а максимальное количество столбцов — 50.
  • Команды для управления лазером загружаются из файла с именем laser.txt и выглядят следующим образом:

Таблица 1: Список команд и их значение.

Command Meaning
I In (move the laser inward so that it begins cutting)
O Out (move the laser outward so that it stops cutting)
R Turn right
L Turn left
A n Move ahead n spaces, n is a positive int <= 80
  • Файл laser.txt будет содержать по одной команде в строке.
  • Лазер начинается в точке (0,0), которая находится в верхнем левом углу сетки.
  • Положительное направление x — вправо, положительное направление y — вниз (см. схему на следующей странице).
  • Лазер начинает указывать в положительном направлении x.
  • Если лазер когда-либо находится в месте или перемещается по нему, пока он находится в положении «В», он отмечает это место (что может можно смоделировать, записав 1 в ваш массив m x n.)
  • Когда ваша программа закончит имитировать движение лазера, она должна распечатать изображение, которое будет вырезано в металлической сетке, используя пробелы для неразрезанных мест и звездочки для вырезов.

Пример (ввод пользователя подчеркнут для наглядности, подчеркнутый текст в вашей программе не нужен):

Enter the file name: laser.txt
Generated grid:
* * * * *
        *
        *
        *
        *


        *

Здесь Laser.txt содержал следующее:

I
A 4
R
A 4
O
A 2
I

Если есть какая-либо недопустимая команда, не указанная в Таблице 1, программа должна быть немедленно остановлена ​​со следующим сообщение об ошибке: «Обнаружена недопустимая команда. Завершение».

Наконец, если указанное имя файла не может быть открыто, выведите следующее сообщение об ошибке: «Ошибка, не удается открыть файл».

Ваша программа должна содержать несколько функций, которые решают более мелкие части проблемы.

Основы сетки

Ниже представлена ​​графическая сетка

x- axis (+)
y
a
x
i
s
+
(0,0)

Это графическое окно. Обратите внимание, что (0,0) — это верхний левый угол, а значения y положительны при движении вниз, а значения x положительны при движении в правильном направлении.

Вы можете предположить, что лазер начинается в положении (0,0) и направлен на восток в соответствии с компасной розой ниже.

Примечание. Вы должны постоянно следить за тем, чтобы лазер оставался в области рисования.

Выше представлена ​​репрезентативная сетка двумерного мира ЧПУ с m=16 и n=16.

T представляет собой начальное положение лазера.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

int main() {
    int n, x = 0, y = 0;
    bool cutting = false;
    const int gridWidth = 80, gridHeight = 50;
    char grid[gridHeight][gridWidth] = {' '};
    char command;

    string fileName; // obtaining and openning file
    cout << "Enter the file name: ";
    cin >> fileName;

    ifstream file(fileName);
    if (!file) {
        cout << "Error, cannot open file." << endl;
        return 0;
    }

    while (file >> command) { // using true/false to operate cutting and positioning
        if (command == 'I') {
            cutting = true;
        }
        else if (command == 'O') {
            cutting = false;
        }
        else if (command == 'R') {
            if (x < gridWidth - 1) x++;
        }
        else if (command == 'L') {
            if (x > 0) x--;
        }
        else if (command == 'A') {
            file >> n;
            if (n > 0 && n <= gridWidth - x) {
                for (int i = 0; i < n; i++) {
                    if (cutting) {
                        grid[y][x+i] = '#';
                    }
                }
                x += n;
            }
        }
    }

    file.close();

    for (int i = 0; i < gridHeight; i++) { // printing grid
        for (int j = 0; j < gridWidth; j++) {
            cout << grid[i][j];
        }
        cout << "\n";
    }

    return 0;
}

Это ваша интерпретация неверна. Лазер имеет направление движения. Так что R не означает шаг вправо, это означает поворот лазера вправо на 90 градусов. Команда A перемещает лазер в его текущем направлении движения. В вашем коде лазер шагает влево и вправо, но в остальном всегда движется вниз.

john 20.04.2023 09:41

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

463035818_is_not_a_number 20.04.2023 09:42

Минимальное количество вещей, которые вам нужно сделать, чтобы заставить его работать: onlinegdb.com/_5mfi36hB

Jerry Jeremiah 20.04.2023 23:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошая задача. И хорошо описано.

С точки зрения программирования, относительно алгоритмов и навыков программа имеет низкую сложность. Усилия по программированию высоки.

Но описание дает много подробных требований и несколько хороших советов.

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

Один из самых важных советов в описании — использовать несколько функций для решения небольших частей задачи. Это очень важное правило, которое поможет вам всегда. Разбейте большую проблему на более мелкие. Решение для них будет намного проще.

Давайте посмотрим, какие более мелкие строительные блоки мы могли бы использовать.

  • Настройка структуры данных
  • Инициализация матрицы
  • Список чтения с командами из файла
  • Разделить одну командную строку на команду и потенциальный атрибут
  • Интерпретировать и выполнять команды
  • Нарисуйте результирующую матрицу

Очень важное требование: всегда оставайтесь в рамках матрицы.

Теперь мы шаг за шагом реализуем требования.

Определение матрицы. Требования говорят, используйте массив 2d с размерами 10x50. Размерность является важным параметром, поэтому мы можем определить ее через глобальные константы. В C++ мы используем для этого константы времени компиляции, которые определяются с помощью ключевого слова constexpr. Кроме того, у вас может возникнуть соблазн использовать массивы C-Style, такие как char matrix[10][50]. Но лучше использовать std::array из библиотеки контейнеров (это похоже на std::vector, но его размер статичен. Чтобы больше абстрагироваться и облегчить понимание, мы будем использовать операторы using или typedef для создания псевдонимов.

// Define the size of the matrix
constexpr int NumberOfRows = 10;
constexpr int NumberOfColumns = 50;

// This will be our 2d matrix
using Matrix = std::array<std::array<char, NumberOfColumns>, NumberOfRows>;
// Note , you could also write
// using Matrix = char[NumberOfRows][NumberOfColumns];

Теперь нам нужно что-то, чтобы инициализировать матрицу или заполнить ее значением. Требование говорит, заполните его 0es.

Это можно сделать с помощью простого двойного вложенного цикла for. Мы создаем функцию, в которой мы можем выбрать «символ заполнения», но присвоить ему значение по умолчанию 0, что означает «пустой». Функция может быть реализована следующим образом:

// Indicator for a not processed field
constexpr char ConditionSolid = '\0';
constexpr char ConditionCut = '\1';

// This will set all values in the matrix 
void fillMatrix(Matrix& matrix, const char fillChar = ConditionSolid) {
    for (int row = 0; row < NumberOfRows; ++row) {
        for (int column = 0; column < NumberOfColumns; ++column) {
            matrix[row][column] = fillChar;
        }
    }
} 

Следующая функциональность, которая нам нужна, — это чтение команд из файла. Нам нужно открыть файл и проверить, можно ли его открыть. Затем нам нужно прочитать строку за строкой и сохранить результаты. Так как мы не знаем, сколько строк в файле, нам нужен контейнер, который может динамически расти, поэтому std::vector и так как команды имеют разную и возможно неизвестную длину, мы будем использовать одну команду как строку. Все это мы снова абстрагируем объявлением «using». Поскольку функция может завершиться ошибкой, мы вернем логическое значение с true в качестве успеха. Что-то вроде приведенного ниже:

//-------------------------------------------------------------------------------
// Read commands from file
using CommandLine = std::string;
using CommandList = std::vector<CommandLine>;

bool readCommandsFromFile(const std::string& fileName, CommandList& commandList) {
    // Function return value. True is OK, false means error. We assume error in the beginning
    bool result = false;

    // Open the file.
    std::ifstream ifs(fileName);

    // Check, if the file could be opened
    if (ifs) {
        // Ok, now the file is open, we want to read command lines
        CommandLine commandLine{};
        // Read all lines in a loop, until the all data have been read
        while (std::getline(ifs, commandLine)) {
            // Store new, just read line in the command list
            commandList.push_back(commandLine);
        }
        result = true;
    }
    else {
        // The file could not be opened or any other stream error
        std::cout << "Error, cannot open file.";
    }
    return result;
}

Итак, теперь у нас есть список с командными строками. Эти команды должны быть позже извлечены из строки и разделены на команду с потенциальным атрибутом. Поскольку в командной строке могут быть недопустимые команды, мы проверим это, а также вернем логическое значение false в случае возникновения проблемы.

Эта функция имеет небольшую длину из-за множества проверок ошибок.

// Define List with commands (we directly use the define Letters for that)
using Command = char;
using CommandAttribute = int;

constexpr Command CMD_In = 'I';
constexpr Command CMD_Out = 'O';
constexpr Command CMD_TurnRight = 'R';
constexpr Command CMD_TurnLeft = 'L';
constexpr Command CMD_Move = 'A';

bool getCommand(const CommandLine& commandLine, Command& command, CommandAttribute& commandAttribute) {
    // Function return value. True is OK, false means error. We assume OK in the beginning
    bool result = true;

    // Sanity check
    if (commandLine.length() > 0) {
        // check first letter in cammand line
        switch (commandLine[0]) {
        case CMD_In:            // Fallthrough
        case CMD_Out:           // Fallthrough
        case CMD_TurnRight:     // Fallthrough
        case CMD_TurnLeft:
            command = commandLine[0];
            commandAttribute = 0;
            break;
        case CMD_Move:
            // The move command has a parameter, This we need to convert to an integer
            // First we need to check, if a valid integer is given
            // Integer starts at index 2 we allow only for a small number of integers
            bool validInteger = ((commandLine.length()>1) and (commandLine.length()<6));
            for (int i = 2; i < commandLine.length() and validInteger; ++i) {
                if (not std::isdigit(commandLine[i])) {
                    validInteger = false;
                }
            }
            // Ok there was a valid character sequence forming an integer
            if (validInteger) {
                command = commandLine[0];
                commandAttribute = std::stoi(commandLine.substr(1)));
            }
            else {
                // Some wrong data in the command
                command = '\0';
                commandAttribute = 0;
                result = false;
            }
            break;
        default:
            // Unknwon command. Result of function will be false
            command = '\0';
            commandAttribute = 0;
            result = false;
        }
    }
    return result;
}

Теперь нам нужно выполнить команды. Мы начинаем с позиции x и y 0, а затем читаем команды. Выполняем их поэтапно.

Важно то, что мы не пересекаем границы. Движение будет выполняться путем добавления или вычитания значений в зависимости от текущего направления.

Для направления мы используем целое число. Каждый раз, когда есть «правильная» команда, мы увеличиваем значение. С делением по модулю 4 мы избегаем переполнения. Для «Left» мы уменьшаем на единицу. Отрицательные значения будут компенсированы добавлением 4. На самом деле мы всегда будем добавлять 4, а затем использовать деление по модулю для ограничения значения.

К сожалению, это довольно длинно

// Execute the commands
using Direction = int;
using LaserState = int;
constexpr Direction DirectionNorth = 0;
constexpr Direction DirectionEast = 1;
constexpr Direction DirectionSouth = 2;
constexpr Direction DirectionWest = 3;
constexpr LaserState LaserStateOff = 0;
constexpr LaserState LaserStateOn = 1;

bool execute(const CommandList& commandList, Matrix& matrix) {
    // Function return value. True is OK, false means error. We assume OK in the beginning
    bool result = true;

    // Set initial values
    int currentX = 0;
    int currentY = 0;
    Direction currentdirection = DirectionEast;
    Command command{};
    CommandAttribute commandAttribute{};
    LaserState laserState = LaserStateOff;

    // Execute all commands
    for (const CommandLine& commandLine : commandList) {

        // First, get the command
        if (getCommand(commandLine, command, commandAttribute)) {
            switch (command) {
            case CMD_In:
                laserState = LaserStateOn;
                matrix[currentY][currentX] = ConditionCut;
                break;
            case CMD_Out:
                laserState = LaserStateOff;
                break;
            case CMD_TurnRight:
                ++currentdirection;
                currentdirection = currentdirection % 4;
                break;
            case CMD_TurnLeft:
                --currentdirection;
                currentdirection = (currentdirection + 4) % 4;
                break;
            case CMD_Move:
                // This is a longer story and should probably be put in a function as well
            {

                // Check Laserstate and correspong fillchar
                char fillChar = ConditionSolid;
                if (laserState == LaserStateOn) {
                    fillChar = ConditionCut;
                }
                int endPosition{};

                switch (currentdirection) {
                case DirectionNorth:
                    // Calculate new target position
                    endPosition = currentY - commandAttribute;
                    // Limit to border
                    if (endPosition < 0) endPosition = 0;

                    // Set values
                    for (int i = currentY; (laserState == LaserStateOn) and  i >= endPosition; --i)
                        matrix[i][currentX] = fillChar;
                    currentY = endPosition;
                    break;
                case DirectionSouth:
                    // Calculate new target position
                    endPosition = currentY + commandAttribute;
                    // Limit to border
                    if (endPosition >= NumberOfRows) endPosition = NumberOfRows-1;

                    // Set values
                    for (int i = currentY; (laserState == LaserStateOn) and i <= endPosition; ++i)
                        matrix[i][currentX] = fillChar;
                    currentY = endPosition;
                    break;
                case DirectionWest:
                    // Calculate new target position
                    endPosition = currentX - commandAttribute;
                    // Limit to border
                    if (endPosition < 0) endPosition = 0;

                    // Set values
                    for (int i = currentX; (laserState == LaserStateOn) and i >= endPosition; --i)
                        matrix[currentY][i] = fillChar;
                    currentX = endPosition;
                    break;
                case DirectionEast:
                    // Calculate new target position
                    endPosition = currentX + commandAttribute;
                    // Limit to border
                    if (endPosition >= NumberOfColumns) endPosition = NumberOfColumns - 1;

                    // Set values
                    for (int i = currentX; (laserState == LaserStateOn) and i <= endPosition; ++i)
                        matrix[currentY][i] = fillChar;
                    currentX = endPosition;
                    break;
                }
            }

                break;
            default:
                result = false;
                std::cout << "Internal programming error.";
                break;
            }
        }
        else {
            // Illegal command found
            result = false;
            std::cout << "Encountered an Invalid command. Terminating.";
            break;
        }
    }
    return result;
}

Функция печати довольно проста. Не нужно показывать это здесь.

Тогда функция main будет довольно короткой. Затем мы можем объединить все вместе:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <array>

//-------------------------------------------------------------------------------
// Define the size of the matrix
constexpr int NumberOfRows = 10;
constexpr int NumberOfColumns = 50;

// This will be our 2d matrix
using Matrix = std::array<std::array<char, NumberOfColumns>, NumberOfRows>;
// Note , you could also write
// using Matrix = char[NumberOfRows][NumberOfColumns];

//-------------------------------------------------------------------------------
// Indicator for a not processed field
constexpr char ConditionSolid = '\0';
constexpr char ConditionCut = '\1';

// This will set all values in the matrix 
void fillMatrix(Matrix& matrix, const char fillChar = ConditionSolid) {
    for (int row = 0; row < NumberOfRows; ++row) {
        for (int column = 0; column < NumberOfColumns; ++column) {
            matrix[row][column] = fillChar;
        }
    }
}

//-------------------------------------------------------------------------------
// Read commands from file
using CommandLine = std::string;
using CommandList = std::vector<CommandLine>;

bool readCommandsFromFile(const std::string& fileName, CommandList& commandList) {
    // Function return value. True is OK, false means error. We assume error in the beginning
    bool result = false;

    // Open the file.
    std::ifstream ifs(fileName);

    // Check, if the file could be opened
    if (ifs) {
        // Ok, now the file is open, we want to read command lines
        CommandLine commandLine{};
        // Read all lines in a loop, until the all data have been read
        while (std::getline(ifs, commandLine)) {
            // Store new, just read line in the command list
            commandList.push_back(commandLine);
        }
        result = true;
    }
    else {
        // The file could not be opened or any other stream error
        std::cout << "Error, cannot open file.";
    }
    return result;
}
//-------------------------------------------------------------------------------
// Define List with commands (we directly use the define Letters for that)
using Command = char;
using CommandAttribute = int;

constexpr Command CMD_In = 'I';
constexpr Command CMD_Out = 'O';
constexpr Command CMD_TurnRight = 'R';
constexpr Command CMD_TurnLeft = 'L';
constexpr Command CMD_Move = 'A';

bool getCommand(const CommandLine& commandLine, Command& command, CommandAttribute& commandAttribute) {
    // Function return value. True is OK, false means error. We assume OK in the beginning
    bool result = true;

    // Sanity check
    if (commandLine.length() > 0) {
        // check first letter in cammand line
        switch (commandLine[0]) {
        case CMD_In:            // Fallthrough
        case CMD_Out:           // Fallthrough
        case CMD_TurnRight:     // Fallthrough
        case CMD_TurnLeft:
            command = commandLine[0];
            commandAttribute = 0;
            break;
        case CMD_Move: {
            // The move command has a parameter, This we need to convert to an integer
            // First we need to check, if a valid integer is given
            // Integer starts at index 2 we allow only for a small number of integers
            bool validInteger = ((commandLine.length() > 1) and (commandLine.length() < 6));
            for (int i = 2; i < commandLine.length() and validInteger; ++i) {
                if (not std::isdigit(commandLine[i])) {
                    validInteger = false;
                }
            }
            // Ok there was a valid character sequence forming an integer
            if (validInteger) {
                command = commandLine[0];
                commandAttribute = std::stoi(commandLine.substr(1));
            }
            else {
                // Some wrong data in the command
                command = '\0';
                commandAttribute = 0;
                result = false;
            }}
            break;
        default:
            // Unknwon command. Result of function will be false
            command = '\0';
            commandAttribute = 0;
            result = false;
            break;
        }
    }
    return result;
}
//-------------------------------------------------------------------------------
// Execute the commands
using Direction = int;
using LaserState = int;
constexpr Direction DirectionNorth = 0;
constexpr Direction DirectionEast = 1;
constexpr Direction DirectionSouth = 2;
constexpr Direction DirectionWest = 3;
constexpr LaserState LaserStateOff = 0;
constexpr LaserState LaserStateOn = 1;

bool execute(const CommandList& commandList, Matrix& matrix) {
    // Function return value. True is OK, false means error. We assume OK in the beginning
    bool result = true;

    // Set initial values
    int currentX = 0;
    int currentY = 0;
    Direction currentdirection = DirectionEast;
    Command command{};
    CommandAttribute commandAttribute{};
    LaserState laserState = LaserStateOff;

    // Execute all commands
    for (const CommandLine& commandLine : commandList) {

        // First, get the command
        if (getCommand(commandLine, command, commandAttribute)) {
            switch (command) {
            case CMD_In:
                laserState = LaserStateOn;
                matrix[currentY][currentX] = ConditionCut;
                break;
            case CMD_Out:
                laserState = LaserStateOff;
                break;
            case CMD_TurnRight:
                ++currentdirection;
                currentdirection = currentdirection % 4;
                break;
            case CMD_TurnLeft:
                --currentdirection;
                currentdirection = (currentdirection + 4) % 4;
                break;
            case CMD_Move:
                // This is a longer story and should probably be put in a function as well
            {

                // Check Laserstate and correspong fillchar
                char fillChar = ConditionSolid;
                if (laserState == LaserStateOn) {
                    fillChar = ConditionCut;
                }
                int endPosition{};

                switch (currentdirection) {
                case DirectionNorth:
                    // Calculate new target position
                    endPosition = currentY - commandAttribute;
                    // Limit to border
                    if (endPosition < 0) endPosition = 0;

                    // Set values
                    for (int i = currentY; (laserState == LaserStateOn) and  i >= endPosition; --i)
                        matrix[i][currentX] = fillChar;
                    currentY = endPosition;
                    break;
                case DirectionSouth:
                    // Calculate new target position
                    endPosition = currentY + commandAttribute;
                    // Limit to border
                    if (endPosition >= NumberOfRows) endPosition = NumberOfRows-1;

                    // Set values
                    for (int i = currentY; (laserState == LaserStateOn) and i <= endPosition; ++i)
                        matrix[i][currentX] = fillChar;
                    currentY = endPosition;
                    break;
                case DirectionWest:
                    // Calculate new target position
                    endPosition = currentX - commandAttribute;
                    // Limit to border
                    if (endPosition < 0) endPosition = 0;

                    // Set values
                    for (int i = currentX; (laserState == LaserStateOn) and i >= endPosition; --i)
                        matrix[currentY][i] = fillChar;
                    currentX = endPosition;
                    break;
                case DirectionEast:
                    // Calculate new target position
                    endPosition = currentX + commandAttribute;
                    // Limit to border
                    if (endPosition >= NumberOfColumns) endPosition = NumberOfColumns - 1;

                    // Set values
                    for (int i = currentX; (laserState == LaserStateOn) and i <= endPosition; ++i)
                        matrix[currentY][i] = fillChar;
                    currentX = endPosition;
                    break;
                }
            }

                break;
            default:
                result = false;
                std::cout << "Internal programming error.";
                break;
            }
        }
        else {
            // Illegal command found
            result = false;
            std::cout << "Encountered an Invalid command. Terminating.";
            break;
        }
    }
    return result;
}
//-------------------------------------------------------------------------------
// printing the matrix
void print(const Matrix& matrix) {
    std::cout << "\n\n";
    for (int row = 0; row < NumberOfRows; ++row) {
        for (int column = 0; column < NumberOfColumns; ++column) {
            std::cout << ((matrix[row][column] == ConditionCut) ? '*' : ' ');
        }
        std::cout << '\n';
    }
}

int main() {
    Matrix matrix{};
    fillMatrix(matrix);

    CommandList commandList{};
    const std::string commandFileName = "r:\\laser.txt";
    if (readCommandsFromFile(commandFileName, commandList)) {
        if (execute(commandList, matrix)) {
            print(matrix);
        }
    }
}

Другие вопросы по теме