C - функция возвращает указатель на строку из матрицы символов, ТОЛЬКО используйте указатели - PullRequest
0 голосов
/ 17 апреля 2019

Мне нужно написать функцию под названием MakeString. Функция возвращает указатель на строку, которая содержит одно слово, составленное из каждой строки маленькой матрицы по порядку, так что каждый разрыв строки будет выражен как один пробел между словами в строке. (После последнего слова не будет пробела.)

Вывод: в функции нет использования [], но выполняется при работе с указателями.

Функция. Кроме того, следует проводить поездки с избирателями, что означает, что они действительно будут голосовать за друг друга

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

Я пытался сделать функцию, но она НЕ похожа на инструкцию и не хороша ...

#define SIZE 4
static char allocbuf[SIZE][];
static char *allocp = allocbuf;

char matrix[SIZE][SIZE]
{
    {U,N,T,E},
    {C,P,G,X},
    {D,L,A,B},
    {J,T,N,N}
};
char MakeString(int n)  /*return pointer to n charachters*/
{
    if (allocbuf + SIZE - allocp >=n)
    {
        allocp += n;
        return  allocp - n;
    }
    else
        return 0;
}

Например:

Маленькая матрица:

U N T E

C P G X

D L A B

J T N N

pStr = UNTE CPGX DLAB JTNN

Спасибо (:

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Если я понимаю ваш вопрос, вы хотите написать функцию для чтения символов из 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)

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

Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 18 апреля 2019

Вам необходимо указать размер allocbuf, чтобы он мог содержать весь результат:

char allocbuf[SIZE * (SIZE + 1)];

Нет необходимости в allocp, потому что имя массива будет уменьшаться до указателя при использовании врасчеты.В MakeString вам нужно циклически перебирать строки и символы matrix, копируя их в allocbuf.

char *MakeString()
    for (int i = 0; i < SIZE; i++) {
        memcpy(allocbuf + i * SIZE, matrix + i, SIZE);
        if (i < SIZE - 1) {
            // write space between rows
            *(allocbuf + i * SIZE + SIZE) = ' ';
        } else {
            // write null at end
            *(allocbuf + i * SIZE + SIZE) = 0;
        }
    }
    return allocbuf;
}

В инструкциях не упоминается аргумент n для MakeString()поэтому я его убрал.

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