如何修改函数内部的多维指针?
How modify a multidimensional pointer inside a function?
我有一个使用 malloc
和 memcpy
以这种方式操作 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;
}
我有一个使用 malloc
和 memcpy
以这种方式操作 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;
}