C语言 如何在循环中创建节点并将它们插入链表



这是我的结构:

typedef struct gene{
char* name;
int length;
int* sequence;
} gene;
typedef struct genes{
gene gene;
struct genes* next;
} genes;

构造 函数:

genes* createGenes(gene newGene){
genes* geneArr = malloc(sizeof(genes));
if (NULL != geneArr){
geneArr->gene = newGene;
geneArr->next = NULL;
}
return geneArr;
}
void deleteGenes(genes* geneArr){
if(NULL != geneArr->next){
deleteGenes(geneArr->next);
}
free(geneArr);
}
genes* addGene(genes* geneList, gene newGene){
genes* toAdd = createGenes(newGene);
if (NULL != toAdd){
geneList->next = toAdd;
}
return geneList;
}

和一个函数(它创建一个具有给定长度的序列。对于 5 ->{2, 2, 2, 2, 2}):

gene twosGene(char* name, int length){
gene newGene;
newGene.name = name;
newGene.length = length;
newGene.sequence = (int*)malloc(sizeof(int) * length);
for(int i = 0; i < length; i++){
newGene.sequence[i] = 2;
}
return newGene;
}

这是我的main()函数:

int main(){
int count = 1;
genes* geneArr = createGenes(twosGene("gene1", count++));
for (int i = 0; i < 4; ++i) {
geneArr = addGene(geneArr, twosGene("geneLoop", count++));
}
genes* iter;
for (iter = geneArr; NULL != iter; iter = iter->next) {
printf("gene=%dn", iter->gene.length);
free(iter->gene.sequence);
}
deleteGenes(geneArr);
return 0;
}

我希望这个输出:

gene=1
gene=2
gene=3
gene=4
gene=5

但相反,我得到了这个:

gene=1
gene=5

此外,当我使用Valgrind时,我的程序中也有一些泄漏。

==20580== HEAP SUMMARY:
==20580==     in use at exit: 132 bytes in 6 blocks
==20580==   total heap usage: 11 allocs, 5 frees, 1,244 bytes allocated

我想不通为什么。感谢您的帮助。

在此函数中

genes* addGene(genes* geneList, gene newGene){
genes* toAdd = createGenes(newGene);
if (NULL != toAdd){
geneList->next = toAdd;
}
return geneList;
}

您始终覆盖最初在语句中创建的节点旁边的数据成员

genes* geneArr = createGenes(twosGene("gene1", count++));

您似乎想在当前列表的末尾添加一个新节点。在这种情况下,函数将如下所示

genes* addGene(genes* geneList, gene newGene){
genes* toAdd = createGenes(newGene);
if (NULL != toAdd){
genes *current = geneList;
while ( current->next != NULL ) current = current->next;
current->next = toAdd;
}
return geneList;
}

但是,通常即使此函数定义也是无效的,因为最初geneList可以等于 NULL。因此,使用您的方法应按以下方式重写函数

genes* addGene(genes* geneList, gene newGene){
genes* toAdd = createGenes(newGene);
if (NULL != toAdd){
if ( geneList == NULL )
{
geneList = toAdd;
}
else
{
genes *current = geneList;
while ( current->next != NULL ) current = current->next;
current->next = toAdd;
}
}
return geneList;
}

但是,如果将指针传递到列表的头部指针,也可以改进此函数实现。

例如

int addGene( genes **geneList, gene newGene )
{
genes* toAdd = createGenes(newGene);
int success = toAdd != NULL;
if ( success )
{
while ( *geneList != NULL ) geneList = &( *geneList )->next;
*geneList = toAdd;
}
return success;
}

在这种情况下,可以像这样调用函数

genes* geneArr = createGenes(twosGene("gene1", count++));
for (int i = 0; i < 4; ++i) {
addGene( &geneArr, twosGene("geneLoop", count++));
}

在:

genes* geneArr = createGenes(twosGene("gene1", count++));
for (int i = 0; i < 4; ++i) {
geneArr = addGene(geneArr, twosGene("geneLoop", count++));
}

第一个分配列表的负责人。在 for 循环中,接下来每次迭代都会覆盖此头部。你应该/可以做:

genes* geneArr = createGenes(twosGene("gene1", count++));
genes *geneNext= geneArr;
for (int i = 0; i < 4; ++i) {
geneNext = addGene(geneNext, twosGene("geneLoop", count++));
}

此外,addGene必须前进指针才能使上述操作正常工作。

genes* addGene(genes* geneList, gene newGene){
genes* toAdd = createGenes(newGene);
if (NULL != toAdd){
geneList->next = toAdd;
genelist= geneList->next;  // add this statement.
}
return geneList;
}

现在你可以打印它,因为你还有头。

addGene函数不会添加到列表的末尾。它只是将新基因与第一个基因联系起来。正如Valgrind报道的那样,列表中第一个基因之后的任何东西都被"遗忘",导致记忆泄漏。

以下是应该可以工作的addGenes函数的更新版本:

genes* addGene(genes* geneList, gene newGene){
genes* toAdd = createGenes(newGene);
if (NULL != toAdd){
if (geneList == NULL){
geneList = toAdd;
} else {
genes *last = geneList;
while (last->next != NULL){
last = last->next;
}
last->next = toAdd;
}
}
return geneList;
}

最新更新