0

我是 C 的新手,但正在从事一个将从数据库中检索呼叫日志信息的项目。在我尝试在实际程序中实现它之前,我正在尝试制作一个测试应用程序,以便我可以通过手动将一些静态数据添加到结构中来确保逻辑是正确的。

呼叫日志将保存呼入呼叫段的详细信息,例如电话号码和持续时间等,并且在该结构中列出了一个链接,其中包含 1 个或多个呼出段。

据我所知,当我单步执行 GDB 中的代码时,我似乎正确地插入了数据,但我相信的问题是当我尝试构建一个字符串以写入文件时。

在导出过程中,它应该循环遍历结构,为入站支路详细信息创建一串逗号分隔值,然后从结构内的链表中检索每个出站支路,并创建另一个逗号分隔值字符串。

一旦我有了与入站腿关联的所有腿,然后我将这两个入站腿字符串和出站腿字符串写入一个 CSV 文件。

除了一个问题之外,这更多的是一种更少的工作。如果入站支路有 2 个出站支路,则在将其写入文件时,仅显示最后一个出站支路,第一个出站支路不写入文件。

下面是我的结构是如何定义的。

typedef struct CallLogStructure
{
    char * date;
    char * time;
    char * bParty;
    char * aParty;
    float duration;
    char * cleardownCause;
    struct Node *outBoundLegs;
} callLogStructure;

typedef struct Node
{
    char * target;
    float targetDuration;
    char * targetCleardownCause;
    struct Node *next;
}node;

下面是我如何设置入站呼叫的数据并调用函数将出站支路插入到链表中。

callLogStructure * callLog = NULL;
    node *temp = NULL;
    int dataRow = 0;

    callLog = malloc(dataRow+2 * sizeof(*callLog));
    //start = (node*)malloc(sizeof(node));
    callLog[dataRow].outBoundLegs = NULL;
    callLog[dataRow].outBoundLegs = (node*)malloc(sizeof(node));
    if (callLog[0].outBoundLegs == NULL)
    {
        printf("Failed to allocate RAM\n");
    }
    temp = callLog[dataRow].outBoundLegs;
    temp->next = NULL;
    callLog[dataRow].outBoundLegs->target = NULL;
    callLog[dataRow].outBoundLegs->targetDuration = 0;
    callLog[dataRow].outBoundLegs->targetCleardownCause = strdup("0");

    //Insert first inbound leg
    callLog[dataRow].date = "16/05/2011";
    callLog[dataRow].time = "00:00:03";
    callLog[dataRow].aParty = "1234";
    callLog[dataRow].bParty = "5678";
    callLog[dataRow].duration = 0;
    callLog[dataRow].cleardownCause = "unanswered";

    outboundTarget = strdup("4321");
    outboundDuration = 0;
    outboundCleardown = strdup("Unanswered");

    //insertOutBoundLeg(&callLog[0].outBoundLegs, outboundTarget, outboundDuration, outboundCleardown);
    insertOutBoundLeg(callLog, outboundTarget, outboundDuration, outboundCleardown, dataRow);

    //Insert secord inbound
    dataRow++;
    callLog[dataRow].outBoundLegs = NULL;
    callLog[dataRow].outBoundLegs = (node*)malloc(sizeof(node));
    //temp = callLog[0].outBoundLegs;
    //temp->next = NULL;
    callLog[dataRow].outBoundLegs->target = NULL;
    callLog[dataRow].outBoundLegs->targetDuration = 0;
    callLog[dataRow].outBoundLegs->targetCleardownCause = strdup("0");

    callLog[dataRow].date = "16/05/2011";
    callLog[dataRow].time = "00:00:58";
    callLog[dataRow].aParty = "6789";
    callLog[dataRow].bParty = "9876";
    callLog[dataRow].duration = 0;
    callLog[dataRow].cleardownCause = "unanswered";

    outboundTarget = strdup("654321");
    outboundDuration = 0;
    outboundCleardown = strdup("unanswered");

    insertOutBoundLeg(callLog, outboundTarget, outboundDuration, outboundCleardown, dataRow);

    outboundTarget = strdup("87654");
    outboundDuration = 10;
    outboundCleardown = strdup("answered");

    insertOutBoundLeg(callLog, outboundTarget, outboundDuration, outboundCleardown, dataRow);
        //printf("NEWLY INSERTED OUTBOUND TARGET: %s", callLog[0].outBoundLegs[0].target);

    writeToFile(callLog, dataRow+1);

下面是将数据写入链表的函数

void insertOutBoundLeg(callLogStructure *callLog, char * target, float targetDuration, char * targetCleardownCause, int callLogIndex)
{
    if (callLog[callLogIndex].outBoundLegs->target == NULL)
    {
        printf("INSERTING BRAND NEW OUTBOUND LEG FOR INBOUND\n");
        callLog[callLogIndex].outBoundLegs->target = strdup(target);
        callLog[callLogIndex].outBoundLegs->targetDuration = targetDuration;
        callLog[callLogIndex].outBoundLegs->targetCleardownCause = strdup(targetCleardownCause);
        callLog[callLogIndex].outBoundLegs->next = NULL;
    }
    else
    {
        printf("INSERTING SECOND OR MORE OUTBOUND LEG\n");
        while (callLog[callLogIndex].outBoundLegs->next != NULL)
        {
            callLog[callLogIndex].outBoundLegs = callLog[callLogIndex].outBoundLegs->next;
        }
        callLog[callLogIndex].outBoundLegs->next = (node *)malloc(sizeof(node));
        callLog[callLogIndex].outBoundLegs = callLog[callLogIndex].outBoundLegs->next;
        callLog[callLogIndex].outBoundLegs->target = strdup(target);
        callLog[callLogIndex].outBoundLegs->targetDuration = targetDuration;
        callLog[callLogIndex].outBoundLegs->targetCleardownCause = strdup(targetCleardownCause);
        callLog[callLogIndex].outBoundLegs->next = NULL;
    }
}

下面是将数据写入文件的函数。

void writeToFile(callLogStructure * callLog, int maxRecords)
{
    FILE * myFile;
    myFile = fopen("legs.csv", "wb");
    char * inboundLegFileString = "0";
    char * outboundLegFileString = "0";
    //inboundLegFileString = malloc(sizeof(char *));
    //outboundLegFileString = malloc(sizeof(char *));

    if (callLog == NULL)
    {
        printf("No inbound legs\n");
        return;
    }

    int i = 0;
    for (i = 0; i < maxRecords; i++)
    {
        asprintf(&inboundLegFileString, "\"%s\",\"%s\",\"%s\",\"%s\",\"%.1f\",\"%s\"",
                callLog[i].date, callLog[i].time, callLog[i].aParty, callLog[i].bParty,
                callLog[i].duration, callLog[i].cleardownCause);

        //printf("Outbound Target: %s\n", callLog[0].outBoundLegs->target);

        while (callLog[i].outBoundLegs != NULL)
        {
            if (callLog[i].outBoundLegs->target != NULL)
            {
                asprintf(&outboundLegFileString, "%s,\"%s\",\"%.1f\",\"%s\"", outboundLegFileString,
                    callLog[i].outBoundLegs->target, callLog[i].outBoundLegs->targetDuration,
                    callLog[i].outBoundLegs->targetCleardownCause);
            }
            callLog[i].outBoundLegs = callLog[i].outBoundLegs->next;
        }
        fprintf(myFile, "%s%s\n", inboundLegFileString, outboundLegFileString);
        inboundLegFileString = "";
        outboundLegFileString = "";
    }
            fclose(myFile);
    return;
}

更新 我在插入函数中添加了一些更多的调试,所以虽然当我单步执行它时看起来我在做正确的事情,但如果我在我仍然只得到最后一个出站腿之后尝试循环插入的内容.

下面是我添加的

node * outBoundLeg;
    for (outBoundLeg = callLog[callLogIndex].outBoundLegs; outBoundLeg != NULL; outBoundLeg = outBoundLeg->next)
    {
        printf("INSERT: %s\n", outBoundLeg->target);
    }

该 printf 语句仅显示插入到列表中的最后一个出站目标编号,而不是之前的那个,所以我不知道我是否添加错了,或者我的指针是否错误,所以我一直在寻找结尾。

4

1 回答 1

0

主要问题在于insertOutBoundLeg函数。当您分配第二个出站支路时,您更新根指针(outBoundLegs成员)以指向新节点,从而丢失第一个节点。

callLog[callLogIndex].outBoundLegs = callLog[callLogIndex].outBoundLegs->next;

您应该使用临时指针来查找列表中的最后一个节点,然后为新节点设置数据。

所以插入第二条腿的代码应该是这样的:

printf("INSERTING SECOND OR MORE OUTBOUND LEG\n");
struct Node *tempLeg = callLog[callLogIndex].outBoundLegs;
while (tempLeg->next != NULL)
{
    tempLeg = tempLeg->next;
}
tempLeg->next = (node *)malloc(sizeof(node));
tempLeg = tempLeg->next;
tempLeg->target = strdup(target);
tempLeg->targetDuration = targetDuration;
tempLeg->targetCleardownCause = strdup(targetCleardownCause);
tempLeg->next = NULL;

另一个问题在于您的writeToFile函数。您用“0”初始化输出字符串,这几乎肯定不是您想要的。

char * inboundLegFileString = "0";
char * outboundLegFileString = "0";

假设应该是:

char * inboundLegFileString = "";
char * outboundLegFileString = "";

否则,您将在 csv 的入站和出站腿之间有一个不需要的零。

我还建议您考虑更新writeToFile函数以在遍历出站腿时使用临时指针,因为它与insertOutBoundLegs函数有相同的问题。您将再次覆盖您的根指针(outBoundLegs成员)。

callLog[i].outBoundLegs = callLog[i].outBoundLegs->next;

该代码有效,但它只会有效一次。

最后,我应该提到,在调用insertOutBoundLeg之前初始化outboundTargetoutboundCleardown变量时,您对strdup进行了不必要的调用。

outboundTarget = strdup("4321");           // this strdup not needed
outboundDuration = 0;
outboundCleardown = strdup("Unanswered");  // this strdup not needed

insertOutBoundLeg函数无论如何都会对这些参数进行strdup,因此字符串最终会被复制两次,这可能会导致内存泄漏。

于 2013-07-22T09:56:28.010 回答