【问题标题】:Append an element to the end of a Circular Linked List with this particular function使用此特定功能将元素附加到循环链接列表的末尾
【发布时间】:2015-07-11 15:45:34
【问题描述】:

我会尽量说清楚。

我在一个名为“esercizio.h”的文件中有这个结构(由于我的老师,我无法更改它):

#ifndef ESERCIZIO_H
#define ESERCIZIO_H

struct ElemSCL{
    int info;
    struct ElemSCL* next;
};

typedef struct ElemSCL NodoSCL;
typedef NodoSCL* TipoSCL;

void accoda(TipoSCL* pscl, int i);
#endif

函数“accoda”必须将一个元素 (int i) 添加到循环链表的末尾(由 TipoSCL* pscl 指向)。我试图在一个名为“esercizio.c”的文件中编写函数体:

#include <stdio.h>
#include <stdlib.h>
#include "esercizio.h"

void accoda(TipoSCL* pscl, int i){
    NodoSCL* temp = (NodoSCL*) malloc(sizeof(NodoSCL));
    temp->info = i;
    temp->next = temp;
    if (pscl == NULL){
        return;}
    while ((*pscl)->next != *pscl){
        *pscl = (*pscl)->next;}
    (*temp)->next = (*pscl)->next; //Problems starts here
    (*pscl)->next = *temp;
    }

正如我在代码中让您注意到的,如果我不添加最后两行,一切都会好起来的。如果函数中没有 TypeSCL* 而是 NodeSCL* 我会使用:

temp->next = pscl->next;
pscl->next = temp;}

但我的老师决定使用 TypeSCL* pscl 而不是 NodeSCL* pscl。

我有一个“test.h”文件...

#include "esercizio.h"

#ifndef TEST_H
#define TEST_H

char* toString(TipoSCL scl);

#endif

... 和一个“test.c”文件,其中包含 main() 函数和所有让我检查我的代码是否正常工作的输入:

#include <stdlib.h>
#include <string.h>
#include "../libtest/libtest.h"
#include "test.h"
#include "esercizio.h"


const int NTEST=5;

TipoSCL input[5];
int add[5] = {1,2,3,4,5};
TipoSCL expected[5];


int main(int argc, char** argv){


    input[0] = NULL;

    input[1] = (TipoSCL) malloc(sizeof(NodoSCL));
    input[1] -> info = 1;
    input[1] -> next = input[1];

    input[2] = (TipoSCL) malloc(sizeof(NodoSCL));
    input[2] -> info = 1;
    input[2] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    input[2] -> next -> info = 2;
    input[2] -> next -> next = input[2];

    input[3] = (TipoSCL) malloc(sizeof(NodoSCL));
    input[3] -> info = 1;
    input[3] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    input[3] -> next -> info = 2;
    input[3] -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    input[3] -> next -> next -> info = 3;
    input[3] -> next -> next -> next = input[3];

    input[4] = (TipoSCL) malloc(sizeof(NodoSCL));
    input[4] -> info = 1;
    input[4] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    input[4] -> next -> info = 2;
    input[4] -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    input[4] -> next -> next -> info = 3;
    input[4] -> next -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    input[4] -> next -> next -> next -> info = 4;
    input[4] -> next -> next -> next -> next = input[4];

    expected[0] = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[0] -> info = 1;
    expected[0] -> next = expected[0];

    expected[1] = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[1] -> info = 1;
    expected[1] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[1] -> next -> info = 2;
    expected[1] -> next -> next = expected[1];

    expected[2] = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[2] -> info = 1;
    expected[2] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[2] -> next -> info = 2;
    expected[2] -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[2] -> next -> next -> info = 3;
    expected[2] -> next -> next -> next = expected[2];

    expected[3] = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[3] -> info = 1;
    expected[3] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[3] -> next -> info = 2;
    expected[3] -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[3] -> next -> next -> info = 3;
    expected[3] -> next -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[3] -> next -> next -> next -> info = 4;
    expected[3] -> next -> next -> next -> next = expected[3];

    expected[4] = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[4] -> info = 1;
    expected[4] -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[4] -> next -> info = 2;
    expected[4] -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[4] -> next -> next -> info = 3;
    expected[4] -> next -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[4] -> next -> next -> next -> info = 4;
    expected[4] -> next -> next -> next -> next = (TipoSCL) malloc(sizeof(NodoSCL));
    expected[4] -> next -> next -> next -> next -> info = 5;
    expected[4] -> next -> next -> next -> next  -> next = expected[4];




    test_reset();

    for (int i = 0; i < NTEST; i++) {
        print_test_start(i+1);
        printf("Funzione: accoda\n");
        printf("Input: %s\n", toString(input[i]));

        accoda(&input[i],add[i]);

        test_compare_strings(toString(expected[i]),toString(input[i]));

        print_test_end();
        print_n_success("#Test superati: ");
    }
    print_test_result("Percentuale test corretti:");
}


char* toString(TipoSCL scl){
    char* res = (char*) malloc(200*sizeof(char));
    res[0] = '[';
    res[1] = '\0';
    TipoSCL aux = scl;
    if (aux != NULL) {
        char buf[10];
        do{
            sprintf(buf,"%d->",aux -> info);
            strcat(res,buf);
            aux = aux -> next;
        }
        while(aux != scl);
        sprintf(buf,"|%d",aux -> info);
        strcat(res,buf);
        aux = aux -> next;
    }
    strcat(res,"]");
    return res;
}

“如果我不将最后两行添加到代码中,一切正常”是什么意思? 当我在没有

的情况下运行我的程序时(感谢终端和 cd make
(*temp)->next = (*pscl)->next; //Problems starts here
(*pscl)->next = *temp;

测试运行没有问题(当然,它说我没有一个正确的结果。但是如果我将这两行添加到我的代码中,我会得到“分段错误:11”。

【问题讨论】:

  • 根据您调用add 的方式,*pscl 可能指向列表的head。除此之外,当你说“事情出错了......”时,你的意思是什么?你能详细说明一下吗?你有构建错误吗?运行时错误?意外行为?什么?请尝试创建一个Minimal, Complete, and Verifiable Example 并向我们展示,包括您如何调用add 函数以及您传递的参数。
  • temp-&gt;next = temp; 这行是不必要的,因为接下来您要做的就是再次更改 temp->next。此外,由于 *pscl 也是一个指针,因此最好检查它是否为空。我会将if(pscl == NULL) 更改为if(pscl == NULL || *pscl == NULL)
  • 标准警告:不要像 malloc 和朋友使用的那样投射 void *
  • 为指针创建类型通常是个坏主意。这使得代码阅读起来更加复杂并增加了混乱,因为您必须记住额外的间接性。最好为指针变量显式添加*
  • 好吧,如果你必须添加到列表的末尾,你不应该使用while循环遍历到最后一个节点吗?该列表可能会超过大小 2

标签: c list linked-list circular-list


【解决方案1】:

尝试将您的添加功能更改为此 ::

void add(TypeSCL* pscl, int i){
    NodeSCL* temp = (NodeSCL*) malloc(sizeof(NodeSCL));
    temp->info = i;
    temp->next = temp;
    if (*pscl == NULL){
    *pscl = temp;
        return;} 
    NodeSCL *tempCheck = *pscl;
    while(tempCheck->next != *pscl) {
        tempCheck = tempCheck->next;
    }
    tempCheck->next = temp;
    temp->next = (*pscl); 
}

你做错的事情:: 您需要意识到 C 中的所有内容都是按值传递的,因此如果您传递一个指针,则该指针也是按值传递的。所以,当你的老师告诉你使用TypeSCL* pscl时,它的意思是NodeSCL **pscl,她是对的,因为你不能用NodeSCL *pscl这样做,这可能有助于你理解我为什么这样说::What is the reason for using a double pointer when adding a node in a linked list?

此外,在您的情况下,pscl == NULL 首先应该是 *pscl == NULL,您需要将您的 *pscl 设置为您的新节点。

接下来,如果你想在最后添加一个新节点,你应该使用一个 while 循环,正如@Neha Chauhan 提到的那样。

接下来,您使用的最后两个语句 ::

(*temp)->next = (*pscl)->next;
(*pscl)->next = *temp;

您将新添加节点的next 设置为链表的第二个元素,这没有任何意义。

我已经使用变量NodeSCL *tempCheck 移动到链表的最后一个节点!

所以,最后两行应该看起来像

tempCheck->next = temp;
temp->next = (*pscl); 

最后,兄弟,您需要使用指针来提高基础知识。 (别介意!)

编辑::

为什么你的测试没有最后两行 :: 因为,在你编写的代码中,你的链表总是大小为 1,在第一个元素之后没有添加任何元素!所以,测试运行了,但是失败了!

【讨论】:

  • 谢谢老哥,现在程序可以正常运行了!我会尝试看一些关于指针的指南,我真的很困惑。
  • 检查我提到的链接,这可能会有所帮助!
  • 再次感谢您!附言cout 未声明使用,所以我删除了行 'cout info
  • cout用于c++终端打印,调试时误放在那里!
【解决方案2】:

我认为您的 pscl 指针必须到达链接列表的末尾,然后它应该插入 temp 元素。 你能做的是

    void add(TypeSCL* pscl, int i){
    NodeSCL* temp = (NodeSCL*) malloc(sizeof(NodeSCL));
    temp->info = i;
    temp->next = temp;
    if (pscl == NULL){
    return;
    while(pscl->next != pscl)
    pscl = pscl->next;
    temp->next = (*pscl)->next; //THINGS GO WRONG HERE...
    (*pscl)->next = temp;       //...AND HERE
     }

'

【讨论】:

    猜你喜欢
    • 2012-09-12
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    相关资源
    最近更新 更多