Можно ли использовать спецификаторы формата в качестве аргументов для функции - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь написать функцию, которая позволяет мне инициализировать каждый элемент матрицы с заданным значением. Мне бы хотелось, чтобы эта функция была как можно более универсальной, то есть она могла бы обрабатывать матрицы любого типа данных (float, char и т. Д.). Очевидно, что в качестве одного из аргументов функции потребуется значение, с которым пользователь хочет инициализировать элементы матрицы. Поскольку это значение может быть любого типа данных, я не знаю, как это сделать. Стандартные функции, такие как printf и scanf, могут принимать аргументы любого типа благодаря использованию спецификаторов формата (% d,% f и т. Д.). Это заставило меня задуматься: как и вообще возможно использовать спецификаторы формата в определенной программистом функции? В идеале моя функция должна выглядеть примерно так:

void initMatrix(void*** matrixToInit, int nRows, int nCols, const char format, void(?) value)

Чтобы при вызове мне пришлось написать что-то вроде:

char matrixOfAs[3][3];

initMatrix(&matrixOfAs, 3, 3, "%c", 'A');

Возможно ли что-то подобное? Есть ли другие решения этой проблемы?

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Предполагая, что матрица представляет собой правильный двумерный массив типа элемента (массив массива типа элемента), а не одномерный массив указателя на тип элемента, вы можете передать указатель void * на первый элемент инициализируемой матрицы, размеры матрицы, размер элемента и указатель на начальное значение элемента, как показано следующим образом:

#include <string.h>
#include <stdio.h>

void initMatrix(void *matrixToInit, unsigned int nRows, unsigned int nCols,
        size_t elemSize, const void *elemVal)
{
    size_t offset, end;

    end = nRows * nCols * elemSize;
    for (offset = 0; offset < end; offset += elemSize) {
        memcpy((char *)matrixToInit + offset, elemVal, elemSize);
    }
}

int main(void)
{
    char matrixOfAs[3][3];
    int i, j;

    initMatrix(&matrixOfAs[0][0], 3, 3, sizeof(char), (char []){ 'A' });
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf(" %c", matrixOfAs[i][j]);
        }
        printf("\n");
    }
    return 0;
}

Если вам не нравится значение составного литерального массива (char []){ 'A' }, которое я передал параметру elemVal (что позволяет значению массива затухать до указателя на его первый элемент), вы можете заменить его указателем на инициализированная переменная типа char в этом случае, например определить char a = 'A'; и заменить (char []){ 'A' } на &a.

0 голосов
/ 14 мая 2019

Чтобы сделать эту функцию универсальной для любого типа данных, который вы решите использовать, просто создайте функцию, которая не обрабатывает специфический тип данных, а вместо этого использует указатели на функции.

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

Например, сделать функцию initMatrix вроде:

void initMatrix(void*** matrix, int nRows, int nCols, void(*creatematrix)(void ***, int, int));

Теперь создайте еще одну функцию, которая будет обрабатывать создание int **matrix, давайте вызовем ее void CreateIntMatrix(void ***matrix, int m, int m); и передадим указатель на эту функцию в качестве аргументафункция initmatrix.Теперь, когда вы вызываете initMatrix для обработки типов данных int, просто вызывайте его так:

void initMatrix(&matrixOfAs, 3, 3, CreateIntMatrix);

, вы должны также создать функцию, которая обрабатывает char, double и т. Д.

Теперь, когда вы создаете функцию initMatrix, создайте ее так:

void initMatrix(void*** matrix, int nRows, int nCols, void(*creatematrix)(void ***, int, int)){
    /*Make something*/
    creatematrix(matrix, nRows, nCols)//initialize any type of matrix
    /*Make something*/
}
...