ページ 1 / 1
help me
Posted: 2011年11月20日(日) 13:11
by aicezuki
次の構造体を用いて、ポインタ版リスト構造によるスタックを実装せよ。
。
typedef struct {
int max;
int num;
List stk;
} Stack;
typedef struct {
Node *head;
Node *crnt;
} List;
typedef struct __node {
char data;
struct __node *next;
} Node;
Teach me , please.
Re: help me
Posted: 2011年11月20日(日) 13:39
by Dixq (管理人)
まずはフォーラムルール
http://dixq.net/board/board.html
をご覧ください。
・現時点で分かっていること
・分からないこと
を明確にして下さい。
なお、aicezukiというお名前は以前問題になったハンドルネームとお見受けします。
今後のトラブル防止のためにも他の名前に改名してはいかがでしょうか。
Re: help me
Posted: 2011年11月20日(日) 14:32
by beatle
言語指定が無かったのでC++でやってみました。
長いので畳んでおきます。
► スポイラーを表示
コード:
#include <iostream>
#include <stdexcept>
typedef struct Node
{
char data;
struct Node *next;
} Node;
typedef struct
{
Node *head;
Node *crnt;
} List;
typedef struct
{
int max;
int num;
List stk;
} Stack;
class ListManager
{
public:
static List Create()
{
return { nullptr, nullptr };
}
static void Add(List& l, char c)
{
if (l.head == nullptr)
{
l.head = l.crnt = CreateNode(c, nullptr);
}
else
{
l.crnt = l.crnt->next = CreateNode(c, nullptr);
}
}
static void RemoveAt(List& l, int index)
{
if (index < 0)
{
throw std::out_of_range("index is out of range");
}
else if (index == 0)
{
if (l.head == nullptr)
{
throw std::out_of_range("index is out of range");
}
auto* temp = l.head;
l.head = l.head->next;
delete temp;
}
else
{
auto* node = NodeIndexOf(l, index - 1);
if (node == nullptr || node->next == nullptr)
{
throw std::out_of_range("index is out of range");
}
auto* temp = node->next;
node->next = node->next->next;
delete temp;
}
}
static char IndexOf(List& l, int index)
{
auto* node = NodeIndexOf(l, index);
if (node == nullptr)
{
throw std::out_of_range("index is out of range");
}
return node->data;
}
static void Destroy(List& l)
{
Destroy(l.head);
}
private:
static Node* CreateNode(char c, Node* next)
{
return new Node { c, next };
}
static Node* NodeIndexOf(List& l, int index)
{
if (l.head == nullptr)
{
return nullptr;
}
auto* node = l.head;
for (int i = 0; i < index && node != nullptr; ++i)
{
node = node->next;
}
return node;
}
static void Destroy(Node* n)
{
if (n != nullptr)
{
Destroy(n->next);
delete n;
}
}
};
class StackManager
{
public:
static Stack Create(int max)
{
if (max < 0)
{
throw std::out_of_range("max must not be negative");
}
return Stack { max, 0, ListManager::Create() };
}
static void Push(Stack& s, char c)
{
if (s.num < s.max)
{
ListManager::Add(s.stk, c);
s.num++;
}
else
{
throw std::runtime_error("stack is full");
}
}
static char Pop(Stack& s)
{
if (s.num == 0)
{
throw std::runtime_error("stack is empty");
}
else
{
auto c = ListManager::IndexOf(s.stk, s.num - 1);
ListManager::RemoveAt(s.stk, s.num - 1);
s.num--;
return c;
}
}
static void Destroy(Stack& s)
{
ListManager::Destroy(s.stk);
}
};
Stack& operator %(Stack& s, char c)
{
StackManager::Push(s, c);
return s;
}
char operator *(Stack& s)
{
return StackManager::Pop(s);
}
int main()
{
auto stk = StackManager::Create(3);
for (int i = 0; i < 3; ++i)
{
stk % i;
}
for (int i = 0; i < 2; ++i)
{
std::cout << (int)*stk << std::endl;
}
StackManager::Destroy(stk);
}
Re: help me
Posted: 2011年11月20日(日) 16:29
by aicezuki
ありがとうございます。
説明不足でした。
c言語でお願いできますか。
Re: help me
Posted: 2011年11月20日(日) 16:35
by softya(ソフト屋)
Dixq (管理人) さんの言われる通り、まずフォーラルルールを御覧ください。
それと故意でないにしても、問題のある名前はトラブルの原因となりますので避けて頂くとありがたいです。
引用:宿題の質問はOK!でも丸投げはX 宿題の文章だけ書いて「誰か答えて下さい」はX
課題の丸投げ(問題文だけ書く事)は禁止です。
ただし上のように記載してもらえればこれは当てはまりません。
自分でどこまでやったのか、今どこが解らないのかを明確にして下さい。
さっぱり解らず、手も足も出ない時は、その事を明記の上、
勉強方法からアドバイスを受けましょう。
どうしても提出期限の関係で答えが欲しい時はその事をしっかり明記の上、
回答者さん達の理解を求めるようにしましょう。
また、解決した時は、「解決しました」とだけ言って去らず、ソースコードや解決した方法を明記して下さい。
同じ事で困っている人の為に過去ログに有用な情報を残すようお願いします。
質問テンプレートをお使い下さい。
[1] 質問文
[1.1] 自分が今行いたい事は何か
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
[1.4] 今何がわからないのか、知りたいのか
[2] 環境
[2.1] OS : Windows, Linux等々
[2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
[3] その他
・どの程度C言語を理解しているか
・ライブラリを使っている場合は何を使っているか
Re: help me
Posted: 2011年11月20日(日) 17:18
by unknown
忠告ありがとうございます。
C言語はさっぱりわからないんですが授業の課題なのでやらなければならなくて丸投げしてしまいました。
コンパイラはBorlandでOSはWindowsです。
C言語でお願いいたします。
Re: help me
Posted: 2011年11月20日(日) 17:31
by softya(ソフト屋)
こちらのスタンスは宿題のお手伝いをすると言う所にありますので、今の宿題で何処が分からないか教えていただけますか。
あと幾つか質問があります。
・mainプログラムは少しでも書かれていないのでしょうか?
・この課題だとC言語の授業でだいぶ進んだ状態だと思いますが、どのあたりからC言語の理解に不安がありますか?
ポインタ、リスト構造、mallocは難易度が高いにしても、それ以前の部分でどうでしょうか?
とりあえず、コードタグで見やすくしたものを貼っておきます。
コード:
typedef struct {
int max;
int num;
List stk;
} Stack;
typedef struct {
Node *head;
Node *crnt;
} List;
typedef struct __node {
char data;
struct __node *next;
} Node;
Re: help me
Posted: 2011年11月20日(日) 17:41
by naohiro19
[迷信] 構造体のタグ名は下線で始める
コード:
typedef struct _FOO {
...
} FOO;
_FOO のように、下線(アンダースコア、アンダーバー)で始まり、下線または大文字が続く識別子は「
予約済み識別子」です。予約済み識別子というのは、規格がライブラリに使うか、処理系が作業用または拡張用に使うために予約されている識別子で、それらを
ユーザープログラムで使用することはできません(使用した場合の動作は未定義です)。
Re: help me
Posted: 2011年11月20日(日) 17:50
by みけCAT
横から失礼します。
naohiro19 さんが書きました:下線または大文字が続く識別子
ということは、下線のあとが小文字ならいいのですか?
例えばこのように。
コード:
typedef sturct _hoge_t {
int foo;
int baa;
} hoge_t;
Re: help me
Posted: 2011年11月20日(日) 17:55
by beatle
http://www.wdic.org/w/TECH/%E4%BA%88%E7 ... 5%E5%AD%90
とか
http://portable-c.jugem.jp/?eid=10
によれば、グローバルな名前の場合は下線で始まる名前は全滅みたいですね。
ちなみに、構造体タグ名とtypedef名は名前空間が違うため重複してもいいですから
コード:
typedef struct hoge_t {
int foo;
int baa;
} hoge_t;
と書きましょう。
この話はnaohiro19さんが提示されたURLに載っている話です。
Re: help me
Posted: 2011年11月20日(日) 18:07
by softya(ソフト屋)
そもそも課題ですので__nodeの名前を変更できない可能性も大きいんじゃないかと思ったりしますが、どうなのでしょう?unknownさん。
Re: help me
Posted: 2011年11月20日(日) 18:17
by beatle
勝手な意見ですが、
「__nodeという名前はこれこれこういう理由により使用してはいけない。よって、このように修正した。」
とか書いて提出すれば、素晴らしい回答になると思います。
Re: help me
Posted: 2011年11月20日(日) 18:19
by unknown
C言語はまずポインタと構造体がさっぱり理解できず、最近は授業についていくことができません。
名前の変更はできないと思います。
Re: help me
Posted: 2011年11月20日(日) 18:39
by softya(ソフト屋)
beatle さんが書きました:勝手な意見ですが、
「__nodeという名前はこれこれこういう理由により使用してはいけない。よって、このように修正した。」
とか書いて提出すれば、素晴らしい回答になると思います。
それは先生によっては喧嘩を売っているようなものかと。
勝手に変えたということで課題が不可となる可能性も・・・。
unknown さんが書きました:C言語はまずポインタと構造体がさっぱり理解できず、最近は授業についていくことができません。
配列なら理解できますか?
まず、固定数の配列だけでスタックのプログラムを書いてみてください。
それをベースに構造化→ポインタ化してみましょう。
Re: help me
Posted: 2011年11月20日(日) 18:54
by たかぎ
softya(ソフト屋) さんが書きました:beatle さんが書きました:勝手な意見ですが、
「__nodeという名前はこれこれこういう理由により使用してはいけない。よって、このように修正した。」
とか書いて提出すれば、素晴らしい回答になると思います。
それは先生によっては喧嘩を売っているようなものかと。
勝手に変えたということで課題が不可となる可能性も・・・。
同じ喧嘩を売るのなら、Borland特有の拡張仕様やバグをついた実装をして提出した方がずっとおもしろいですね。
それを指摘されたときに初めて、「どうせ未定義の動作に依存したプログラムしか書けないので、五十歩百歩である」ことを伝えると完璧です。
Re: help me
Posted: 2011年11月20日(日) 23:40
by たかぎ
一応、Cで作ってみました。
ただし、情報が少ないので期待している仕様になっているかどうかは知りません。
また、おそらく手元の処理系では、そのままではコンパイルできないでしょうから、どうすべきかは自分で考えてください。
コード:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct __node {
char data;
struct __node *next;
} Node;
typedef struct {
Node *head;
Node *crnt;
} List;
typedef struct {
int max;
int num;
List stk;
} Stack;
bool stack_init(Stack *stack)
{
if (stack == NULL)
return false;
*stack = (Stack){ 0 };
return true;
}
bool stack_term(Stack *stack)
{
if (stack == NULL)
return false;
Node *node = stack->stk.head;
while (node != NULL)
{
Node *p = node;
node = node->next;
free(p);
}
return true;
}
bool stack_push(Stack *stack, char data)
{
if (stack == NULL)
return false;
Node *node = malloc(sizeof(Node));
if (node == NULL)
return false;
*node = (Node){ .data = data, .next = stack->stk.head };
stack->stk.head = node;
return true;
}
bool stack_pop(Stack* stack, char* data)
{
if (stack == NULL || data == NULL)
return false;
if (stack->stk.head == NULL)
return false;
Node *node = stack->stk.head;
*data = node->data;
stack->stk.head = node->next;
free(node);
return true;
}
int main(void)
{
Stack stack[1];
stack_init(stack);
for (;;)
{
int data;
scanf("%d", &data);
if (data < 0 || 127 < data)
break;
stack_push(stack, data);
}
for (;;)
{
char data;
if (!stack_pop(stack, &data))
break;
printf("%d\n", data);
}
stack_term(stack);
}