
双方向リストにデータファイルから読み込んだ氏名と成績のデータを追加し,リストの末尾から順にデータを表示するプログラムを作成したのですが、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 );
}
A 回答 (8件)
- 最新から表示
- 回答順に表示
No.8
- 回答日時:
あはは、すみません。
コンパイルも通るし、間違いでも無いので、化石的コーディングとは言い過ぎたかもしれません。言いたかったのは、typedef で始めて、構造体を定義するのは、(私が思うに)、あまり良いスタイルとは言えないというだけのことです。
ただでさえ、理解するのが少し難しい typedef と構造体の定義を絡ませてわざわざ複雑にすべきではなく、typedef を使うのなら Tacosan のおっしゃるように
typedef struct sList sList;
struct sList {
sList* m_pslist;
};
というように分けて書いた方がよほど分かりやすく、自己参照構造体にしてもすっきりと定義できるので、こちらの方が良いと思うと、単にそう言いたかっただけなのでした。
No.7
- 回答日時:
C++ では無意味だけど C では「無意味」というほどではない>#5, #6. 文法上は「struct と書かなくていい」程度 (プログラムを読む人間の意味としては違うけど) ではあるので, 個人的には
typedef struct sList { ... } sList;
または
typedef struct sList sList;
struct sList { ... };
の方が好み.
さておいて, 「先頭に挿入する」のも「末尾に挿入する」のも同じことで, 図を描いて「どのようにリンクを張り直せばよいか」を考えればわかる.
No.6
- 回答日時:
> typedef struct sList { ... } sNode;
自己参照構造体を定義するときには十分意味がある書き方のように見えます。
化石的コーディングではないと思います。
No.5
- 回答日時:
あと、その他の指摘として、本質とは無関係ですが、構造体を次のように typedef で定義するのは(未だに良く見かけますが)、もはや、化石的コーディングなので止めましょう。
typedef struct sList { ... } sNode;
この場合、同じ構造体に sList と sNode という二つの名前が付いてしまいます。だから、間違いというわけではないですが、無意味であり、混乱の元になるだけです。
次のように定義してください。
struct sNode { ... };
課題のコードが元から typedef を使って書かれていたのであれば、先生の頭がちょっと古いのかもしれませんよ。
No.4
- 回答日時:
リスト構造について解説しているサイトはそれこそ山のようにありますが、
私が見かけた中で「これはわかりやすそうだ」と思った場所を
参考URLに挙げておきます。
なお、ds03.html~ds06.htmlがありまして、最後のds06で双方向リストについて解説しています。
線形リストについてご存じであっても、復習をかねて
ds03~ds05もごらんになっておくとよいかもしれません。
参考URL:http://tdweb.cssa.chs.nihon-u.ac.jp/ds/ds03.html
No.3
- 回答日時:
main() 側で、
/*** insertLast() 関数を用いて末尾ノードの後ろに新しいノードを連結する ***/
insertLast(list, pNew);
のように insertLast() を呼び出し、insertLast() 側では、渡された引数を元に list の最後に pNew を連結するということですね。
課題なのであれば、ここかさ先は自分で考えたほうが良いと思います。
あと、malloc() で確保したメモリは、必ず開放するということをお忘れなく。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- XML マスターノード 1 2023/03/14 10:38
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ルート要素ノードが2個ある場合?
-
PHPを使ったDOMの操作で兄弟ノ...
-
C言語のプログラムを教えてくだ...
-
XML::LibXMLのfindnodes()で、...
-
VB6.0でDOMを使用して...
-
C#でTreeViewのCheckBoxのサイ...
-
SNMP リンクダウンとノードダ...
-
vbsのDOMDocumentで要素のText...
-
各ノードの行数取得
-
昔Winnyってありましたけど、あ...
-
CPUの考え方を教えてください ...
-
xmlから吐き出したhtmlデータの...
-
DOSコマンドラインからxmlファ...
-
XSLスタイルシートについて
-
サイトマップの作り方。
-
JavaScriptを使うとXMLで実体参...
-
xmlの初歩の初歩の質問ですが
-
質問
-
XMLとXSLTでリンクを張る方法
-
2つの行動の違い
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CPUの考え方を教えてください ...
-
ルート要素ノードが2個ある場合?
-
SNMP リンクダウンとノードダ...
-
あるノードリストに、特定の名...
-
同じタグ名の項目取得
-
C#でTreeViewのCheckBoxのサイ...
-
TreeView の初期表示について
-
昔Winnyってありましたけど、あ...
-
ノードとは
-
複数のマックPCによる数値計算...
-
C# TreeView 効率良いノード追...
-
TreeViewで複数ノードの選択は...
-
vbsのDOMDocumentで要素のText...
-
ツリービューのノードをダブル...
-
TreeViewに重複する値をセット
-
ToolStripMenuItemの選択(VB)
-
各ノードの行数取得
-
VB2005 TreeViewの任意ノード選択
-
TreeViewのノードの編集結果が...
-
TreeVIewのノード名を編集する...
おすすめ情報