2

私は二重にリンクされたリストをやっています。私の知る限り、それは機能していますが、正しい方法で行っているかどうかを確認するためにここに来ました。

反対に、これを作成したとき、二重リンクリストに関連するのではなく、構造と C ファイル間の「可視性」に関連する他の質問に出くわしました。この他の 2 つの疑問に対して別の質問を作成する必要があることを理解したら、教えてください。それ以外の場合は、お気軽に教えてください。

私のfile1.cにはこれがあります:

コード

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

typedef struct team{
    char *name;
    char *teamPlace;
}Team;

typedef struct nodeTeam{
    int numberOfTeams;
    Team team;
    struct nodeTeam *next;
    struct nodeTeam *prev;
}NodeTeam;

int createsListOfTeams(NodeTeam **head, NodeTeam **tail);
void printListOfTeams(NodeTeam *listofTeams);
int addNodeTeamsSorted(NodeTeam *head, NodeTeam **tail, Team team);

int main()
{
    NodeTeam *headEquipas,*tailEquipas;
    Team eq;
    /*Creates the doubly linked list*/
    if(createsListOfTeams(&headEquipas,&tailEquipas)){
        printf("\nError\n");
        return 0;
    }
    /*Add the teams to the doubly linked list. At the end, all teams will be sorted by name*/
    eq.name = "D team";
    eq.teamPlace = "D team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    eq.name = "A team";
    eq.teamPlace = "A team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    eq.name = "C team";
    eq.teamPlace = "C team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    eq.name = "B team";
    eq.teamPlace = "B team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    /*Will print all the teams*/
    printListOfTeams(headEquipas);

    return 0;
}

そして、私のfile2.cにはこれがあります

コード

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    typedef struct team{
        char *name;
        char *teamPlace;
    }Team;

    typedef struct nodeTeam{
        int numberOfTeams;
        Team team;
        struct nodeTeam *next;
        struct nodeTeam *prev;
    }NodeTeam;

    /*Add the teams to the doubly linked list. At the end, all teams will be sorted by name*/
    int createsListOfTeams(NodeTeam **head, NodeTeam **tail){
        (*head) = (NodeTeam *)malloc(sizeof(NodeTeam));

        if ((*head) == NULL){
            return -1;
        }
        (*head)->numberOfTeams = 0;
        (*head)->team.teamPlace = "";
        (*head)->team.name = "";
        (*head)->next = NULL;
        (*head)->prev = NULL;

        *tail = *head;
        return 0;
    }

    /*Creates the doubly linked list*/
    int addNodeTeamsSorted(NodeTeam *head, NodeTeam **tail, Team team){
        NodeTeam *no,*listIni;


        no = (NodeTeam*) malloc(sizeof(NodeTeam));
        if (no == NULL){
            return -1;
        }

        /*copy of my list*/
        listIni = head;

        no->team = team;
        /*to see is it's the first element of my list*/
        if(head->numberOfTeams == 0)
        {
            no->next = head->next;
            no->prev = head;
            head->next = no;
            *tail = no;

        }
        else{ /*If not the first element*/
            head = head->next;
            while(head->prev != *tail && strcmp(head->team.name,no->team.name) < 0 && strcmp((*tail)->team.name,no->team.name)>0){
                head = head->next;
                (*tail) = (*tail)->prev;
            }
            if(strcmp(head->team.name,no->team.name) >= 0 || head->prev == *tail){
                no->next = head;
                no->prev = head->prev;
                (head->prev)->next = no;
                head->prev = no;

            }
            else if(strcmp((*tail)->team.name,no->team.name) <= 0){
                no->next = (*tail)->next;
                no->prev = (*tail);
                (*tail)->next = no;
                *tail = no;

            }
        }

        /*Updates the number of element of the list*/
        head = listIni;
        head->numberOfTeams++;

        return 0;
    }
    /*Prints my lists*/
    void printListOfTeams(NodeTeam *listofTeams){
        printf("|   number of teams %22d |\n",listofTeams->numberOfTeams);
        printf("|      team name      |        team place      |\n");
        printf("--------------------------------------------------\n");
        listofTeams = listofTeams->next;
        while (listofTeams != NULL){
            printf("| %-21s | %-22s |\n",listofTeams->team.name,listofTeams->team.teamPlace);
            listofTeams = listofTeams->next;
        }
        printf("--------------------------------------------------\n\n");
    }

だからここに私のツリーの質問があります:

Q1 - これは、先頭と末尾がそれぞれリストの先頭と末尾を指す双方向リンク リストを実装する正しい方法ですか?

Q2struct team - ファイルの両方でとを宣言するのはなぜstruct nodeTeamですか? それらはすべて同じプロジェクトにあるため、宣言はプロジェクトのすべてのファイルに「表示」されるべきではありませんか?

Q3 -struct teamなぜchar *name代わりに宣言しなければならないのchar name[31]ですか?

4

1 に答える 1

2

以前のコメントの後、コードをより注意深く分析した後、いくつかの編集を行いました。頭と尾の項目に関する 1 つの発言を誤って解釈しました。循環リストを設計していましたが、

  1. コードをコピー/貼り付け/コンパイルするのに時間がかかりました。ほとんど機能していますが、別の方法で設計したと言わざるを得ません。

    • prev/ポインタnextstruct team
    • teamのメンバーを最初の へnodeTeamheadポインターに置き換えますteam

    これには次の利点があります。

    • numberOfTeamsそれぞれに複製されているnodeTeamsが、最初のものにのみ意味があるためのスペースの無駄な無駄を防ぎます
    • head概念と実際の最初のチームの間の混乱を避ける

    チームリストにポインターの値を追加することにより、

    printf("| %-21s | %-22s | %p - p=%p n=%p\n",listofTeams->team.name, listofTeams->team.teamPlace, listofTeams, listofTeams->prev, listofTeams->next);

    リンクにバグの可能性があることに気付きました:

    | | チーム | チームの場所 | 0x101d00980 - p=0x101d00920 n=0x101d009e0

    | | Bチーム | Bチームの場所 | 0x101d009e0 - p=0x101d00980 n=0x101d009b0

    | | Cチーム | Cチームの場所 | 0x101d009b0 - p=0x101d00980 n=0x101d00950

    | | Dチーム | Dチームの場所 | 0x101d00950 - p=0x101d009b0 n=0x0

    次のポインターは問題ないことがわかりますが、前のポインターは疑わしい重複を示しています(0x101d00920 は実際には「先頭」です)。

    コードの実行をトレースし、それが何を行ったかを確認すると、ステップ 3 (既存の A & D の後にチーム C を追加)までaddNodeTeamsSorted()はすべて問題ないことがわかります。

    • 新しいアイテムを挿入する場所を見つけるために頭と尾の両方の奇妙な二重変更が原因で、頭と尾が交差しています: 尾は実際には 'A' を指し、頭は 'D' を指しています (while とその変更が勝つことを忘れないでくださいhead) Nodeteam *。 '関数の外に伝播されない、tailは ですNodeteam **。したがって、それが呼び出し元に変更され、次の呼び出しでは間違っています
    • テストのステップ 4 (「B」の追加) で、の前/次、(*tail) の次else ifは適切に変更しますが、前の部分は変更しないので、 nono->next
      • 'B' -> 次 = 'C' : OK
      • 'B' -> prev = 'A' : OK
      • *tail (='A') -> next = 'B' : OK
      • 'C' -> prev still = 'A' :間違い
  2. これは、コンパイラが考えているようなものではありません。彼は一度に 1 つずつ、コンパイル単位のみを処理します。.c で宣言されていないものと、含まれている別の .h は不明のままです。equipa.h2 つのモジュール間で構造体宣言を共有し、コード メンテナンスのエラーを防止する場合は、typedef を切り取り、両方の .c に含まれる共通のヘッダー ファイル (例: ) に配置します。

  3. in file1.c では、リテラル文字列から直接割り当てを行っており、コンパイラではリテラル文字列を char 配列に割り当てることができないため、char*代わりに使用する必要があります。代わりに使用したい場合は、char[]main()char[]

    eq.nome = "D team";

    のような文字列コピーによって

    strcpy(eq.nome, "D team");

    もちろん、私は概念を扱っているだけです。実際には、コピーされる文字列がバッファより長くならないように注意する必要がありますstrncpy()sizeof(eq.nome)

于 2012-05-12T10:24:17.360 に答える