ページ 11

無題

Posted: 2010年4月01日(木) 17:59
by テツ
お世話になります。テツです。
今回課題を出されてまったくイメージが沸かないので教えていただきです。
ちなみにリスト構造は少しふれたことがあるだけで、コーディングしたことはないレベルです。。。orz
これから勉強しながらコーディングしたいと思います。

仕様については別途添付ファイルに記載します。

まず構造体について自分自身をメンバとして持つと思うのですが、
今回でいう空のリスト、高優先順位リスト、通常優先順位リストごとに3つの構造体を作るのでしょうか?
それとも構造体を1つで空のリスト、高優先順位リスト、通常優先順位リストをメンバに持つのでしょうか?
もしくはネスト?

う~ん。。。まったくイメージが沸きません(泣

アドバイス頂けないでしょうか?

Re:無題

Posted: 2010年4月01日(木) 18:02
by テツ
管理人様

申し訳ありません。
タイトルが無題になってしまいました。

Re:無題

Posted: 2010年4月01日(木) 18:44
by たいちう
まず構造体について自分自身をメンバとして持つと思うのですが、
今回でいう空のリスト、高優先順位リスト、通常優先順位リストごとに3つの構造体を作るのでしょうか?
それとも構造体を1つで空のリスト、高優先順位リスト、通常優先順位リストをメンバに持つのでしょうか?
もしくはネスト?

空きリスト:root1 → data1 → data2 → data3 → data4 → NULL
高優先度リスト:root2 → data5 → data6 → data7 → data8 → NULL

題意はこのようなイメージでしょう。
リストの各要素は次の要素へのポインタを持てばよく、
プログラム全体で3つのルート(リストの起点)を持ちます。

Re:無題

Posted: 2010年4月01日(木) 19:43
by 初級者
自己参照型構造体とは、
その構造体の型へのポインターをメンバーに持つ
構造体のことです。

決して、自分自身をメンバーに持つのではありません。

Re:無題

Posted: 2010年4月01日(木) 19:59
by テツ
たいちうさんお世話になります。

>リストの各要素は次の要素へのポインタを持てばよく、
これは何となくイメージがつきます。ただ、双方向の場合直前の要素のポインタも持たなくてはいけないのではないでしょうか?

>プログラム全体で3つのルート(リストの起点)を持ちます。
ここが今いちわからないです。これはリストを管理する構造体のメンバ?として持てばいいのでしょうか?

初級者さんお世話になります。

>自己参照型構造体とは、
その構造体の型へのポインターをメンバーに持つ
構造体のことです。

仰せの通りです。私の投稿では意味が全く違ってきてしまいますよね。
ご指摘ありがとうございました。

Re:無題

Posted: 2010年4月01日(木) 22:08
by たいちう
> これは何となくイメージがつきます。
> ただ、双方向の場合直前の要素のポインタも持たなくてはいけないのではないでしょうか?

双方向リストでしたね。失礼しました。
前の要素と次の要素の2つのポインタが必要です。


> >プログラム全体で3つのルート(リストの起点)を持ちます。
> ここが今いちわからないです。これはリストを管理する構造体のメンバ?として持てばいいのでしょうか?

仕様に指定はないようです。
3つのリストを管理する構造体を定義し、
プログラム全体で1つだけこの構造体のインスタンスを持つつもりならば、
それでも結構です。

Re:無題

Posted: 2010年4月01日(木) 22:55
by テツ
たいちうさんお世話になります。

>3つのリストを管理する構造体を定義し、
>プログラム全体で1つだけこの構造体のインスタンスを持つつもりならば、

となると
typedef struct List{
    struct List *prev;
    struct List *Next;
    ここに空リスト管理?
    ここに高優先度登録リスト管理?
    ここに通常優先度登録リスト管理?
}
こんな感じで大丈夫でしょうか?

ちなみにたいちうさんならどんな感じにするのでしょうか?
よろしければ教えていただけないでしょうか?

Re:無題

Posted: 2010年4月02日(金) 01:23
by ideyan
横槍失礼。

>3つのリストを管理する構造体を定義し、
>プログラム全体で1つだけこの構造体のインスタンスを持つつもりならば、

これは、まず構造体が以下のように定義されているとして
typedef struct list List;
struct list{
    List *next,*prev;
    char *rec;
};

・プログラム全体で3つのルート(リストの起点)を持つ場合

List *nRoot,*hpRoot,*npRoot;

上みたいにrootを持っておけば大丈夫です。

・3つのリストを管理する構造体を定義し、プログラム全体で
  1つだけこの構造体のインスタンスを持つ場合

struct{
    List *n;//空リスト
    List *hp;//高優先度
    List *np;//通常優先度
}Root;
こんな感じで一つにまとめてしまえます。

とこんなことが言いたかったのではないかと思います。

Re:無題

Posted: 2010年4月02日(金) 09:08
by たいちう
> ちなみにたいちうさんならどんな感じにするのでしょうか?
> よろしければ教えていただけないでしょうか?

ideyanさんの書いている通りです。
3つのリスト管理用の構造体は特に必要なものではありません。
ない方が簡単かと。

Re:無題

Posted: 2010年4月02日(金) 09:13
by テツ
ideyanさんいつもお世話になります。
typedef struct list List;
struct list{
    List *next,*prev;
    char *rec;
};
>上みたいにrootを持っておけば大丈夫です。
このように3つのリストを持つ場合はList *nRoot,*hpRoot,*npRoot;を
構造体外部変数として扱えばいいということでしょうか?

ということは今回は別に3つの構造体は用意しなくても1つでいいんですね。

ちなみに
>・プログラム全体で3つのルート(リストの起点)を持つ場合
>・3つのリストを管理する構造体を定義し、プログラム全体で
>1つだけこの構造体のインスタンスを持つ場合

この方法はどちらがいいのでしょうか?

自分としては下のほうが分かりやすいような気がしますが。。。
でも何となくです(笑

Re:無題

Posted: 2010年4月02日(金) 09:15
by テツ
すみません。たいちうさんのレスを見逃してしまいました。

>ideyanさんの書いている通りです。
>3つのリスト管理用の構造体は特に必要なものではありません。
>ない方が簡単かと。

そうなんですね。僕はてっきり3つ作成して管理しなくてはいけないと思っていました。
ご指摘ありがとうございます。

Re:無題

Posted: 2010年4月02日(金) 11:09
by テツ
最初の関数だけ作成しようと思ったのですが、全く軌道に乗りません。。。orz

とりあえずヘッダとソースにわけて、コンパイルだけしてみたのですが、コンパイルが通りません。
#include <stdio.h>
#include <stdlib.h>
#include "QueControl.h"

struct Root root;

int    QueOpen(int RecSize, int RecN)
{
    // 引数のチェック
    if (RecSize <= 0 || RecN <= 0) {
        return -1;
    }
    
    root->List.Empty = (char *)calloc(RecSize, RecN);
        ↑で怒られます。
        流れとしてはココで3つのリスト分(空、高優先度、通常優先度)
        のメモリを確保しなくてはいけないのでしょうか?

    if (rec == NULL) {
        return -1;
    }
    
    return 0;
}
私の構造体の定義の仕方が間違っているのでしょうか?
序盤から行き詰ってしまいました。。。orz

Re:無題

Posted: 2010年4月02日(金) 12:01
by ideyan
コンパイルが通らないなら通らないで
せめてエラーの内容が無いと困ります^^;

struct {
    List    *Empty;        // 空リスト
    …
} Root;
この書き方は、Root と言う名前の構造体を定義するのではなく
名無しの構造体で Root 変数を宣言するとなるので
struct Root root は通りません。

仮に root が通ったとしても
root->List.Empty
root はポインタではないのでアロー演算子は使えません。

Root が持っているのはListという変数ではないので
アクセスする場合は
Root.List.Empty でなく Root.Empty となります。

後半にいきなり rec という変数が出てきています。

calloc の引数は num,size の順番です。

あと、QueOpen は
1.List 1個分だけ calloc
2. その中の rec に対して RecSize 分だけ calloc
3. 空リストに繋げる
4. 1~3を RecN 回繰り返す
このような手順でいくのがいいかと思います。

Re:無題

Posted: 2010年4月02日(金) 12:03
by Ma
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>


struct list{
list *next,*prev;
char *rec;
}lowPriority,highPriority,normalPriority;


int QueOpen(int RecSize, int RecN)
{
// 引数のチェック
if (RecSize <= 0 || RecN <= 0) {
return -1;
}

lowPriority.prev = NULL;
normalPriority.prev = NULL;
highPriority.prev = NULL;

list* pNodeList[/url] = { &lowPriority,&normalPriority,&highPriority};

for each(list* p in pNodeList){
for(int i = 0; i < RecN;i++){
p->rec = (char*)malloc(RecN);
p->next = (list *)malloc(sizeof(list));
if(p->next == NULL)
return -1;
list* tempPre = p;
p = p->next;
p->prev = tempPre;
}
}
return 0;
}



参考程度にしてください。
一応動作確認はしましたが、もっと最適化できそうだし、綺麗になりそうだし、間違いもあるかもしれませんのでw
画像

Re:無題

Posted: 2010年4月02日(金) 13:01
by テツ
ideyanさん
>コンパイルが通らないなら通らないで
>せめてエラーの内容が無いと困ります^^;

そっそうですよね。失礼しました^^;
以下のようなエラーです。
エラー E2451 QueControl.c 14: 未定義のシンボル List(関数 QueOpen )
エラー E2451 QueControl.c 15: 未定義のシンボル rec(関数 QueOpen )

ideyanさんがおっしゃる通りのエラーでした。

いろいろとありがとうございます。
少し整理してやってみます!

Maさん
サンプルのご提示ありがとうございます!
ただ今回Boralnd Bcc5.5というのを記述し忘れました。。。orz

Re:無題

Posted: 2010年4月02日(金) 13:05
by Ma
>ただ今回Boralnd Bcc5.5というのを記述し忘れました。。。orz
コードはそんなに変わらないと思うけども。。。

Re:無題

Posted: 2010年4月02日(金) 13:21
by テツ
Maさん

ここのfor each(list* p in pNodeList)
をCでいうfor文等に置き換えてやればいいのでしょうか?

構造体の管理は
struct list{
    list *next,*prev;
    char *rec;
}lowPriority,highPriority,normalPriority;
こちらのように全体で3つのルートをもつほうがよいのでしょうか?

質問ばかりですいません。
すごくてんぱってまして^^;

Re:無題

Posted: 2010年4月02日(金) 13:44
by たいちう
> こちらのように全体で3つのルートをもつほうがよいのでしょうか?
>
> 質問ばかりですいません。
> すごくてんぱってまして^^;

質問ばかりは良いのですが、同じ質問を繰り返していますよ。
今作っている課題のことは一旦忘れて、単純なリストのサンプルを作ってみてはどうですか。
理解せずに質問を繰り返すよりも、その方が早いと思うのですが。

Re:無題

Posted: 2010年4月02日(金) 13:44
by Ma
>ここのfor each(list* p in pNodeList)
>をCでいうfor文等に置き換えてやればいいのでしょうか?

書いたコードはC++言語です。
Wikipedia によると、C++標準ライブラリによって与えられるもので、Cでは使えないかもしれません。
BCCは for each 対応していないのだろうか?(そんなばかな)

もし、エラーでるようでしたら

for(int i = 0; i < 3; i++){
list* p = pNodeList;

と、置き換えてもOkです。(同じ意味ですので)

>こちらのように全体で3つのルートをもつほうがよいのでしょうか?
他に方法がおもいつかないので、それが最善だと思います。
構造体にひとつにまとめたとしても、ルートの数はかわらないとおもいますよ。 画像

Re:無題

Posted: 2010年4月02日(金) 13:51
by たいちう
具体的に課題を出します。

http://www9.plala.or.jp/sgwr-t/c/sec15-5.html

ここにリストの丁寧な説明があります。
「実際に」作って試し、「完全に」理解してください。
その上で、このプログラムのリストを双方向のリストに変更し、
リストを逆順で表示できるようにしてください。

Re:無題

Posted: 2010年4月02日(金) 15:14
by テツ
たいちうさん

レスありがとうございます。
これからそっちをやってみます!

Re:無題

Posted: 2010年4月02日(金) 15:31
by kaiten
>for each(list* p in pNodeList)

この構文って確かVC++独自の構文かなんかだったと思います。C++標準ライブラリに入ってるのはstd::for_eachだったかと。

Re:無題

Posted: 2010年4月02日(金) 15:42
by テツ
kaitenさん

情報ありがとうございます。
ちなみに今回C限定ということを記載し忘れました。。。orz
すみません。

Re:無題

Posted: 2010年4月02日(金) 23:40
by テツ
遅くなってすみません。とりあえず作成してみましたのでよろしくお願いします。 画像

Re:無題

Posted: 2010年4月04日(日) 18:00
by テツ
とりあえずたいちうさんの課題をやってみました。

>あと、QueOpen は
>1.List 1個分だけ calloc
>2. その中の rec に対して RecSize 分だけ calloc
>3. 空リストに繋げる
>4. 1~3を RecN 回繰り返す

この文通りにコーディングすればいいと思うのですが、
List1個分だけというのはどういうことなのでしょうか?

Re:無題

Posted: 2010年4月04日(日) 19:00
by sizuma
>List1個分だけというのはどういうことなのでしょうか?
List構造を構成する構造体を1つ、ということではないでしょうか?

まずはList(ポインタで構成)を一つ分確保
次にポインタで指すrecodeのメモリを確保
これを用意するバッファサイズまで

という流れだと思います。

Re:無題

Posted: 2010年4月04日(日) 22:08
by たいちう
> とりあえずたいちうさんの課題をやってみました。

課題の条件の書き方がまずかったようですね。
双方向リストの使い方の練習のために、
リストを正順・逆順どちらでも表示できるようにしてほしかったのです。
お手数ですが次の条件に変更できますか?

add_listは、リストの末尾に要素を追加。
show_listは、リストを正順で表示。
show_list_revは、リストを逆順で表示。

Re:無題

Posted: 2010年4月05日(月) 10:14
by テツ
sizumaさん

>まずはList(ポインタで構成)を一つ分確保
これはコードにするにはどういうふうにすればよいのでしょうか?

たいちうさん

>リストを正順・逆順どちらでも表示できるようにしてほしかったのです。
>お手数ですが次の条件に変更できますか?
これをQueOpen()にそってやるにはどうすればよいでしょうか?
とりあえずQueOpenだけでも完成させて持ってきてと言われたので^^;
困ってしまいました(泣

Re:無題

Posted: 2010年4月05日(月) 10:30
by たいちう
> これをQueOpen()にそってやるにはどうすればよいでしょうか?
> とりあえずQueOpenだけでも完成させて持ってきてと言われたので^^;
> 困ってしまいました(泣

ご理解いただいていると思っていたのですが、私の出している「課題」は
本来の課題に取り掛かるための準備運動のようなものです。
QueOpen等とは直接的な関係はありませんが、
本来の課題に取り組む前に1つ2つリストを使ったプログラムを作った方が
良いだろうと考えた上での誘導です。

取り急ぎQueOpenを作る必要があるとのことですが、
QueOpenを作るためにも、ある程度全体のイメージを掴まないといけません。
全体のイメージを把握するには今のテツさんは経験不足ですので、
私の出す「課題」に取り組むことが、結局早いのではないか、と私は思います。

Re:無題

Posted: 2010年4月05日(月) 11:15
by テツ
たいちうさん

>取り急ぎQueOpenを作る必要があるとのことですが、
>QueOpenを作るためにも、ある程度全体のイメージを掴まないといけません。
>全体のイメージを把握するには今のテツさんは経験不足ですので、
>私の出す「課題」に取り組むことが、結局早いのではないか、と私は思います。

そうですよね。。。ただそれはわかっているのですが、とりあえずQueOpenだけでも
提出した後デバッグしながら理解しようと思いまして^^;
やはりちゃんと設計してからの方がいいんでしょうか?

期間とかなければちゃんと基礎的なことをやってからやりたいのですが(泣

Re:無題

Posted: 2010年4月05日(月) 11:49
by たいちう
> そうですよね。。。ただそれはわかっているのですが、とりあえずQueOpenだけでも
> 提出した後デバッグしながら理解しようと思いまして^^;
> やはりちゃんと設計してからの方がいいんでしょうか?

いいも悪いも現段階ではQueOpenを作れないのでしょ?

Re:無題

Posted: 2010年4月05日(月) 11:57
by テツ
>いいも悪いも現段階ではQueOpenを作れないのでしょ?
はい。ですのでサンプル等いただければと思ったのですが、
それですと丸投げになってしまいますね^^;

ちょっとわかりそうにないので諦めます。
今まで付き合っていただきありがとうございました。

レスを下さった皆さまにも感謝致します。

それでは失礼します。

Re:無題

Posted: 2010年4月05日(月) 12:04
by Ma
>い。ですのでサンプル等いただければと思ったのですが、
サンプルあげたのに・・・orz

Re:無題

Posted: 2010年4月05日(月) 12:19
by テツ
Maさん

list* pNodeList[/url] = { &lowPriority,&normalPriority,&highPriority};
ここの部分を構造体で管理しようと思ったのですが、うまく出来なくて駄目でした^^;
あと引数のRecSizeはどこで使っているかわかりませんでした。
とりあえず構造体定義部分(メンバとか)だけでもしっかり理解できればよかったのですが。。。

ただMaさんのサンプルを基本に改良出来たらと思っています!
ありがとうございました。
ササッと作れない自分が情けないです。。。orz

Re:無題

Posted: 2010年4月05日(月) 12:56
by sizuma
あまり詳しく読んでないのですが、たいちうさんの出された課題なんて、ちゃんとすれば2・3時間で終わるんじゃないですか?
準備運動と書かれてるように、リスト構造さえ理解してればちょちょいとしたコードで実装できると思いますし。


>>まずはList(ポインタで構成)を一つ分確保
>これはコードにするにはどういうふうにすればよいのでしょうか?

struct Listが定義されてるとする
ここでListの構成要素はList型へのポインタpre,nextと登録されるデータ(文字列)へのポインタrecodeとする

for(バッファ数分){
  List型ひとつを確保
  recodeにメモリを確保
  preで確保したものと前の要素をくっつける
  前の要素からも、今回確保したものをくっつける(最初であればルートポインタ)
}

こんな感じじゃないでしょうか?
たいちうさんが張られたリンク先を見ればある程度理解はできると思うのですが。 画像

Re:無題

Posted: 2010年4月05日(月) 13:13
by たいちう
> あまり詳しく読んでないのですが、たいちうさんの出された課題なんて、ちゃんとすれば2・3時間で終わるんじゃないですか?
> 準備運動と書かれてるように、リスト構造さえ理解してればちょちょいとしたコードで実装できると思いますし。

私もその位に考えていたんですけどね。
リンク先の単方向リストをしっかり理解した後ならば30分程度でできるんじゃないかと。
但し、今までの学習でソースコードは殆ど読むだけで、
何となく理解したつもりになっているだけだったら、2・3時間じゃ到底できないでしょうが、
その場合は本来の課題に歯が立つ段階ではないと。

ちなみにOpenQueの締め切りはいつですか?
課題全体の締め切りと。

# 折角私の課題をやってくれたのに、No.50062の書き込みに気付かず、
# レスが丸二日も後になってしまったのは申し訳なかったです。
# 土曜日もこの掲示板は読んでいたはずですが気付きませんでした。

Re:無題

Posted: 2010年4月05日(月) 13:54
by テツ
sizumaさん

参考になります。ありがとうございます。
>前の要素からも、今回確保したものをくっつける(最初であればルートポインタ)
ココがちょっとわかりません。ルートポインタとはどういうことでしょうか?

たいちうさん

>何となく理解したつもりになっているだけだったら、2・3時間じゃ到底できないでしょうが、
>その場合は本来の課題に歯が立つ段階ではないと。
そうなんですよね^^;
今までのやつはwebを見たりして結構小手先のテクニックで出来たのですが、
今回のようなデータ構造系は苦手で(泣

>ちなみにOpenQueの締め切りはいつですか?
>課題全体の締め切りと。

課題自体は今週中なのですが、QueOpenは今日です(汗
遅くても明日の午前中くらいと言っていました。

Re:無題

Posted: 2010年4月05日(月) 13:57
by テツ
連レスすみません。

ちなみに3番のQueGetNでそれぞれのリストに繋がれている数を返す関数で、
必要と思われるメンバを構造体で定義したのですが、こんな感じで大丈夫でしょうか?
typedef struct List {
    struct    List    *next, *prev;
    char             *rec;
} List;

typedef struct {
    int        cntRegist;        // 登録最大件数
    int        cntEnptyList;        // 空リスト登録数
    int        cntHighPriorityList;    // 高優先度リスト登録数
    int        cntNormalPriorityList;    // 通常優先度リスト登録数
} CntList;

Re:無題

Posted: 2010年4月05日(月) 14:01
by Ma
>あと引数のRecSizeはどこで使っているかわかりませんでした。
失礼しました。

一部、間違っている部分があります。
p->rec = (char*)malloc(RecN);
正しくは
p->rec = (char*)malloc(RecSize);
でした。


>list* pNodeList[/url] = { &lowPriority,&normalPriority,&highPriority};
>ここの部分を構造体で管理しようと思ったのですが、うまく出来なくて駄目でした^^;


課題読んだ上で、別に構造体にしなくていいとおもいますが、どうしてもしたいなら

struct pNodeListStr{
list* nodeList[3];
void init(){
nodeList[0] = &lowPriority;
nodeList[1] = &normalPriority;
nodeList[2] = &highPriority;
}
};

とかにすればいいかと。
ただ、ほとんど無意味だと思うので、特に理由がないなら、さけたほうがいいとおもいますよ。

Re:無題

Posted: 2010年4月05日(月) 14:05
by Ma
>ちなみに3番のQueGetNでそれぞれのリストに繋がれている数を返す関数で、
>必要と思われるメンバを構造体で定義したのですが、こんな感じで大丈夫でしょうか?


変数を作って常に記録しておくのではなく、関数等でいつでもリストのサイズを取得できるようにしてほしいのだとおもいますよ。
ヒントをあげると、ノードをたどってNULLにあたるまで数をカウントする感じです。



>ルートポインタとはどういうことでしょうか?
ルート(根っこ)のポインタです。
prev (前のノード)がNULLなノードへのポインタのことです。
リストの一番最初のノードになります。 画像

Re:無題

Posted: 2010年4月05日(月) 14:12
by テツ
Maさん

>課題読んだ上で、別に構造体にしなくていいとおもいますが、どうしてもしたいなら
ただ、他の関数でも使うと思うので(考え方が間違っていたらすみません)
構造体にした方がいいのかと思いまして。
ちなみにC++使えないことを記述するのを忘れました。orz
すみません。

>変数を作って常に記録しておくのではなく、関数等でいつでもリストのサイズを取得できるように
>してほしいのだとおもいますよ。
>ヒントをあげると、ノードをたどってNULLにあたるまで数をカウントする感じです。
そういうことなんですかね?私はてっきり変数で用意するものと思っていました。
ということは3番で各ノードをNULLまで繰り返して件数を求めればいいんですね!

Re:無題

Posted: 2010年4月05日(月) 14:35
by たいちう
> 今までのやつはwebを見たりして結構小手先のテクニックで出来たのですが、
> 今回のようなデータ構造系は苦手で(泣
> ...
> 課題自体は今週中なのですが、QueOpenは今日です(汗

さてどうしたものかな。QueOpenを私が代わりに作るのは避けたいし。

【プログラム全体のイメージ】
双方向であることはしばらく忘れて、リストを洋服のハンガーと思ってください。
タンスにはハンガーをかけるフックが3つあります。
またハンガーにはハンガーを1つだけかけることができます。
ハンガーは1着の服をかけることができます。かけないでもOKです。
これで理論的には、タンスは無限個のハンガー(と服)を収納できます。
1つのフックにかかっている一連のハンガーを「リスト」と呼びましょう。
タンスにはフックが3つあるので、3つのリストがあります。
(ハンガーのかかってないフックも空の「リスト」とみなします。)
3つのリストにはそれぞれ用途があり、それぞれ「空のハンガーのリスト」
「普通の服のかかったハンガーのリスト」「良い服のかかったハンガーのリスト」です。

【QueOpenで行うことのイメージ】
QueOpenは2つの引数をとります。
RecSizeはハンガーの大きさ。
RecNはハンガーの個数とみなせるでしょう。
服にはサイズが色々ありますが、小さいハンガーには小さい服のみかけることができ、
大きいハンガーには大きい服も小さい服もかけられます。
題意よりタンスの中のハンガーは全て同じ大きさです。

QueOpenが呼ばれたら、指定された大きさのハンガーを指定された個数用意します。
ここでは服(データ)はまだ用意しません。
全てのハンガーは空のハンガーなので、全体で「空のハンガーのリスト」を作ります。


# 提出後にQueOpenを改良しても良いのだろうし、
# こんなイメージでしのげませんか?
# 判らなければ再度質問してください。

Re:無題

Posted: 2010年4月05日(月) 14:49
by テツ
たいちうさん

ありがとうございます。以前よりイメージは掴めました。

># 提出後にQueOpenを改良しても良いのだろうし、
># こんなイメージでしのげませんか?
それがしのげないんですよ^^;
早くコード持ってきてね(ニコ)って言われました。。。orz

ちなみにMaさんのを改良してみたのですが、こんな感じで大丈夫なのでしょうか?
#include <stdio.h>
#include <stdlib.h>

struct list{
    list    *next,*prev;
    char     *rec;
} enpty, high, normal;


int QueOpen(int RecSize, int RecN)
{
    struct    list    *p, *tempPre;
    int        i;
    
    // 引数のチェック
    if (RecSize <= 0 || RecN <= 0) {
        return -1;
    }
    
    p = NULL;
    tempPre = NULL;
    enpty.prev = NULL;
    normal.prev = NULL;
    high.prev = NULL;

    list* pNodeList[/url] = { &enpty, &normal, &high };
    
    for (i = 0; i < 3; i++) {
        list *p = pNodeList
        for (j = 0; j < RecN; j++){
            p->rec = (char *)malloc(RecSize);
            p->next = (list *)malloc(sizeof(list));
            if (p->next == NULL) {
                return -1;
            }
            tempPre = p;
            p = p->next;
            p->prev = tempPre;
        }
    }    
    return 0;
}

Re:無題

Posted: 2010年4月05日(月) 15:00
by たいちう
> それがしのげないんですよ^^;
> 早くコード持ってきてね(ニコ)って言われました。。。orz

私の言う「しのぐ」は、完璧でないとしても
OpenQueのコードを作ることを意味しています。
これだけ説明したんだから何とか作れるかい?ということ。


> ちなみにMaさんのを改良してみたのですが、
> こんな感じで大丈夫なのでしょうか?

私あてではないと思いますが、他力本願であまり見たくない質問です。
自分でコンパイルはしたのか?テストはしたのか?
有効なテストができなかったのだとすれば、
「どのようにしてテストしたらよいでしょうか?」
という質問になるはずです。

Re:無題

Posted: 2010年4月05日(月) 19:15
by Ma
>ちなみにC++使えないことを記述するのを忘れました。orz
いえ、存じていますがC++言語からC言語にコードを変えるのはそんなに難しくないと思いますよ。
まぁ、実際できたようですし。

>struct list *p
pが二度宣言されてます。
ひとつめのpを消すか、二つ目のpを消してください。
まぁ、いつ宣言するかは人の好みだと思うので、どちらで宣言してもいいとおもいます。

Re:無題

Posted: 2010年4月05日(月) 19:28
by Ma
あと、再び読み直して、おかしいと思ったので修正。

for (j = 0; j < RecN; j++){
p->rec = (char *)malloc(RecSize);
p->next = (list *)malloc(sizeof(list));
if (p->next == NULL) {
return -1;
}
tempPre = p;
p = p->next;
p->prev = tempPre;
}


ではなく、


for (j = 0; j < RecN; j++){
p->rec = (char *)malloc(RecSize);

if (p->next == NULL) {
return -1;
}
if(j+1 < RecN){
p->next = (list *)malloc(sizeof(list));
if(p->next == NULL){
return -1;
}
tempPre = p;
p = p->next;
p->prev = tempPre;
}
else
p->next = NULL;
}

か、あるいは、

for (j = 0; j < RecN-1; j++){
p->rec = (char *)malloc(RecSize);
if (p->rec == NULL) {
return -1;
}
p->next = (list *)malloc(sizeof(list));
if (p->next == NULL) {
return -1;
}
tempPre = p;
p = p->next;
p->prev = tempPre;
}
p->next = NULL;
p->rec = (char *)malloc(RecSize);
if (p->rec == NULL) {
return -1;
}


等。


できれば、内容を読んでどう違うのか理解して修正していただきたい。
あと、たいちうさんが言うように、このようなミスはprintfを生かして実験してみればすぐに気づくので
ご自身で、これで満足いく動作をするか確かめてみてください。
(まだ間違っている可能性もありますので) 画像

Re:無題

Posted: 2010年4月05日(月) 22:58
by テツ
たいちうさん、Maさんレスありがとうございます。

今やってみて思ったのですが、forループは1回だけでは駄目でしょうか?
高優先度リストと、通常優先度リストの領域は確保しなくてもいいような気がしたのですが、
考え違いでしょうか?

Re:無題

Posted: 2010年4月05日(月) 23:55
by たいちう
仕様にこのような記述があります。

> キューへの登録要求を受けると、空きリストから一つのレコードバッファを取り出し、要
> 求された登録情報をレコードバッファにセットし、登録リストの末尾に接続する。

QueOpenが終了したときに、リストはどのような状態になっているべきと思いますか?
No:50188の説明も読み返して考えてみて下さい。

Re:無題

Posted: 2010年4月06日(火) 01:08
by テツ
>QueOpenが呼ばれたら、指定された大きさのハンガーを指定された個数用意します。
>ここでは服(データ)はまだ用意しません。
>全てのハンガーは空のハンガーなので、全体で「空のハンガーのリスト」を作ります。
ということは空、高、通常の3つ分の領域を確保しなければならないのでしょうか?

>QueOpenが終了したときに、リストはどのような状態になっているべきと思いますか?
空リストの領域がRecN個分確保されていればいいのではないでしょうか?
それで2番目のQueRegistの時に空リストのアドレスを条件に従って、通常または高に渡してやればいいのかと思ったのですが。
違いますでしょうか?

でも上記で自分が言ってることって矛盾してますよね^^;

Re:無題

Posted: 2010年4月06日(火) 04:29
by Ma
>空リストの領域がRecN個分確保されていればいいのではないでしょうか?
>それで2番目のQueRegistの時に空リストのアドレスを条件に従って、通常または高に渡してやればいいのかと思ったのですが。
>違いますでしょうか?

すいません、私勘違いしていたみたいです。課題の意味がようやくわかりました。
てっきり、優先度が三つあるのかと勘違いしておりました。
前半の投稿から、空リストなんてへんな名前つけるなぁ、と思ってました(汗

そうですね、初期化するときは、空リストにメモリ確保を指示してそれ以外のリストはNULLにしておけばいいんじゃないでしょうか。


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


struct list{
list *next,*prev;
char *rec;
} empty, high, normal;



int QueOpen(int RecSize, int RecN)
{
// 引数のチェック
if (RecSize <= 0 || RecN <= 0) {
return -1;
}

high.next = NULL;
high.prev = NULL;
high.rec = NULL;
normal.next = NULL;
normal.prev = NULL;
normal.rec = NULL;
empty.rec = NULL;
empty.prev = NULL;
empty.next = NULL;

list* now = & empty;
list* pre = NULL;
for (int i = 0; i < RecN; i++){
now->rec = (char *)malloc(RecSize);
if(i+1 < RecN)
now->next = (list *)malloc(sizeof(list));
if(pre != NULL)
now->prev = pre;
pre = now;
now = now->next;
}

return 0;
}


void main(){
QueOpen(10,2);
}

また参考程度に。
あと、malloc 失敗してないときの判定いれてないので、そのへんは修正お願いします。 画像

Re:無題

Posted: 2010年4月06日(火) 09:08
by テツ
Maさん

サンプルありがとうございます。
動かして試してみたいと思います!

Re:無題

Posted: 2010年4月06日(火) 09:11
by たいちう
> >全てのハンガーは空のハンガーなので、全体で「空のハンガーのリスト」を作ります。
> ということは空、高、通常の3つ分の領域を確保しなければならないのでしょうか?

タンス全体で「空のハンガーのリスト」が1つ有ればよいのです。
「高、通常の3つ分の領域を確保」は、「フック」用意するだけです。
ですので、↓この解釈であってます。

> >QueOpenが終了したときに、リストはどのような状態になっているべきと思いますか?
> 空リストの領域がRecN個分確保されていればいいのではないでしょうか?
> それで2番目のQueRegistの時に空リストのアドレスを条件に従って、
> 通常または高に渡してやればいいのかと思ったのですが。
> 違いますでしょうか?


それと気付いた点1つめ。
× enpty
○ empty

2つめ。
問題文にレコードの定義が明確に書かれていませんが、
QueRegistの引数からおそらく文字列がデータであると思われます。
QueOpenの2つめの引数に渡されるのが文字列長だとすると、
必要な領域は(文字列長 + 1)バイト必要です。


Maさん>
> >ちなみにC++使えないことを記述するのを忘れました。orz
> いえ、存じていますがC++言語からC言語にコードを変えるのはそんなに難しくないと思いますよ。
> まぁ、実際できたようですし。

Cに四苦八苦している人には難しい場合もあるでしょう。
もしもやったことがないならば、一度ご自分のソースコードの拡張子をcに変更して
コンパイルしてみてください。
思っているよりも変更は多いかもしれませんよ。

Re:無題

Posted: 2010年4月06日(火) 09:46
by テツ
修正してみたのですが、39、47、53、56行目で問題のあるポインタ変換と出ます。
これはどの部分を修正すればいいのでしょうか?

管理テーブルとか作ってしまってすみません^^;
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char    *rec;
    struct    List    *prev;
    struct    List    *next;
} List;

// 管理テーブル
typedef struct {
    int        RecN;
    List    *dataList;
} ControlList;

ControlList    empty, high, normal;

int QueOpen(int RecSize, int RecN)
{
    List    *now;
    List    *pre;
    int        i;

    // 引数のチェック
    if (RecSize <= 0 || RecN <= 0) {
        return -1;
    }

    empty.dataList->rec   = NULL;
    empty.dataList->prev  = NULL;
    empty.dataList->next  = NULL;

    now = &empty;
    pre = NULL;
    for (i = 0; i < RecN; i++) {
        now->rec = (char *)malloc(RecSize);
        if (now->rec == NULL) {
            return -1;
        }
        if (i + 1 < RecN) {
            now->next = (List *)malloc(sizeof(List));
            if (now->next == NULL) {
                return -1;
            }
        }
        if (pre != NULL) {
            now->prev = pre;
        }
        pre = now;
        now = now->next;
    }
    return 0;
}

int    main(void)
{
    QueOpen(10,2);

    return 0;
}

Re:無題

Posted: 2010年4月06日(火) 09:50
by テツ
たいちうさん

>QueOpenの2つめの引数に渡されるのが文字列長だとすると、
>必要な領域は(文字列長 + 1)バイト必要です。

2つめの引数は空リストの数ではないのでしょうか?

Re:無題

Posted: 2010年4月06日(火) 10:05
by Ma
>必要な領域は(文字列長 + 1)バイト必要です。
かもしれませんね。


>Cに四苦八苦している人には難しい場合もあるでしょう。
たしかに、そうかもしれないですね。
言うだけじゃいけないと思ったので実際やってみたら、自分はCの学習はあまりしたことがなかったので、てこずりました(汗
せっかく作ったので、参考にでもどうぞです。

(RecSize+1 のところは、引数の意図が分かり次第変えてください。)


//test.c
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>


struct list{
struct list *next,*prev;
char *rec;
} empty, high, normal;



int QueOpen(int RecSize, int RecN)
{
struct list *now,*pre;
int i;

now = &empty;
pre = NULL;

// 引数のチェック
if (RecSize <= 0 || RecN <= 0) {
return -1;
}

high.next = NULL;
high.prev = NULL;
high.rec = NULL;
normal = high;
empty = high;



for (i = 0; i < RecN; i++){
now->rec = (char *)malloc(RecSize+1);
if(i+1 < RecN)
now->next = (struct list *)malloc(sizeof(struct list));
if(pre != NULL)
now->prev = pre;
pre = now;
now = now->next;
}

return 0;
}


void main(){
QueOpen(10,2);
}


*追記
>2つめの引数は空リストの数ではないのでしょうか?
一つ目との間違いだと思います。 画像

Re:無題

Posted: 2010年4月06日(火) 10:15
by たいちう
このように書けます。

typedef struct tagList {
char *rec;
struct tagList *prev;
struct tagList *next;
} List;

http://www.bohyoh.com/CandCPP/FAQ/FAQ00051.html


もう一つはきっと管理テーブルに関連するものでしょうが、
ご自分で導入したものだし、コピペにも失敗していることですので、
もう少し考えてみてください。
と思ったけど、時間がないんだっけ。

now = empty.dataList;

です。emptyが文字化けしているみたいなので、全角で貼り付けました。
enptyだったらこんなことにはならなかったか。


> 一つ目との間違いだと思います。

フォローありがとうございます。

Re:無題

Posted: 2010年4月06日(火) 10:27
by Ma
いろいろ間違っている気がしたので、修正したものを添付しました。

*ただし、もともとのコードに間違いがあってコンパイルできても実行時エラーになります。

Re:無題

Posted: 2010年4月06日(火) 10:36
by Ma
比較

ってここまでやらなくていいですよね(汗

Re:無題

Posted: 2010年4月06日(火) 11:26
by テツ
たいちうさんMaさん

本当にありがとうございます。
とりあえず午前中に見せてきます!
感謝感激です。

Re:無題

Posted: 2010年4月06日(火) 14:18
by テツ
お世話になります。
提出しましたら、続きをやってと言われたので、とりあえずほっとしました。
またお世話になりそうです^^;
その際はよろしくお願いします。
プログラムって出来ると楽しいですけど、出来ないと苦痛だということがわかりました。。。orz
頑張ります^^