如何修改函数内部的多维指针?

How modify a multidimensional pointer inside a function?

我有一个使用 mallocmemcpy 以这种方式操作 char*** 的函数

// Convert a buffer full line to separated variables
int parseBufferToVariables(char ***variableContainer, char *bufferToParse, int maxVarSize) {
    int i = 0;
    // Get number of rows of the string
    int numberOfRows = 0;
    for (i = 0; bufferToParse[i] != '[=10=]'; i++) {
        if (bufferToParse[i] == '\n')
            ++numberOfRows;
    }
    // Get number of columns of the string
    int numberOfColumns = 1;
    for (i = 0; bufferToParse[i] != '\n'; i++) {
        if (bufferToParse[i] == '\t')
            ++numberOfColumns;
    }
    // Allocate separated variable array
    size_t dim0 = numberOfColumns, dim1 = numberOfRows, dim2 = maxVarSize;
    variableContainer = malloc(sizeof *variableContainer * dim0);
    if (variableContainer) {
        size_t i;
        for (i = 0; i < dim0; i++) {
            variableContainer[i] = malloc(sizeof *variableContainer[i] * dim1);
            if (variableContainer[i]) {
                size_t j;
                for (j = 0; j < dim1; j++) {
                    variableContainer[i][j] = malloc(sizeof *variableContainer[i][j] * dim2);
                }
            }
        }
    }
    // Start parsing string to 3D array
    int init            = 0;
    int numberOfVars    = 0;
    int numberOfLines   = 0;
    int sizeOfVar       = 0;
    int position        = 0;
    char emptyArray[MAXVARSIZE] = {0};
    // Loop trought all lines
    i = 0;
    while (numberOfLines  < numberOfRows) {
        // Every delimiter
        if (bufferToParse[i] == '\t' || bufferToParse[i] == '\n') {
            // Size of the new sring
            sizeOfVar = i - init;
            // Set last [=10=] character in order to recognize as a proper string
            memcpy(&variableContainer[numberOfVars][numberOfLines], emptyArray, maxVarSize);
            // Copy the string to array
            memcpy(&variableContainer[numberOfVars][numberOfLines], &bufferToParse[position], sizeOfVar);
            // Handle pointers poisition
            init = i + 1;
            position += sizeOfVar + 1;
            // Handle when end of line is reached
            if (bufferToParse[i] == '\n') {
                numberOfVars = 0;
                numberOfLines++;
            }
        }
        i++;
    }
    return numberOfRows;
}

我正在尝试用不同的方式来称呼它:

char*** container= {0};
parseBufferToVariables (&container, inputString, MAXVARSIZE);

char*** container= {0};
parseBufferToVariables (container, inputString, MAXVARSIZE);

甚至我尝试在函数中调用 char****:

int parseBufferToVariables(char**** variableContainer, char* bufferToParse, int maxVarSize)

但我总是在 parseBufferToVariables 函数外调用 char*** 时出现段错误。 有任何想法吗?

OP 的目标是 4 * 参数,但其他方法更好。

*s 的高度掩饰了一个关键的失败是代码需要以某种方式传达列(选项卡的数量)宽度。

此外,我没有看到某些空字符终止形成_strings_as 第二个 memcpy() 的大小没有限制 - 甚至可能会覆盖分配边界。


下面的想法是每个级别的分配都以 null 结尾。

csv = parse_file_string(const char *file_string);

在return,当csv[line] == NULL,没有更多的行

csv[line][tab] == NULL时,没有更多的字符串。

这种方法还允许每行使用不同数量的字符串。

调整算法,伪C代码

// return NULL on error
char ***parse_file_string(const char *file_string) {
  number_lines = find_line_count(file_string);
  char ***csv = calloc(number_lines + 1, sizeof *csv);
  if (csv == NULL) return NULL;

  for (line=0; line < number_lines; line++) {
    tab_count = find_tab_count(file_string);
    csv[line] = calloc(tab_count + 2, sizeof *(csv[line])); 
    // add NULL check

    for (tab=0; tab < tab_count; tab++) {
      char *end = strchr(file_string, '\t');
      csv[line][tab] = malloc_string(file_string, end);
      // add NULL check
      file_string = end + 1;
    }
    char *end = strchr(file_string, '\n');
    csv[line][tab++] = malloc_str(file_string, end); 
    // add NULL check
    file_string = end + 1;
    csv[line][tab] = NULL;

  }
  csv[line] = NULL;
  return csv;
}

用法

char ***container = parse_file_string(file_string);

for (line=0; container[line]; line++)
  for (tab=0; container[line][tab]; tab++)
     puts(container[line][tab]);

//free
for (line=0; container[line]; line++)
  for (tab=0; container[line][tab]; tab++)
     free(container[line][tab]);
  free(container[line]);
free (container)

如果支持,可以使用指向可变长度数组的指针。
首先获取缓冲区内容的维度。这假设每一行都有相同数量的制表符。
声明指针并分配内存。
然后将缓冲区解析到分配的内存中。

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

void getdimension ( char *buffer, int *rows, int *cols, int *size) {
    int maxsize = 0;
    *rows = 0;
    *cols = 0;
    *size = 0;
    while ( *buffer) {//not the terminating zero
        if ( '\n' == *buffer) {
            if ( ! *rows) {//no rows counted yet
                ++*cols;//add a column
            }
            ++*rows;
            if ( maxsize > *size) {
                *size = maxsize;
            }
            maxsize = 0;
        }
        if ( '\t' == *buffer) {
            if ( ! *rows) {//no rows counted yet
                ++*cols;
            }
            if ( maxsize > *size) {
                *size = maxsize;
            }
            maxsize = 0;
        }
        ++maxsize;
        ++buffer;
    }
    if ( '\n' != *(buffer - 1)) {//last character is not a newline
        ++*rows;
        if ( maxsize > *size) {
            *size = maxsize;
        }
    }
}

void createptr ( int rows, int columns, int size, char (**ptr)[columns][size]) {
    if ( NULL == ( *ptr = malloc ( sizeof **ptr * rows))) {
        fprintf ( stderr, "malloc problem\n");
        exit ( EXIT_FAILURE);
    }
    for ( int line = 0; line < rows; ++line) {
        for ( int tab = 0; tab < columns; ++tab) {
            (*ptr)[line][tab][0] = 0;
        }
    }
}

void parsebuffer ( char *buffer, int rows, int columns, int size, char (*ptr)[columns][size]) {
    int eachrow = 0;
    int eachcol = 0;
    int eachsize = 0;

    while ( *buffer) {
        if ( '\n' == *buffer) {
            ++eachrow;
            eachcol = 0;
            eachsize = 0;
        }
        else if ( '\t' == *buffer) {
            ++eachcol;
            eachsize = 0;
        }
        else {
            ptr[eachrow][eachcol][eachsize] = *buffer;
            ++eachsize;
            ptr[eachrow][eachcol][eachsize] = 0;
        }
        ++buffer;
    }
}

int main ( void) {
    char line[] = "12\t34\t56\t78\t!@#\n"
    "abc\tdef\tghi\tjkl\t$%^\n"
    "mno\tpqr\tstu\tvwx\tyz\n"
    "ABC\tDEF\tGHI\tJKL\tMNOPQ\n";
    int rows = 0;
    int columns = 0;
    int size = 0;

    getdimension ( line, &rows, &columns, &size);
    printf ( "rows %d cols %d size %d\n", rows, columns, size);

    char (*ptr)[columns][size] = NULL;//pointer to variable length array

    createptr ( rows, columns, size, &ptr);

    parsebuffer ( line, rows, columns, size, ptr);

    for ( int row = 0; row < rows; ++row) {
        for ( int col = 0; col < columns; ++col) {
            printf ( "ptr[%d][%d] %s\n", row, col, ptr[row][col]);
        }
    }

    free ( ptr);

    return 0;
}