Если я понимаю ваш вопрос, вы хотите написать функцию для чтения символов из matrix
(двумерный массив char
) в выделенную строку, помещая пробел между символами в каждой строке и возвращая строка с нулевым символом в конце возвращается к вызывающей функции.Вы должны сделать это, используя указатели и без массива [index]
.
Для начала, ваше объявление matrix
неверно.E
это не символ, это переменная.'E'
символьный литерал.(обратите внимание на одинарные кавычки) Таким образом, правильное объявление matrix
будет выглядеть следующим образом:
char matrix[SIZE][SIZE] = { {'U','N','T','E'}, /* don't use globals */
{'C','P','G','X'}, /* declare in main and */
{'D','L','A','B'}, /* pass as a parameter */
{'J','T','N','N'} };
( примечание: достаточно просто char matrix[][SIZE] = {{...}};
, где число строк будетразмер зависит от вашей инициализации)
Как отмечено в комментарии, избегайте использования глобальных переменных, если это не является абсолютно необходимым.(очень ограниченные случаи - не здесь).Вместо этого объявите matrix
в области, где это требуется, и передайте matrix
в качестве параметра любой функции, которая должна обрабатывать данные.Напротив, определение константы с #define
совершенно правильно, и вы должны определять константы по мере необходимости, чтобы избежать использования магических чисел в вашем коде.
Поскольку matrix
является 2Dмассив, чтобы передать его в качестве параметра, вы должны включить количество столбцов как часть передаваемого параметра.Вы можете объявить параметр как char matrix[SIZE][SIZE]
или эквивалентно char (*matrix)[SIZE]
, отражая тот факт, что первый уровень косвенности преобразуется в указатель на первый элемент при доступе.См .: C11 Standard - 6.3.2.1 Другие операнды - L-значения, массивы и обозначения функций (p3) (обращая внимание на 4 исключения)
В вашей функции makestring()
вы должнывыделите хранилище не менее SIZE * SIZE + SIZE
(пробел для каждого символа + 3 пробела + нуль-завершающий символ).Присвоение начального адреса вашего нового блока памяти указателю, а затем создание второго указателя на блок позволит вам перебирать его, копируя в него символы - при сохранении указателя на начало.
Соединяя эти части вместе, вы можете сделать что-то похожее на:
char *makestring (char (*a)[SIZE])
{
char *str = malloc (SIZE * SIZE + SIZE), *p = str; /* allocate */
if (!str) { /* validate EVERY allocation */
perror ("malloc-str");
return NULL;
}
for (int i = 0; i < SIZE; i++) { /* for each row */
if (i) /* if row not 1st */
*p++ = ' '; /* add space */
for (int j = 0; j < SIZE; j++) /* for each char */
*p++ = *(*(a + i) + j); /* copy to str */
}
*p = 0; /* nul-terminate string */
return str; /* return pointer to allocated string */
}
( примечание: , хотя это не ошибка, C обычно избегает использования переменной camelCase
или MixedCase
имена в пользу всех в нижнем регистре при резервировании в верхнем регистре имен для использования с макросами и константами.)
Сложив это в кратком примере, вы могли быdo:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
char *makestring (char (*a)[SIZE])
{
char *str = malloc (SIZE * SIZE + SIZE), *p = str; /* allocate */
if (!str) { /* validate EVERY allocation */
perror ("malloc-str");
return NULL;
}
for (int i = 0; i < SIZE; i++) { /* for each row */
if (i) /* if row not 1st */
*p++ = ' '; /* add space */
for (int j = 0; j < SIZE; j++) /* for each char */
*p++ = *(*(a + i) + j); /* copy to str */
}
*p = 0; /* nul-terminate string */
return str; /* return pointer to allocated string */
}
int main (void) {
char matrix[SIZE][SIZE] = { {'U','N','T','E'}, /* don't use globals */
{'C','P','G','X'}, /* declare in main and */
{'D','L','A','B'}, /* pass as a parameter */
{'J','T','N','N'} },
*str;
if ((str = makestring (matrix))) { /* validate call to makestring */
printf ("str: '%s'\n", str); /* output string */
free (str); /* free allocated memory */
}
}
( примечание: не забудьте free
выделенную память. Хотя она будет освобождена при выходе из программы, приобретите привычку отслеживать свои выделенияи обеспечение освобождения всех выделенных блоков)
Пример использования / вывода
$ ./bin/makestring
str: 'UNTE CPGX DLAB JTNN'
Использование памяти / проверка ошибок
В любом написанном вами коде, который динамически распределяет память,у вас есть 2 обязанности в отношении любого выделенного блока памяти: (1) всегда сохраняйте указатель на начальный адрес для блока памяти, поэтому (2) это может быть освобождается когда он больше не нужен.
Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы убедиться, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, попытайтесьчитать или основывать условный переход на неинициализированном значении и, наконец, подтвердить, что вы освобождаете всю выделенную память.
Для Linux valgrind
- нормальный выбор.Для каждой платформы есть похожие проверки памяти.Все они просты в использовании, просто запустите вашу программу через нее.
$ valgrind ./bin/makestring
==6576== Memcheck, a memory error detector
==6576== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6576== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==6576== Command: ./bin/makestring
==6576==
str: 'UNTE CPGX DLAB JTNN'
==6576==
==6576== HEAP SUMMARY:
==6576== in use at exit: 0 bytes in 0 blocks
==6576== total heap usage: 1 allocs, 1 frees, 20 bytes allocated
==6576==
==6576== All heap blocks were freed -- no leaks are possible
==6576==
==6576== For counts of detected and suppressed errors, rerun with: -v
==6576== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Всегда подтверждайте, что вы освободили всю выделенную память и нет ошибок памяти.
Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.