私は C を初めて使用しますが、データベースから通話ログ情報を取得するプロジェクトに取り組んでいます。実際のプログラムでこれを実装しようとする前に、構造に静的データを手動で追加するだけでロジックが正しいことを確認できるように、テスト アプリを作成しようとしています。
コール ログには、電話番号や通話時間などのインバウンド コール レッグの詳細が保持されます。その構造内には、1 つ以上のアウトバウンド レッグを含むリンクがリストされています。
GDB でコードをステップ実行するときからわかる限り、データを正しく挿入しているように見えますが、問題は、ファイルに書き込む文字列を作成しようとするときです。
エクスポート プロセスでは、構造をループし、インバウンド レッグの詳細についてコンマ区切り値の文字列を作成し、構造内のリンク リストから各アウトバウンド レッグを取得して、カンマ区切り値の別の文字列を作成することになっています。
インバウンド レッグに関連付けられたすべてのレッグを取得したら、これら 2 つのインバウンド レッグ文字列とアウトバウンド レッグ文字列を CSV ファイルに書き込みます。
これは、1 つの問題を除いてあまり機能しません。インバウンド レッグに 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;
}
UPDATE 挿入機能内にさらにデバッグを追加したので、ステップスルーすると正しいことをしているように見えますが、最後のアウトバウンドレッグしか取得した直後に挿入されたものをループしようとすると.
以下は私が追加したものです
node * outBoundLeg;
    for (outBoundLeg = callLog[callLogIndex].outBoundLegs; outBoundLeg != NULL; outBoundLeg = outBoundLeg->next)
    {
        printf("INSERT: %s\n", outBoundLeg->target);
    }
そのprintfステートメントは、リストに挿入された最後のアウトバウンドターゲット番号のみを表示しているため、追加が間違っているかどうか、またはポインターが間違っているかどうかがわからないため、常に終わり。