我需要一个包含动态数量的字符数组的字符数组,这些数组基于特定文件夹中的文件数量。我能够通过初始化来实现这一目标
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH]
然后在我知道另一个函数发现了多少个文件(未提供)之后再使用FullPathNames = malloc( sizeof(*FullPathNames) * NumOfFiles * MAX_FILENAME_AND_PATHNAME_LENGTH ) )
。这个过程完美无瑕。
我只能使用ANSI C;我特意使用LabWindows CVI 8.1来编译我的代码。我不能使用任何其他编译器。
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH];
size_t Size;
NumOfFiles = NumberOfUserFiles(“*.txt”, “C:\\ProgramData” );
FullPathNames = malloc( sizeof(*FullPathNames) * NumOfFiles * MAX_FILENAME_AND_PATHNAME_LENGTH ) );
Size = sizeof(*FullPathNames) * NumOfFiles;
Memset(FullPathNames,0,Size);
上面的代码正在做我想要的。我可以使用以下代码轻松填充此数组:
Strcpy(FullPathNames[0],”Test Word”);
我的问题如下。我希望能够将FullPathNames
(一个指向可变数量的字符数组的指针数组)传递给方法。我希望此方法能够删除给定索引处的单个字符数组字符数组。该方法存在的结果是FullPathNames
不再包含索引处的给定字符数组。我已成功完成将FullPathNames传递给方法,以便为其添加字符串。我不需要帮助创建数组。我有那个部分在工作。 我的问题仅限于我尝试修改传递给Remove_Element方法的char指针时发生的行为。
下面的代码没有完成,它有一些问题,但在编写它的过程中,我发现了关于指针如何在C中工作的知识差距。我对被告知这些问题不感兴趣除了我发现的问题之外,我还可以解决其他问题。我发现虽然我能够在方法中修改数组本身,但我无法替换它,我正在努力找到一种方法。
我使用以下代码调用该方法。
Remove_Element(FullPathNames,1, NumOfFiles);
我对目前的情况的期望是FullPathNames的原始数据保留,除了我删除的索引,通过从index + 1
复制数据,FullPathNames中包含的原始指针当然更新。由于我也想缩小数组,我试图将数组设置为等于新数组。以下信息说明了我尝试调试此行为。
当我输入方法时,监视变量会显示以下信息。
FullPathNames = XXXXXX
NewArray = Unallocated
Array = XXXXXX
填写新临时数组后,会发生以下情况:
FullPathNames = XXXXXX
NewArray = YYYYY
Array = XXXXXX
当我退出方法时,会发生以下情况:
FullPathNames = XXXXXX
NewArray = YYYYY
Array = YYYYY
我试图通过将其作为指针传递来修改FullPathNames
。我最初使用 realloc 尝试了此任务,但这只是导致了一个空闲指针异常。我相信我理解发生的原因。
我已经确认我实际上通过在初始化FullPathNames
的原始代码块中打印包含它的字符串来修改FullPathNames
中包含的指针。为了填充数组,我将FullPathNames
作为参数传递给调用此 Remove_Element 方法的方法。到目前为止,一切都在起作用,我的预期是如何工作的,除了,我似乎无法修改堆栈上的原始变量。 我相信我可以完成我想要的东西?如果我能理解我无法修改堆栈中的原始变量的原因,我可能能够自己弄明白,那是什么误解和/或 如何以有效的方式实现这一目标?一旦我理解,我可以提供更多的问题澄清,不清楚,我不能发布这个问题从代码所在的位置开始,可能需要一段时间才能完成。
void Remove_Element( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN], int Index, int Array_Length )
{
int i;
char String[MAX_FILENAME_AND_PATHNAME_LEN];
char (*NewArray)[MAX_FILENAME_AND_PATHNAME_LEN];
int NewLength = Array_Length - 1;
size_t Size;
NewArray = malloc( sizeof( *NewArray) * NewLength * ( MAX_FILENAME_AND_PATHNAME_LEN ) );
Size = sizeof( *NewArray ) * NewLength;
memset(NewArray, 0, Size);
for ( i = Index; i < Array_Length - 1; i++ )
{
memcpy(String,Array[i+1],MAX_FILENAME_AND_PATHNAME_LEN); // Remove last index to avoid duplication
strcpy( Array[Index], String );
}
Array = NewArray;
}
注意: MAX_FILENAME_AND_PATHNAME_LENGTH = 516;
由于一些反馈,我的最终问题似乎并不清楚。我想了解我可以修改传入方法的原始数组内容的原因,但我无法用另一个数组替换该数组。如果我可以填补我的理解,我可以自己找出解决方案。
答案 0 :(得分:4)
如果我理解正确,您要做的是修改初始化原始数组的代码部分中的FullPathNames指针。
声明FullPatchNames
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH]
你基本上声明了一个指向MAX_FILENAME_AND_PATHNAME_LENGTH字符元素数组的指针。通过调用void Remove_Element(...)
,您只需将此指针的副本提供给函数内有效的局部变量Array
。由于这个Array = NewArray;
,只更改函数内部指针的本地副本,而不是FullPathNames
。
如果要更改FullPathNames
的值,则必须指向指向函数的指针。 Remove_Element
的原型必须如下所示:
void Remove_Element( char (**Array)[MAX_FILENAME_AND_PATHNAME_LEN],
int Index, int Array_Length )
现在,Array是指向(一个dimansional)char数组的指针。通过取消引用此指针,您可以更改原始指针FullPathNames以指向您在函数内创建的新对象。您必须将对此功能的调用修改为Remove_Element(&FullPathNames,1, NumOfFiles);
。要从Array读取,必须使用*运算符取消引用它:
memcpy(String,*Array[i+1],MAX_FILENAME_AND_PATHNAME_LEN);
...
Array = NewArray;
警告:此代码现在会产生内存泄漏,因为您丢失了对orignal对象的引用。您应该使用代码中某处的free()函数删除它!
答案 1 :(得分:2)
在C语言中,似乎首先缺乏对语法的了解。
select table1.something,
table2.somethingelse,
table3.somethingelse2
From Table1,
Table2,
Table3
Where Table1.ColumnID in ('ID1','ID2','ID3')
And Table1.SomeColumn = Table2.SomeColumn
And Table2.AnotherColumn = Table3.AnotherColumn
这是一个例子。此处显示的语法将由c程序员读取为:
char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH]
或者他想要char *FullPathNames;
嗯...... 所以这里是第101个:
char FullPathNames[MAX_FILENAME_AND_PATH_NAME_LENGTH];
取决于char foo[50]; // A fixed size array with capacity 50 (49 chars + '\0' max).
char *foo = NULL; // a uninitialized pointer to some char.
char (*foo)(); // a pointer to a function of signature: char(void).
char *foobar[50]; // This is an array of 50 pointers to char.
所在的位置(在代码文件中,在函数中,在结构定义中),用于它的存储会有所不同。
char foo[50];
现在我们了解了基础知识,让我们看看二维动态数组
char foo1[50]; // zerovars section.
char foo2[50] = { 0 }; // initvars section
char foo3[50] = "Hello World!"; // also initvars section
void FooTheFoo( const char *foo )
{
if(NULL != foo )
{
printf("foo = %s\n", foo);
}
}
int main(int argc, const char *argv[])
{
char bar[50] = "Message from the past."; // bar is located on the stack (automatic variable).
FooTheFoo(bar); // fixed size array or dynamic array - passed as a (const pointer) in C.
return 0;
}
指向char指针的指针。或指向字符指针数组的指针或指向字符数组指针的指针数组。
如上所述,没有&#34; meta&#34;关于char **matrix = NULL;
或char*
指向的内容的信息,最终取消引用的项目将是char类型。而且它是指向指针的指针。
如果你想从中制作一个二维数组,你必须相应地进行初始化:
char **
最后,至少,如何将这样的二维数组传递给函数?由于char **构造不包含关于大小的元信息,在一般(内部不是0终止的字符串)的情况下,你会这样做:
const size_t ROW_COUNT = 5;
const size_T COL_COUNT = 10;
char **myMatrix = malloc(sizeof(char *) * ROW_COUNT);
// check if malloc returned NULL of course!
if( NULL != myMatrix )
{
for(size_t row = 0; row < ROW_COUNT; row++ )
{
myMatrix[row] = malloc(sizeof(char) * COL_COUNT);
if( NULL == myMatrix[row] ) PanicAndCryOutLoudInDespair();
for(size_t col = 0; col < COL_COUNT; col++ )
{
myMatrix[row][col] = 0;
}
// of course you could also write instead of inner for - loop:
// memset(myMatrix[row], 0, sizeof(char) * COL_COUNT);
}
}
最后,如果您想再次摆脱2D动态数组,则需要正确释放它。
void FooIt( const char **matrix, size_t rowCount, size_t colCount )
{ // Note: standard checks omitted! (NULL != matrix, ...)
putchar(matrix[0][0]);
}
关于它我唯一要说的是我留给其他温和的贡献者。我想到的一件事就是如何正确地表达那些多维事物的持久性。
void Cleanup2DArray( char **matrix, size_t rowCount )
{
for(size_t row = 0; row < rowCount; row++ )
{
free(matrix[row];
}
free(matrix);
}
有了这个,您应该能够找到代码中出错的地方并修复它。
答案 2 :(得分:1)
您传递的指针只是一个值。它拥有一个地址意味着您可以取消引用它来修改指向的内容,但这并不意味着直接更改其值(您的赋值语句)将影响调用者参数。与C中的其他所有内容一样,如果您想通过地址修改某些内容,那么地址就是您需要执行的操作。如果你正在修改的东西是指针,那么指针的地址(通过指向指针的参数)就是通常规定的解决方案。
但是,我可以告诉你这样做的语法和管家是......在你的情况下没有意义。一个简单的指针很容易,但指向数组的指针并不那么简单。如果我是他,他只会使用函数本身的返回结果,否则当前正在使用该函数void
。像这样声明你的函数:
char (*Remove_Element( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN],
int Index, int Array_Length ))[MAX_FILENAME_AND_PATHNAME_LEN]
{
....
return Array; // or whatever else you want to return so
// long as the type is correct.
}
只需让来电者这样做:
Array = RemoveElement(Array, Index, Array_Length);
答案 3 :(得分:-2)
我最终不得不做一个Sascha建议在方法的参数中使用char **Array)[MAX_FILENAME_AND_PATHNAME_LEN]
的变体。
我的解决方案的工作变体如下所示。我必须这样做的原因是因为虽然我能够解除引用(**Array)[MAX_FILENAME_AND_PATHNAME_LEN]
我只能修改数组中的第一个字符串数组。
数组已初始化并填充了类似于以下内容的内容。
阵列
- 字符串1
- 字符串2
- 字符串3
- 字符串4
我可以访问字符串1 而*Array[0]
没有任何问题,但字符串2 不是*Array[1]
,因为我的想法是克隆和替换删除索引后的数组我无法使用它。
我复制代码以便发布此答案后修复的唯一已知问题是for循环将跳过新数组中的索引(0,1,2,3等)并且错误地不填充它有数据。生成的数组将替换原始数组。此方法仅适用于初始化要替换的数组的初始代码块。
#define MAX_FILENAME_AND_PATHNAME_LEN MAX_FILENAME_LEN + MAX_PATHNAME_LEN
/*
This method was designed to free the memory allocated to an array.
*/
void FreeFileAndPathArrays( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN] )
{
free( Array );
}
/*
This method was designed to remove an index from an array. The result of this method will shrink the array by one.
*/
void Remove_Element( char (**ArrayPointer)[MAX_FILENAME_AND_PATHNAME_LEN],int Index, int *Array_Length, char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN] )
{
int i = 0;
int j = 0;
char String[MAX_FILENAME_AND_PATHNAME_LEN];
char (*NewArray)[MAX_FILENAME_AND_PATHNAME_LEN];
char (*GC)[MAX_FILENAME_AND_PATHNAME_LEN];
int Length = *Array_Length;
int NewLength = Length - 1;
size_t Size;
NewArray = malloc( sizeof( *NewArray) * NewLength * ( MAX_FILENAME_AND_PATHNAME_LEN ) );
Size = sizeof( *NewArray ) * NewLength;
memset(NewArray, 0, Size);
UI_Display("Test Block:");
for ( j = 0; j < NewLength; j++ )
{
if ( j != Index )
{
memcpy(String,Array[j],MAX_FILENAME_AND_PATHNAME_LEN);
strcpy( Array[Index], String );
Fill(NewArray,String,j);
UI_Display(String);
}
}
GC = Array;
*ArrayPointer = NewArray;
free(GC);
*Array_Length = *Array_Length - 1;
}
/*
This method was designed to place a string into an index.
*/
void Fill( char (*Array)[MAX_FILENAME_AND_PATHNAME_LEN], const char * String, int Index)
{
strcpy( Array[Index], String );
}
/*
This method was designed to place fill each string array contained within the array of string arrays with 0's.
*/
void PrepareFileAndPathArrays( char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LEN], int ROWS )
{
size_t Size;
Size = sizeof( *FullPathNames ) * ROWS;
memset(FullPathNames, 0, Size);
}