質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.80%

線形リスト 途中の挿入と削除

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,143

score 11

以下の入力による命令が線形リストに反映されるプログラムを作りたいです。

0 :終了
1 :リスト表示
2 num val :リストのnum番目に値valを追加
3 num :リストのnum番目を削除
また、追加と削除に関しては、成功したとき1、失敗したとき0を返すようにする必要があります。

リストの終了(0)、表示(1)、削除(3)はできています。追加が上手くいきません。
追加の命令(2 1 1など)をしたあと、リスト表示を行っても何も表示されませんので、上手く追加ができていないのだと思います。
コードはこちらになります。テンプレートとして用意されたものを使用していますので、私が書いたのはaddNode、deleteNode、showList関数内のみです。今回は追加が上手くいきませんので、addNode関数内のみ見ていただければと思います。
どうぞよろしくお願いいたします。

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

#define FAIL_RETURN(flg,message) if(!(flg)){printf("%s",message);freeList();exit(1);}

typedef struct LISTNODE {
    int data;
    struct LISTNODE *pNext;
} ListNode;

ListNode rootNode;

int addNode(int num, int val){
    /*write your program.*/
    ListNode *pPrevNode = &rootNode;
    ListNode *pNewNode = (ListNode*)malloc(sizeof(ListNode));
    pNewNode -> data = val;
    pNewNode -> pNext = NULL;

    int Pos=1;
    pPrevNode = pPrevNode -> pNext;
    while(pPrevNode != NULL){
        pPrevNode = pPrevNode -> pNext;
        Pos++;
    }

    pPrevNode = &rootNode;

    if(num <= Pos+1){

        int pos=1;
        while(pos<num){
            pPrevNode = pPrevNode->pNext;
            pos++;
    }

        pNewNode -> pNext = pPrevNode->pNext;
        pPrevNode-> pNext = pNewNode;

        return 1;
    }else
    {
        return 0;
    }
}

int deleteNode(int num){
    /*write your program.*/

    ListNode *nNode = &rootNode;
    int Pos=1;
    nNode = nNode -> pNext;
    while(nNode != NULL){
        nNode = nNode -> pNext;
        Pos++;
    }

    if(num<=Pos){

        Pos=1;
        ListNode *Node = &rootNode;
        /*削除するノードのひとつ前まで進める*/
        while(Pos<num){
            Node = Node->pNext;
            Pos++;
        }


        ListNode *Node2 = &rootNode;
        Pos = 1;
        /*削除するノードまで進める*/
        while(Pos <= num){
            Node2 = Node2->pNext;
            Pos++;
        }

        /*前の要素のpNextに削除される要素のpNextをコピー*/
        Node->pNext = Node2->pNext;

        free(Node2);
        return 1;
    }else
    {
        return 0;
    }

    }

void showList(void) {
    /*write your program.*/
    ListNode *Node;
    Node = &rootNode;
    Node = rootNode.pNext;
    if(Node != NULL){
        if(Node->pNext != NULL){
         printf("%d", Node->data);}

        Node = Node->pNext;
         while(Node != NULL){
             printf(" %d", Node->data);
            Node = Node->pNext;
        }
    printf("\n");
    }

}

void freeList(void) {
    ListNode *currentNode = rootNode.pNext;
    ListNode *tmp;

    for (;currentNode != NULL;) {
        tmp = currentNode;
        currentNode = currentNode -> pNext;
        free(tmp);
    }
}


int main(void) {
    int op, num, val;
    char message[256];

    rootNode.data = 0;
    rootNode.pNext = NULL;



  /*addNodeが使えないので確認用
  ListNode node1, node2, node3;
  rootNode.pNext = &node1;
  node1.pNext = &node2;
  node2.pNext = &node3;
  node3.pNext = NULL;
  node1.data = 10;
  node2.data = 20;
  node3.data = 30;*/

    while (scanf("%d", &op), op) {
        switch (op) {
            case 1:
                showList();
                break;
            case 2:
                scanf("%d%d", &num, &val);
                sprintf(message, "error in addNode(%d, %d)\n", num, val);
                FAIL_RETURN(addNode(num, val), message)
                break;
            case 3:
                scanf("%d", &num);
                sprintf(message, "error in deleteNode(%d)\n", num);
                FAIL_RETURN(deleteNode(num), message)
                break;
        }
    }

    freeList();

    return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

今回は追加が上手くいきませんので、addNode関数内のみ見ていただければ

showList関数の正しさには自信があるということですか?

01:void showList(void) {
02:  /*write your program.*/
03:  ListNode *Node;
04:  Node = &rootNode;
05:  Node = rootNode.pNext;
06:  if (Node != NULL) {
07:    if (Node->pNext != NULL) {
08:      printf("%d", Node->data);
09:    }
10:
11:    Node = Node->pNext;
12:    while (Node != NULL) {
13:      printf(" %d", Node->data);
14:      Node = Node->pNext;
15:    }
16:    printf("\n");
17:  }
18:}


rootの次に一つ要素がある状態を想定すると
root[data,pNext] - node1:[data,NULL]
という状態。

これでshowListに入ると、
05:でnode1へのポインタがNodeに入りますね。
06:は真ですが、
07:のifの条件式はnode1のpNextを検査してNULLですからdataの表示は行われません。
11:でNodeはnode1のpNextすなわちNULLになって以降スキップ。

つまり、

追加の命令(2 1 1など)をしたあと、リスト表示を行っても何も表示されません

ということになります。
もう一個要素を追加すると以降は表示されます。07:のifが余計ですね。
まぁ、言い出すと06:のifと12:のwhileの条件が同じあたり、工夫のしようがあるんじゃないか、とかも思います。

ここはあっているはず、と思うと間違いを見逃します。
(addListとかdeleteListがあっているかはちゃんとは見ていませんが)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/06 12:56

    お返事が遅くなってしまい申し訳ありません。
    確認用の10 20 30が表示されたので、すっかり合っていると思い込んでしまっていました。教えていただいたことを確認してみると、たしかに…となりました。とても助かりました。ご回答ありがとうございました。

    キャンセル

+1

確認に使用している showList が正常に動作致しません.
テストされた形跡がコメントにありますが,「データが1件の場合」に表示されるかをテストされていません.

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

typedef struct LISTNODE {
    int data;
    struct LISTNODE *pNext;
} ListNode;

ListNode rootNode;

int addNode(int num, int val){
  /*write your program.*/
  ListNode *node, *pNewNode;
  for(node=&rootNode; node!=NULL; node=node->pNext) {
    if(--num == 0) {
      pNewNode = (ListNode *)malloc(sizeof(ListNode));
      pNewNode->data  = val;
      pNewNode->pNext = node->pNext;
      node->pNext = pNewNode;
      return 1;
    }
  }
  return 0;
}

void showList(void) {
  /*write your program.*/
  ListNode *node;
  printf("showList:");
  for(node=rootNode.pNext; node!=NULL; node=node->pNext) {
    printf(" %d", node->data);
  }
  printf("\n");
}

void freeList(void) {
  ListNode *node, *tmp;
  for(node=rootNode.pNext; node!=NULL; ) {
    tmp = node;
    node = node->pNext;
    free(tmp);
  }
}

int main(void) {
  rootNode.data = 0;
  rootNode.pNext = NULL;

  showList();
  printf("addNode: return=%d\n", addNode(1,10));
  showList();
  printf("addNode: return=%d\n", addNode(1,20));
  showList();
  printf("addNode: return=%d\n", addNode(2,30));
  showList();
  printf("addNode: return=%d\n", addNode(5,40));
  showList();

  freeList();

  return 0;
}
showList:
addNode: return=1
showList: 10
addNode: return=1
showList: 20 10
addNode: return=1
showList: 20 30 10
addNode: return=0
showList: 20 30 10

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/06 12:59

    お返事が遅くなってしまい申し訳ありません。10 20 30の表示ですっかり合っていると思ってしまいました。テストする際にはいくつか条件を変えて行った方がよいと学ぶことができました。ご回答ありがとうございました。

    キャンセル

  • 2020/01/06 13:18

    なお, ご提示のコードでは addNode が 0 を返す場合に malloc した領域が解放されずに残ってしまいます.
    挿入が確定してから malloc するか, 0 を返す前に free するようにしてください.

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る