Многомерные массивы с Char/pointer Проблемы с записью в Curses

Новичок-программист на C (опыт работы с другими языками высокого уровня), и я все еще изо всех сил пытаюсь привыкнуть к массивам, указателям и строкам и т. д.

Этот проект воссоздает то, что я сделал на питоне. Я храню набор символов (7 строк в высоту и 6 в ширину) в массиве. Массив является многомерным для хранения всех строк всех символов, на которые ссылается их соответствующий код ascii - структура массива: шрифт[код_кода][строка]. См. код ниже для ясности.

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

Мои проблемы (я уверен, потому что я все еще изучаю сложные способы программирования на c):

Я также не понимаю, почему объявление типа

char cur_char = ' '; 

Работает нормально, но это не так:

char msg = "This is a message";

Но это делает:

char msg[] = "This is a message";

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

Снова вызов функции curses следующим образом:

mvaddch(1, 74, " ");

Выдает мне ошибку "целое число из указателя". Я надеялся нарисовать пробел в строке 1 столбца 74. Если эта функция ожидает указатель, а не строку, означает ли это, что необходимо сохранить пробел в символе, а затем передать указатель этого символа функции? Я пытаюсь найти правильный подход здесь.

Наконец, я просто после некоторого руководства от более опытных программистов на C относительно логического подхода к этому. Возможно, хранить все эти строки в большом массиве — не лучший способ. Возможно ли (практично) поместить этот набор символов в память и ссылаться на него таким образом?

Любые предложения, советы и советы, с благодарностью и смиренно принимаются. Цените ваши глазные яблоки, и я полон решимости освоить этот язык!

Бонусный раунд Первоначально я пытался загрузить свой массив набора символов из функции в файле заголовка, чтобы у меня не было всех этих уродливых строк данных в основном файле c. Сдался, потому что я не мог передать массивы обратно в качестве возвращаемого значения функции. Я уверен, что есть лучший способ. Как бы вы его разделили?

Вот код: Все еще получаю ошибки:

mvaddch(l, m, scr_matrix[l][m]); // makes integer from pointer error; 
strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]); // incompatible pointer type

Вот тестовая версия моего кода. Напишите комментарии для ясности.

#include <curses.h>
#include <unistd.h> // For sleep()
#include <string.h> // For strlen()
#include <stdlib.h> // For malloc()

int main(int argc, char* argv[])
{
    // Let's initialise constants and set some configs
    char msg[] = "XYZ";
    int msg_length;
    int i, j, k, l, m;
    int msg_pos = 0;
    int char_pos = 0;
    char cur_char = ' ';

    // Array to make a matrix that we will draw to screen with curses
    char scr_matrix[7][76][2];  // Our lines (7) and cols (76) positions in an array

    // Lets just initalise all the array elements to contain spaces
    for (i = 0; i < 14; i++) {
      for (j = 0; j < 75; j++) {
        strcpy(scr_matrix[i][j], " "); //Have to use strcpy because can't set element
      }
    }

    // char font array to hold our char set
    char font2[100][7][7];  // 100 chars, 7 tall by 6 wide (+ /0 makes 7)

    // Set array elements - first element correspond to char ascii code
    // glyphs are 7 lines tall by 6 wide
    // Use strcpy because cannot directly set elements?

    strcpy(font2[88][0], "@@  @@");
    strcpy(font2[88][1], "@@  @@");
    strcpy(font2[88][2], " @@@@ ");
    strcpy(font2[88][3], "  @@  ");
    strcpy(font2[88][4], " @@@@ ");
    strcpy(font2[88][5], "@@  @@");
    strcpy(font2[88][6], "@@  @@");

    strcpy(font2[89][0], "@@  @@");
    strcpy(font2[89][1], "@@  @@");
    strcpy(font2[89][2], " @@@@ ");
    strcpy(font2[89][3], " @@@@ ");
    strcpy(font2[89][4], "  @@  ");
    strcpy(font2[89][5], "  @@  ");
    strcpy(font2[89][6], "  @@  ");

    strcpy(font2[90][0], "@@@@@@");
    strcpy(font2[90][1], "@@@@@@");
    strcpy(font2[90][2], "   @@ ");
    strcpy(font2[90][3], "  @@  ");
    strcpy(font2[90][4], " @@   ");
    strcpy(font2[90][5], "@@@@@@");
    strcpy(font2[90][6], "@@@@@@");

    // Get msg length
    msg_length = strlen(msg);

    // Initialize screen for curses
    initscr();
    // Hide the cursor with curses
    curs_set(0);

    for (i = 0; i < msg_length; i++) {

      cur_char = msg[msg_pos]; // keep track of which char from msg we are working on

      // Loop for 6 cols - 6 for glyph width
      for (j = 0; j < 7; j++) {
        clear(); // Clear the screen with curses

        // Loop for 7 lines - writing 1 char of the glyph to the matrix
        for (k = 0; k < 7; k++) {
          // cpy the character from font array into the matrix array
          strcpy(scr_matrix[k][74], &font2[cur_char][k][j]);
        }

        // Now add all matrix positions to the screen with curses mvaddch
        // Loops through all positions in scroll area
        for (l = 0; l < 7; l++) {
          for (m = 0; m < 75; m++) {
            mvaddch(l, m, scr_matrix[l][m]);  // add to screen with curses
            // now shift this character in the matrix over by -1 col so it shifts left
            strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]);
          }
        }
        // Now draw the screen as built by curses with mvaddch
        refresh();
        // Wait a bit - pause for timing purpose
        usleep(80000);
      }  // Back to top of loop for the next col

      // Finished the glyph so add a col of spaces for kerning between letters
      for (l = 0; l < 7; l++) {
        mvaddch(l, 74, " ");
        refresh();
        usleep(80000);
      }
      msg_pos++;
    }

    // Clean up our curses screen
    endwin();

    return 0;
}


«Я понимаю, что символы на самом деле являются массивами значений ascii». Нет, это совершенно неправильно. char — это 8-битное значение. Значение ascii — это целочисленное значение символа. Это значение может быть сохранено в объекте char. В C нет строковых объектов, как в таких языках, как Python. Соглашение в C заключается в том, что строка представляет собой последовательность символов, которая заканчивается символом `\0', то есть символом со значением ascii, равным 0.

Pablo 11.01.2023 01:11

Отдельные символы могут быть записаны либо через их числовое значение, например 65, либо через их представление. В последнем случае вы используете одинарные кавычки, например 'a'. Обратите внимание, что 'a' == 65. Строки создаются с использованием двойных кавычек, в этом случае компилятор обязательно добавляет завершающий байт '\0'.

Pablo 11.01.2023 01:14

Примечание: добавьте комментарии для ясности. Повезло тебе! Так всегда поступают опытные программисты ;-)

Craig Estey 11.01.2023 01:54
strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]); играет с огнем... "Строки" источника и назначения перекрываются... Когда вы расширяете эту программу на арабский, иврит или ???, (пишется справа налево), это не сработает... 1) Просто перемещайте один символ за раз в цикле. 2) Посмотрите на memmove(), если вам нужно сдвинуть блоки, которые могут перекрываться.
Fe2O3 11.01.2023 02:21

@CraigEstey - спасибо. Как ученик, это единственный способ, которым я могу читать и понимать свой собственный код! ржу не могу

Finno 11.01.2023 03:16
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
Уроки CSS 6
Уроки CSS 6
Здравствуйте дорогие читатели, я Ферди Сефа Дюзгюн, сегодня мы продолжим с вами уроки css. Сегодня мы снова продолжим с так называемых классов.
Что такое Css? Для чего он используется?
Что такое Css? Для чего он используется?
CSS, или "Каскадные таблицы стилей", - это язык стилей, используемый в веб-страницах. CSS является одним из основных инструментов веб-разработки...
0
5
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Объяснение

  char cur_char = ' '; 

Работает нормально, потому что '<char>' - это литерал с одним (8-битным) символом. char — это тип данных, в котором хранится 8-битный символ.

Это не работает

 char msg = "This is a message";

Потому что char содержит только один символ.

Боковая панель: строки символов в c:-

Строка символов в c представляет собой непрерывный массив 8-битных символов, за которым следует байт 0

Так что это "Привет" хранится в памяти как

 x48x65x6cx6cx6fx00
  H  e  l  l  o 

Хорошо, так что это

 char msg[] = "Hello";

Делает это создает массив из 6 (обратите внимание, +1 вместо 0) байтов в стеке и загружает в него буквы Hello и добавляет 0.

Это делает что-то совсем другое

 char *msg = "Hello";

Это создает 6-байтовый массив символов как литерал (обычно в сегменте кода), а также создает указатель стека (называемый msg) и устанавливает его так, чтобы он указывал на этот литерал.

Надеюсь это поможет.

Это очень помогает - спасибо. Я думаю, что это начинает погружаться - char - это всего лишь один символ (не содержит строку), но массив char может действовать как строка с 0 для ее разграничения.

Finno 11.01.2023 02:32

@Finno не «похож на строку», это строки в c, массив символов с 0 в конце

pm100 11.01.2023 02:54
Ответ принят как подходящий

Проблема возникает из-за того, что C изначально создавался без обеспечения безопасности типов, а проверки типов были добавлены позже, когда уже был создан некоторый удобный синтаксис.

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

char array[10];
char two_dim_array[10][20];

char *charpointer;

charpointer = array;     /* leaving the index away, so pointer to first element */
charpointer = &array[0]; /* basically the same */

charpointer = two_dim_array[3]; /* is short for */
charpointer = &two_dim_array[3][0];  /* this */

Но если вы используете переменную массива без индекса в sizeof или оператора адреса, компилятор все равно узнает, что это массив.

char array[10];
char two_dim_array[10][20];

int size;
char *charpointer;

size = sizeof(array);     /* 10 */
size = sizeof(two_dim_array[3]); /* 20 */

charpointer = &two_dim_array[10]; /* wrong pointer type, address of array of 20 char */

К вашим ошибкам от компилятора:

Mvaddch(l, m, scr_matrix[l][m]); // makes integer from pointer error;

Поскольку scr_matrix объявлен как char scr_matrix[7][76][2];

Scr_matrix[l][m] — указатель на первый байт строки массива самого низкого уровня. Компилятор жалуется, что mvaddch ожидает, что целочисленный код символа scr_matrix[l][m][0] подойдет.

Strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]); // incompatible pointer type

Спасибо за это объяснение. Все эти комментарии и ответы очень помогли мне разобраться в этом. Теперь моя программа работает, и мой первоначальный код много очищен. Ваше здоровье!

Finno 17.01.2023 00:46

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