2013-07-18 42 views
0

我是C新手,但正在研究一个项目,该项目将从数据库中检索呼叫日志信息。在我尝试在真实程序中实现这个功能之前,我正在试着制作一个测试应用程序,以便我可以通过手动添加一些静态数据来确保逻辑正确。从结构中的链接列表导出数据

呼叫日志将保持所述呼入呼叫支路的信息,如电话号码和持续时间等等,并且结构内没有列出其含有1个或多个出站腿的链接。

我会正确显示,据我可以从我通过GDB单步执行代码,但是我相信这个问题是当我尝试建立一个字符串写入文件告诉要插入的数据。

在导出过程中,应该循环遍历结构,为入站腿细节创建逗号分隔值的字符串,然后从结构中的链接列表中检索每个出站腿,并创建另一个逗号分隔的字符串值。

一旦我有入腿相关联的所有的腿,我接着写这两个入境腿串并出站腿串到CSV文件。

这更多的是少除了一个问题的工作。如果入站支路有两个出站支路,当其写入文件时,它仅显示最后一个出站支路,第一个出站支路不写入文件。

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

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; 
} 

感谢您提供任何帮助。

UPDATE 我已经添加了插入功能中的一些更多的调试,所以虽然它看起来像我在做正确的事情时,我通过它一步,如果我再尝试,并通过了什么之后我插入右环仍然只能获得最后一次出站航段。

下面是我已经添加

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

这printf语句只显示之前被插入到列表中的最后一个出站目标数量,而不是一个,所以我不知道如果我将它添加错误的,或者我的指针是否有问题,所以我一直在寻找结果。

任何帮助,将不胜感激。

+0

这可能是'asprintf'使用与其中一个参数相同的目标指针,因此它可以在“打印”字符串之前释放该缓冲区(从而使'outboundLegFileString'指向的任何内容无效)。您可能需要使用第二个缓冲区。 –

+0

不要认为我只是将值打印到目标控制台,它只打印最后一个出站目标。 – Boardy

回答

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"; 

Assumedly应该是:

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这些参数无论如何,因此琴弦只落得被复制两次,这很可能会导致内存泄漏。

+0

非常感谢您的帮助。你是对的我正在更新指针,所以完成了你所建议的一切,并按预期工作 – Boardy