• 締切済み

C言語のプログラムを書いたのですが上手く動きません

C言語の練習問題をプログラミングしたのですが、上手く動きません。 コンパイルはできるのですが、実行すると「Segmentation fault(core dumped)」となります。 問題は、コマンドライン引数としてファイル名を指定したテキストファイルから読み込んだデータを,双方向リストに格納し,順番に表示するというものです。 テキストファイルは 10T5001 C 10T5002 A 10T5003 B 10T5004 C 10T5005 D 10T5006 B 10T5007 A 10T5008 D このように、IDとランクをランクABCDをスペースで区切ったもので、これをランクAから順番に表示させます。 上手く動けば ID: 10T5002, grade: A, ID: 10T5007, grade: A ID: 10T5003, grade: B ID: 10T5006, grade: B ID: 10T5001, grade: C ID: 10T5004, grade: C ID: 10T5005, grade: D ID: 10T5008, grade: D と表示されるはずなんですが・・・ これが僕の書いたプログラムです(長いです。ごめんなさい) #include <stdio.h> #include <stdlib.h> #include <string.h> #define ID_LENGTH 8 /* IDの長さ+ナル文字 */ #define EFOPEN -1 #define ENOMEM -2 #define EINVAL -3 /* 双方向リストのノード */ typedef struct sList /* タグ */ { char id[ID_LENGTH]; /* ID */ char grade; /* ランク*/ struct sList *prev; /* 前のノードのアドレス */ struct sList *next; /* 次のノードのアドレス */ } sNode; /* 双方向リストのノードを作成する関数 makeNewNode() 作成したノードのprevとnextはNULLにする 引数 ・ノードに格納するID ・ノードに格納するランク(A/B/C/D) 戻値 作成したノードの先頭アドレス.メモリの確保に失敗した場合はNULL */ sNode *makeNewNode(char *id, char grade) { sNode *pNewNode; pNewNode = (sNode*)malloc(sizeof(sNode)); if(pNewNode != NULL) { strncpy(pNewNode->id, id, ID_LENGTH-1); pNewNode->grade = grade; pNewNode->prev = NULL; pNewNode->next = NULL; } return pNewNode; } /* 引数で渡された任意のノードの後ろに新しいノードを追加する関数 insertNext() 引数 ・後ろにノードを追加したいノードの先頭アドレス ・追加するノードの先頭アドレス 戻値 なし */ void insertNext(sNode *node, sNode *newNode) { if(node->next == NULL) //一番後ろに追加する場合 { node->next = newNode; newNode->prev = node; } else //まん中に挿入する場合 { newNode->prev = node; newNode->next = node->next; node->next->prev = newNode; node->next = newNode; } } /* main() 引数 int argc コマンドライン引数の数 char *argv[] 与えられたコマンドライン引数の文字列の先頭アドレスの配列 戻値 int 正常終了の時 0 以下の場合は異常終了し,括弧内の値を返す データファイルが開けなかった場合(EFOPEN) makeNewNode()でメモリが確保できなかった場合(ENOMEM) 引数の数が正しくない場合(EINVAL) */ int main(int argc, char *argv[]) { sNode *top; /* リストの先頭ノードのアドレスを保持する変数*/ sNode *new; /* 新しく作成したノードのアドレスを保持する変数 */ sNode *now; /* 現在見ているノードのアドレスを保持する変数 */ FILE *fp; /* データファイルのファイルポインタ */ char id[ID_LENGTH]; /* ファイルから読み込んだIDを一時的に保持する変数 */ char grade; /* ファイルから読み込んだランクを一時的に保持する変数 */ /* コマンドライン引数の数をチェックする 数に過不足があれば,使い方を表示し,異常終了する */ if(argc != 2){ printf("Usage: %s datafilename.\n", argv[0]); return EINVAL; } /* データファイルを読み込み用に開く ファイルが開けなかった場合,エラーメッセージを表示し異常終了する */ fp = fopen(argv[1], "r"); if(NULL == fp){ printf("No such file %s.\n", argv[1]); return EFOPEN; } /* リストの先頭に番兵を立てる */ new = makeNewNode("Banpei", 'A'-1); if (new == NULL){ printf("Error: cannot allocate memory\n"); return ENOMEM; } top = new; /* データファイルから1行ずつデータを読み込み,ランク順にリストに追加していく 既にリストの先頭には番兵ノードがある点に注意 */ while(EOF != fscanf(fp, "%s %c", id, &grade)){ new = makeNewNode(id, grade); if(new == NULL){ printf("Cannot allocate memory.\n"); return EFOPEN; } if(top->next == NULL){ //リストが空の場合 insertNext(top, new); } else{ now = top; while(new->grade > now->grade){ now = now->next; } insertNext(now, new); } } /* できあがったリストの内容を先頭から順に表示する ただし,番兵ノードは表示しない */ now = top; while(now != NULL){ printf("ID: %s, grade: %c\n",now->id, now->grade,); now = now->next; } /* リストのノードを全て(番兵ノードも含む)解放し,リストを空にする */ now = top; while(now->next != NULL){ free(now->prev); now = now->next; } free(now); fclose(fp); return (0); } まだまだ練習中なもので、かなり拙いものだと思いますが、とりあえずまずはプログラム動くようにしたいです。 よろしくお願いします。

みんなの回答

回答No.2

sNode *makeNewNode(char *id, char grade) { … strncpy(pNewNode->id, id, ID_LENGTH-1);   →strncpy()の仕様では    id <= ID_LENGTH-1の場合はヌル文字が付加されません。    なので仮にソートがうまくいっても表示がおかしくなるはず。    手っ取り早く直すならstrncpy()の直前で    確保したノードエリアを初期化します。    memset(pNewNode, 0, sizeof(sNode));    strncpy(pNewNode->id, id, ID_LENGTH-1); ----------------------------------------------------- int main(int argc, char *argv[]) { … while(new->grade > now->grade){ now = now->next; }   →now->gradeがAで、new->gradeがBの場合、    nowがnow->nextにズレますが、    次のnow->nextがCの場合にwhile文を抜けても    Cグレードの後ろに追加されてしまうので、    順番がぐちゃぐちゃになります。        ここではinsertNext(node, newNode)は    nodeの後ろにnewNodeを挿入する仕様なので、    おかしくなります。        修正方法としては、2つ。    1.insertNext(node, newNode)でnodeの前にnewNodeを挿入する    2.上記while文を以下のように修正する      for( now = top; NULL != now->next; now = now->next )      {        if( new->grade <= now->next->grade ) break;      } ----------------------------------------------------- /* できあがったリストの内容を先頭から順に表示する ただし,番兵ノードは表示しない */ now = top;   →番兵ノードも表示されてしまうので、    now = top->next;    にします。     ----------------------------------------------------- 全体的にポインタのチェックがありません。 きちんとヌルチェックをしたほうがいいです。

回答No.1

> while(new->grade > now->grade){ >  now = now->next; > } > insertNext(now, new); ここでおかしくなりそう。 このループが必ず停止するために番兵を置いたはず。 ならば番兵はどんな要素より大きくなくてはならない。 にもかかわらず、番兵は最も小さい。 さらに、番兵が最も大きいなら番兵は常にリストの末尾にあるはず。 そうであるなら、> insertNext(now, new); はnewをnowの"手前"に挿入しなければならない。

関連するQ&A

  • 教えて。

    双方向リストを書いているのですが、指定したノードの次に新たなノード追加以降からどうしてもうまくできません。 できればソースで教えてもらえれば助かります。 class MyListw{ int data; //データ MyListw next = null; MyListw prev = null; MyListw firstNode = null; MyListw lastNode = null; MyListw(int data){ this.data = data; } void insertTail(MyListw newNode){ if(lastNode == null) insertHead(newNode); else insertAfter(lastNode, newNode); } void insertHead(MyListw newNode){ if(firstNode == null){ firstNode = newNode; lastNode = newNode; newNode.prev = null; newNode.next = null; }else{ insertBefore(firstNode, newNode); } } void insertAfter(MyListw node, MyListw newNode){ //指定したノードの次に新たなノード追加 newNode.prev = node; newNode.next = node.next; if(node.next == null) lastNode = newNode; else node.next.prev = newNode; node.next = newNode; } void insertBefore(MyListw node, MyListw newNode){ //指定したノードの前に新たなノード newNode.prev = node.prev; newNode.next = node; if(node.prev == null) firstNode = newNode; else node.prev.next = newNode; node.prev = newNode; } void delete(MyListw node){ //リストからデータを1つ削除 if(node.prev == null) firstNode = node.next; else node.prev.next = node.next; if(node.next == null) lastNode = node.prev; else node.next.prev = node.prev; } void deleteHead(){ //先頭のノードを削除 delete(firstNode.next); } void deleteTail(){ //最後のノードを削除 delete(lastNode.prev); } void show(){ MyListw node = firstNode; while(node != null){ System.out.print(node.data); node = node.next; } System.out.println(""); } void showTail(){ MyListw node = lastNode; while(node != null){ System.out.print(node.data); node = node.prev; } } } class MyListwApp{ public static void main(String[] args){ MyListw list = new MyListw(0); //初期ダミー System.out.println("最後に追加"); list.insertTail(new MyListw(1)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.insertTail(new MyListw(5)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("先頭に追加"); list.insertHead(new MyListw(8)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.insertHead(new MyListw(9)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("指定したノードの次に新たなノード追加"); list.insertAfter(new MyListw(1), new MyListw(2)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.insertAfter(new MyListw(2), new MyListw(3)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("指定したノードの前に新たなノード"); list.insertBefore(new MyListw(1), new MyListw(0)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("リストからデータを削除"); list.delete(new MyListw(1)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("先頭のノードを削除"); list.deleteHead(); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.deleteHead(); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("最後のノードを削除"); list.deleteTail(); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.deleteTail(); list.show(); System.out.println("逆順に表示"); list.showTail(); } }

  • C言語 線形探索

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXBUFFERSIZE 256 struct LinkedListNode{ int data; struct LinkedListNode *next; }; struct LinkedList{ int node_num; struct LinkedListNode *head; }; LinkedList *LinkedListMake(char *filename) { FILE *fp; LinkedList *list; char buffer[MAXBUFFERSIZE]; /* ファイル有無のチェック */ if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "No Such File : %s\n", filename); exit (1); } list = LinkedListAlloc(); if (list == NULL) { /* 領域確保失敗 */ exit (0); /* 終了 */ } while (fgets(buffer, MAXBUFFERSIZE, fp)) { /* ファイル終端に到達するまでループ */ buffer[strlen(buffer) - 1] = '\0'; /* 改行文字を削除 */ LinkedListDataAdd(list, atoi(buffer)); } fclose(fp); return (list); } LinkedList *LinkedListAlloc(void) { LinkedList *list; list = (LinkedList *)malloc(sizeof(LinkedList)); if (list == NULL) { /* 領域確保失敗 */ return (NULL); } list->node_num = 0; list->head = NULL; return (list); } LinkedListNode *LinkedListDataAdd(LinkedList *list, int x) { LinkedListNode *ptr; /* 注目するノードへのポインタ */ LinkedListNode *prev; LinkedListNode *new_node; ptr = list->head; prev = NULL; while (ptr) { /* 終端ノードに到達するまでループ */ if (ptr->data < x) { prev = ptr; /* 直前ノードの更新 */ ptr = ptr->next; /* 注目ノードの更新 */ } else if (ptr->data == x) { /* x は登録済み */ return (NULL); } else { /* x を注目ノードの直前に追加 */ new_node = LinkedListNodeAlloc(); if (new_node == NULL) { /* 領域確保失敗 */ exit (0); /* 終了 */ } new_node->data = x; new_node->next = ptr; /* ポインタの付け替え(注目ノードの直前) */ if (prev != NULL) { /* 連結リストの先頭以降に追加 */ prev->next = new_node; /* ポインタの付け替え */ } else { /* 連結リストの先頭に追加 */ list->head = new_node; } list->node_num++; /* ノード総数の更新 */ return (new_node); } } /* 終端ノードに到達 */ /* x を終端に追加 */ new_node = LinkedListNodeAlloc(); if (new_node == NULL) { /* 領域確保失敗 */ exit (0); /* 終了 */ } new_node->data = x; new_node->next = NULL; /* new_node は新たな終端ノード */ if (prev != NULL) { /* list は少なくともひとつのノードを有している */ prev->next = new_node; /* 更新前の終端ノードの直後が new_node となる */ } else { /* list は空(ノードがひとつも含まれない) */ list->head = new_node; } list->node_num++; /* ノード総数の更新 */ return (new_node); } LinkedList *LinkedListSearch(LinkedList *list, int x)←ここがわかりません★ { for(i = 0; i < node_num)      ??? int main(int argc, char *argv[]) { int a, i, x; printf("xの値を入力"); scanf("%d", &x); LinkedListMake(argv[1]); LinkedListSearch(list, x); 連結リストに格納されたint型データから目的の値を線形探索するプログラムをつくってます。 連結リスト作成関数まではできたので、あと連結リストにおいて目的の値を線形探索する関数LinkedListSearchをつくればだいたい完成だと思うのですが、関数LinkedListSearchの作り方がわかりません。 引数で連結リストのポインタと目的値をとって、目的値が存在すればそのノードのポインタ、存在しない場合はNULLを返すようにするつもりです。 わかる方、是非とも教えてください! お願いいたします。

  • C言語 二分木探索

    今、int型の二分木にデータを追加する関数(引数は二分木へのポインタと追加する値、追加されたノードへのポインタを返す)をつくろうとしてます。 以前リストにデータを追加する関数をつくったのでそれを変更してつくろうとしているのですが途中までいってつまってしまいました。 つくりかたを教えてください。 よろしくお願いします! struct BinaryTreeNode{ int data; struct BinaryTreeNode *l_next; struct BinaryTreeNode *r_next; }; struct BinaryTree{ int node_num; struct BinaryTreeNode *root; }; BinaryTreeNode *BinaryTreeNodeAlloc(void) { BinaryTreeNode *node; node = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); if (node == NULL) { return (NULL); } node->l_next = NULL; node->r_next = NULL; return (node); } BinaryTreeNode *BinaryTreeDataAdd(BinaryTree *list, int x) { BinaryTreeNode *ptr; BinaryTreeNode *prev; BinaryTreeNode *new_node; ptr = list->root; prev = NULL; while (ptr) {       ←?? if (ptr->data < x) { prev = ptr; ptr = ptr->next; } else if (ptr->data == x) { return (NULL); } else { new_node = BinaryTreeNodeAlloc(); if (new_node == NULL) { exit (0);                ←?? } new_node->data = x; new_node->next = ptr; if (prev != NULL) { prev->next = new_node; } else { list->head = new_node; } list->node_num++; return (new_node); } } new_node = BinaryTreeNodeAlloc(); if (new_node == NULL) { exit (0); } new_node->data = x; new_node->r_next = NULL; new_node->l_next = NULL; if (prev != NULL) { prev->next = new_node; } else { list->head = new_node; } list->node_num++; return (new_node); }

  • 先頭・最後尾ノードを使わないプログラムに変更。

    下記のプログラムは、リストへの書き込み・削除のために先頭/最後尾ノードを利用していますが、このプログラムを先頭/最後尾ノードを使わない形のプログラムに変更するにはどうしたらいいですか? それと、プログラムはディープコピーコンストラクタとoperator=を含んでいるのですが、デストラクタをどう入れていいのかわからずにいます。デストラクタの入れ方も教えていただきたいです。よろしくお願いします。 #include <iostream> #include <string> using namespace std; class Node { public: Node(string s = ""); string name; Node *next; }; class LList { public: LList(); LList(LList& here); // ディープコピーコンストラクタ void Insert (string s); void Delete (string s); void Display (); void operator= (LList& here); private: Node *head; Node *Copy (); }; Node::Node(string s) { name = s; next = NULL; } LList::LList() { head = new Node ("AAAAA"); head -> next = new Node ("zzzzz"); } LList::LList (LList& here) { head = here.Copy(); } void LList::Insert (string s) { Node *here = head->next; Node *prev = head; while (s > here->name) { prev = here; here = here->next; } Node *newnode = new Node (s); newnode->next = here; prev->next = newnode; } void LList::Delete (string s) { Node *here = head->next; Node *prev = head; while (s != here->name && here->next != NULL) { prev = here; here = here->next; } if (here->next != NULL) { prev->next = here->next; delete here; } } void LList::Display() { Node *here = head->next; while (here->next != NULL) { cout << here -> name << endl; here = here -> next; } } Node* LList::Copy() { Node *start, *loc, *temp; temp = head; start = loc = new Node(temp->name); temp = temp->next; while(temp != NULL) { loc->next = new Node(temp->name); loc = loc->next; temp = temp->next; } return start; } void LList::operator= (LList& here) { head = here.Copy(); } int main() { LList list, copy; char option; string thisname; while (1) {cout << "Options: (I)nsert, (D)isplay, (R)emove, (E)xit"; cin >> option; cin.ignore(); switch (option) {case 'I': case 'i': cout << "Enter name: "; cin >> thisname; list.Insert(thisname); break; case 'D': case 'd': list.Display(); break; case 'R': case 'r': cout << "Enter name: "; cin >> thisname; list.Delete(thisname); break; case 'E': case 'e': copy = list; list.Insert("frank"); list.Insert("zebedee"); cout << "\n list: \n"; list.Display(); cout << "\n copy: \n"; copy.Display(); exit(0); } } }

  • 双方向リストの関数

    双方向リストにデータファイルから読み込んだ氏名と成績のデータを追加し,リストの末尾から順にデータを表示するプログラムを作成したのですが、insertLast() 関数を用いて末尾ノードの後ろに新しいノードを連結するという部分をどのようにして良いのかわからず困っています。 どのように記述して良いのかわからなかった部分を/*** ***/のコメントで示してあります。 どなたかアドバイスやヒント、その他の指摘などご教授してくださる方いましたらよろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define NAME_LENGTH 20 /* 名前を格納する文字列の長さ */ /* 双方向リストのノードとなる構造体の定義 */ typedef struct sList{  struct sList *prev; /* 前のノードのアドレス */  char name[NAME_LENGTH]; /* 名前 */  char grade; /* 成績 */  struct sList *next; /* 次のノードのアドレス */ } sNode; /* この構造体を sNode型 と定義する */ /* 双方向リストの先頭と末尾を格納するための構造体 */ typedef struct {  sNode *firstNode; /* リストの先頭ノードのアドレス */  sNode *lastNode; /* リストの末尾ノードのアドレス */ } manageList; /*  双方向リストの末尾にノードを追加する関数 insertLast()  引数   manageList *list リストの先頭・末尾ノードを管理する構造体のアドレス   sNode *node 末尾に追加したいノードのアドレス  返値   なし */ void insertLast(manageList *list, sNode *node ) {  /*** リストの末尾にノードを追加する ***/  return; } /*  双方向リストの新しいノードを作成する関数 makeNewNode()  引数   char *aName 名前(文字列)の先頭アドレス   char aGrade 成績  返値   sNode * 新しく作成したノードの先頭アドレス */ sNode *makeNewNode(char *aName, char aGrade ) {  sNode *pNewData;  /* sNode 型のメモリ領域を確保 */  pNewData = (sNode *) malloc( sizeof(sNode) );  /* 名前と成績のデータを設定する */  strcpy( pNewData->name, aName );  pNewData->grade = aGrade;  pNewData->prev = NULL;  pNewData->next = NULL;  return( pNewData ); } /*  main()  引数   なし  返値   int 正常終了の時 0     異常終了の時 -1 (ファイルの読み込み失敗など) */ int main( void ) {  manageList list; /* リストの先頭・末尾ノードのアドレスを持つ構造体 */  sNode *pNew; /* 新しく作成したノードのアドレスを持つ変数 */  sNode *pNow; /* 現在見ているノードのアドレスを持つ変数 */  FILE *fp; /* データファイルのファイルポインタ */  char name[ NAME_LENGTH ]; /* ファイルから読み込んだ名前を一時的に保持する変数 */  char grade; /* ファイルから読み込んだ成績を一時的に保持する変数 */  /* 初期状態では先頭・末尾ノードともNULL */  list.firstNode = NULL;  list.lastNode = NULL;  /* データファイル exer6.txt を読み込み用に開く.    ファイルが開けなかった場合,エラーメッセージを表示し異常終了する.*/  fp = fopen("exer6.txt","r");  if(NULL == firstNode){   printf( "ファイルが開けませんでした. \n" );   return( -1 );  }  /* データをファイルの最後(EOF)まで読み込み,双方向リストにデータを追加する */  while( EOF != fscanf( fp, "%s %c", name, &grade ) ) {   /* 新しいノードを作成 */   pNew = makeNewNode( name, grade );   /*** insertLast() 関数を用いて末尾ノードの後ろに新しいノードを連結する ***/   pNow->next = pNew ;   pNew->prev = pNow ;   pNow = pNew ;  /* ファイルを閉じる */  fclose( fp );  /* 現在見ているノードを末尾ノードにセットする */  pNow = lastNode  /* 末尾のノードから前のノードへたどりながらデータを出力する */  while( NULL != pNow ) {   /* 出力 */   printf( "%s %c\n", pNow->name, pNow->grade );   /* 現在見ているノードを一つ前のノードにする */   pNow = pNow->prev;  }  return( 0 ); }

  • java教えてください。

    双方向リストをjavaで書きたいんですけどここまで書いて双方向リストになってるか不安になってきました。 これは双方向リストになっていますか? class MyListw{ int data; MyListw next = null; //次のノードへのポインタ MyListw prev = null; //前のノードへのポインタ MyListw(int data){ this.data = data; } void insertTail(MyListw node){ //リストの最後へ追加 MyListw tmp = this; while(tmp.next != null){ tmp = tmp.next; } tmp.next = node; node.prev = tmp.next; } void insertHead(MyListw node){ //リストの先頭へ追加 node.next = this.next; this.next = node; node.prev = this.next; } void insert(int head, MyListw node){ //リストの途中へ新規データを挿入 MyListw tmp = this; while(tmp != null){ if(tmp.data == head){ break; } tmp = tmp.next; } node.next = tmp.next; tmp.next = node; node.prev = tmp.next; } void delete(int here, MyListw node){ //リストからデータを1つ削除 MyListw tmp = this; while(tmp != null){ if(tmp.data == here){ break; } tmp = tmp.next; } node = tmp.next; tmp.next.prev = node; tmp.next = node.next; node.next.prev = tmp.next; node.next = null; node.prev = null; } void deleteHead(){ //先頭のノードを削除 MyListw tmp = next; this.next = tmp.next; tmp.next.prev = this.next; tmp.next = null; tmp.prev = null; } void deleteTail(){ //最後のノードを削除 MyListw tmp = this; MyListw lastList = null; while(tmp.next != null){ lastList = tmp; tmp = tmp.next; } lastList.next = null; lastList.prev = null; } void show(){ MyListw tmp = next; while(true){ System.out.print(tmp.data); if(tmp.next == null) break; tmp = tmp.next; } System.out.println(""); } void showTail(){ } } class MyListwApp{ public static void main(String[] args){ MyListw list = new MyListw(0); //初期ダミー System.out.println("最後に追加"); list.insertTail(new MyListw(1)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.insertTail(new MyListw(5)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("先頭に追加"); list.insertHead(new MyListw(8)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.insertHead(new MyListw(9)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("途中からデータを追加"); list.insert(1, new MyListw(2)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.insert(2, new MyListw(3)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("リストからデータを削除"); list.delete(8, new MyListw(1)); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("先頭のノードを削除"); list.deleteHead(); //先頭のノードを削除 list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.deleteHead(); list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("最後のノードを削除"); list.deleteTail(); //最後のノードを削除 list.show(); System.out.println("逆順に表示"); list.showTail(); System.out.println("\n"); list.deleteTail(); list.show(); System.out.println("逆順に表示"); list.showTail(); } }

    • ベストアンサー
    • Java
  • C言語 リスト

    (1) /* list.c */ #include <stdio.h> #include <stdlib.h> struct node { int num; struct node *next; }; main() { struct node *head, *p; int x; head = NULL; while(scanf("%d",&x) != EOF) { p = (struct node *)malloc(sizeof(struct node)); p->num = x; p->next = head; head = p; } // リストの要素のnumの値を先頭から順に表示する p=head; while(p!=NULL) { printf("%d\n" ,p->num); p = p->next; } } (2) struct node *q; q = head; while(q->next != NULL) q = q->next; (1)を(2)を使い新しいノードをリストの最後に追加するようにしたいのですが どう書いたら良いのか教えていただきたいです

  • C言語解読

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define dBufferSize (32768) #define dPrintFmt "#d: %s\n" typedef struct _NODE NODE; struct _NODE { char *line; NODE *next; }; int RemoveReturnCode(char *string); NODE *MakeNode(char *string); int FreeNodeList(NODE *node); void FreeNode(NODE *node); int PrintNoceList(NODE *node); NODE *ReverseNodeList(NODE **head); int main(void){ char buffer[dBufferSize]; NODE *head = NULL; while (fgets(buffer, dBufferSize, stdin) != NULL){ NODE *pivot; RemoveReturnCode(buffer); pivot = MakeNode(buffer); if (pivot == NULL) return FreeNodeList(head); pivot->next = head; head =pivot; } PrintNodeList(head); ReverseNodelist(&head); PrintNodeList(head); FreeNodeList(head); return 0; } int RemoveReturnCode(char *str){ char *p; if (str == NULL) return -1; for (p = str; *p != '\n' && *p != '\r' && *p != '\0'; p++) ; *p = '\0'; return p - str; } NODE *MakeNode(char *str){ NODE *node; if(str == NULL)return NULL; node = (NODE *)calloc(1,sizeof(NODE)); if(node != NULL){ char *p = (char *)calloc(strlen(str)+1, sizeof(char)); if (p != NULL){ node->line = strcpy(p, str); node->next = NULL; } else{ free(node); node = NULL; } } return node; } int FreeNodeList(NODE *node){ int ct = 0; while (node != NULL){ NODE *next = node->next; FreeNode(node); ct++; node = next; } return ct; } void FreeNode(NODE *node){ free(node->line); free(node); } int PrintNodeList(NODE *node){ int ct; for (ct = 0; node != NULL; node = node->next, ct++) printf(dPrintFmt, ct+1, node->line); return ct; } NODE *ReverseNodeList(NODE **head){ NODE *reverse = NULL; NODE *node = *head; while (node != NULL){ NODE *next = node->next; node->next = reverse; reverse = node; node = next; } return *head = reverse; } このプログラムは単方向リストを利用して複数行のデータを格納していくものであるという ものらしいのですが、そのようなヒントがあっても、まったく解読できません、 手も足も出ない状態です。 できれば、初心者に近い私にもわかるように、関数ごとの解説をおねがいします!! エラーがでるかもしれないのですが・・・大体の意味にはかわりないと思いますので、宜しくお願いします!!

  • List構造

    Listの尻にノードを追加する関数で困っています。 以下に、ソースの一部を掲載させていただきます。 typedef struct __node{ int data; struct __node *next; }Node; ... /*リストの尻にノードを追加する関数 * 引数: head. リストの先頭ノードのポインタ data. リストの尻に追加したいint型の変数*/ void Insert_Tail(Node *head, int data) { Node *ptr = head; if(ptr == NULL){ /*<ノードが存在しない時には追加されない>*/ /*領域の確保*/      head = (Node*)calloc(1,sizeof(Node)); /*データをセット*/ head->data = data; head->next = NULL; return ; }else{ /*<ノードが存在するときには正常に動作>*/ while(ptr->next != NULL){ ptr = ptr->next; } /*領域の確保*/ ptr->next = (Node*)calloc(1,sizeof(Node));      /*データのセット*/ ptr->next->data = data; ptr->next->next = NULL; } } コメントアウトにも書かせていただきましたが、ノードがすでに存在するときには、正常にノードの最後に追加してくれるのですが、ノードが存在しない時にはリストに追加してくれません。 どうかご指導、ご指摘の程お願いします。

  • c言語 ハッシュ表

    下のハッシュ表のプログラムについて質問です.関数enterを二回呼び出して,valueの値を変更して表示させても値が更新されません.値が更新せれるにはどうすればよいのでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASH_SIZE 997 /* ハッシュ表の内部配列のサイズ */ #define HASH_RADIX 97 /* ハッシュ関数用の基数 */ /* ハッシュ表内の連結リストに含まれるノードの構造体 */ struct hash_node { /* ハッシュ表内の連結リストのノード */ char *key; /* キー */ int value; /* キーに対応する値 */ int id; /* キーに付与された通し番号 */ struct hash_node *next; /* 次のノードへのポインタ */ }; typedef struct hash_node HashNode; typedef HashNode *HashNodePtr; /* ハッシュ表の構造体 */ struct hashtable { HashNodePtr *heads; /* 内部配列 */ int serial_id; /* 通し番号管理用の変数 */ int size; /* 内部配列のサイズ */ }; typedef struct hashtable HashTable; typedef HashTable *HashTablePtr; /* 文字列 s のハッシュ値を計算する */ unsigned int hash(char *s) { unsigned int v; v = 0; while (*s != '\0') { v = v * HASH_RADIX + *s; s++; } return v; } /* ハッシュ表を一つ生成し,そのポインタを返す */ HashTablePtr create_hashtable() { HashTablePtr t = NULL; int i; t = malloc(sizeof(HashTable)); t->serial_id = 0; t->size = HASH_SIZE; t->heads = malloc(sizeof(HashNodePtr) * t->size); /* 各連結リストの先頭要素へのポインタは必ず NULL に初期化する */ for (i = 0; i < t->size; i++) { t->heads[i] = NULL; } return t; } /* 指定したポインタ変数に NULL を代入して終わるためのマクロ */ #define delete_hashtable(t) \ (delete_hashtable0(t),t=NULL) /* 実質的な削除作業を行う関数(free 後の NULL 代入は省略)*/ void delete_hashtable0(HashTablePtr t) { HashNodePtr n = NULL, m = NULL; int i; /* 各連結リストの領域を解放 */ for (i = 0; i < t->size; i++) { n = t->heads[i]; while (n != NULL) { m = n; n = n->next; free(m); } } /* 最後に連結リストの先頭ポインタの領域を解放 */ free(t->heads); free(t); } /* ハッシュ表 t に登録されているキーと値のペアの数を返す */ int get_cardinality(HashTablePtr t) { return t->serial_id; } /* ハッシュ表 t にてキー key に対応する値を調べる */ int lookup(HashTablePtr t, char *key) { HashNodePtr n = NULL; int index; /* ハッシュ表の内部配列の添え字を計算 */ index = hash(key) % t->size; /* index 番目の連結リストを先頭から順に走査 */ n = t->heads[index]; while (n != NULL) { /* 引数で指定された key とハッシュ表内のキーが一致したら 直ちに対応する値を返す */ if (strcmp(key, n->key) == 0) return n->value; /* 走査を次に進める */ n = n->next; } /* ここではキーに対応する値は非負であると仮定し, 見つからなかったら -1 を返す */ return -1; } /* キー key と値 value のペアをハッシュ表 t に登録し,その通し番号を返す */ int enter(HashTablePtr t, char *key, int value) { HashNodePtr n = NULL, m = NULL; int index; index = hash(key) % t->size; /* 内部配列の添え字を計算 */ /* キーが既に存在しているかどうかチェック(lookup() と同じ処理)*/ n = t->heads[index]; while (n != NULL) { if (strcmp(key, n->key) == 0) return n->id; /* 通し番号を返す */ n = n->next; } /* 新しいノードを生成 */ m = malloc(sizeof(HashNode)); m->key = _strdup(key); m->id = t->serial_id; m->value = value; /* 連結リストの add_first() と同様にして連結リストに追加 */ m->next = t->heads[index]; t->heads[index] = m; t->serial_id++; /* 次の通し番号に更新 */ return m->id; /* 登録したキーと値のペアに付与された通し番号を返す */ } /* * ハッシュ表 t に登録されるキーの配列を返す *(この配列のサイズは get_cardinality() で取得可能) */ char **get_keys(HashTablePtr t) { char **keys = NULL; HashNodePtr n = NULL; int i; keys = malloc(sizeof(char *) * t->serial_id); /* 各連結リストを走査し,配列に詰め込む */ for (i = 0; i < t->size; i++) { n = t->heads[i]; while (n != NULL) { keys[n->id] = n->key; /* 通し番号を配列添え字に */ n = n->next; } } return keys; /* 後で free() する必要あり */ } void print_hashtable(HashTablePtr t) { printf("Taro => %d\n", lookup(t, "Taro")); } /* ハッシュ表の使用例 */ int main(void) { HashTablePtr t = NULL; t = create_hashtable(); enter(t, "Taro", 25); print_hashtable(t); enter(t, "Taro", 35); print_hashtable(t); delete_hashtable(t); }