Новичок-программист на 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;
}
Отдельные символы могут быть записаны либо через их числовое значение, например 65, либо через их представление. В последнем случае вы используете одинарные кавычки, например 'a'. Обратите внимание, что 'a' == 65. Строки создаются с использованием двойных кавычек, в этом случае компилятор обязательно добавляет завершающий байт '\0'.
Примечание: добавьте комментарии для ясности. Повезло тебе! Так всегда поступают опытные программисты ;-)
strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]);
играет с огнем... "Строки" источника и назначения перекрываются... Когда вы расширяете эту программу на арабский, иврит или ???, (пишется справа налево), это не сработает... 1) Просто перемещайте один символ за раз в цикле. 2) Посмотрите на memmove()
, если вам нужно сдвинуть блоки, которые могут перекрываться.
@CraigEstey - спасибо. Как ученик, это единственный способ, которым я могу читать и понимать свой собственный код! ржу не могу
Объяснение
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 не «похож на строку», это строки в c, массив символов с 0 в конце
Проблема возникает из-за того, что 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
Спасибо за это объяснение. Все эти комментарии и ответы очень помогли мне разобраться в этом. Теперь моя программа работает, и мой первоначальный код много очищен. Ваше здоровье!
«Я понимаю, что символы на самом деле являются массивами значений ascii». Нет, это совершенно неправильно. char — это 8-битное значение. Значение ascii — это целочисленное значение символа. Это значение может быть сохранено в объекте char. В C нет строковых объектов, как в таких языках, как Python. Соглашение в C заключается в том, что строка представляет собой последовательность символов, которая заканчивается символом `\0', то есть символом со значением ascii, равным 0.