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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

3566閲覧

C言語 二分木を生成する

iheanachonpa

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/06/24 02:34

scanfで <<-,1,->,2,<-,3,->> と入力して、それを二分木にする関数を作っているんですが、scanfで読み込むために宣言したcharの配列buffを解析する関数がわからないので教えてほしいです。

※ <,,~>が一つの節点を表していて、- は子の節点がないことを意味します。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

正規表現でやってみた(Cだとちょっと面倒かしら...)

C++

1#include <iostream> 2#include <string> 3#include <regex> 4 5using namespace std; 6 7struct node { 8 node* left; 9 string value; 10 node* right; 11}; 12 13node* parse(const string& str) { 14 node* result = new node(); 15 regex re(R"_(<(<.*>|-),([^<>,]+),(<.*>|-)>)_"); 16 smatch match; 17 if ( regex_match(str, match, re) ) { 18 result->left = match.str(1) == "-" ? nullptr : parse(match.str(1)); 19 result->value = match.str(2); 20 result->right = match.str(3) == "-" ? nullptr : parse(match.str(3)); 21 } else { 22 result->left = nullptr; 23 result->value = str; 24 result->right = nullptr; 25 } 26 return result; 27} 28 29void print(node* p) { 30 if ( p ) { 31 cout << (p->left ? " left ":"(null)"); 32 cout << " [" << p->value << "] "; 33 cout << (p->left ? "right ":"(null)"); 34 cout << endl; 35 } else { 36 cout << "(null)\n"; 37 } 38} 39 40int main() try { 41 node* root = parse("<<-,1,->,2,<-,3,->>"); 42 print(root); 43 print(root->left); 44 print(root->right); 45} catch ( const regex_error& err ) { 46 cout << err.code() << ':' << err.what() << endl; 47}

実行結果

投稿2016/06/24 05:26

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2016/06/24 06:36

ああ、よく見たら一つ一つのノードがカンマで区切られてるわけじゃないんですね。 これは確かに正規表現を使わない方が楽かもしれません。 episteme さんすみませんでした。 そしてお見事です。
episteme

2016/06/24 07:50

おもっきし手を抜いたパーサです。 「ノード は "<ノード,数,ノード>" または "-" である」を正規表現にして、 ノード中のノードを見つけたら再帰。 #てか”見たまんま”ですねー
guest

0

構文解析というのは、それ自体がかなり手間のかかる作業です。

とはいえ、この規模の問題だとそこまで規模も大きくならないので、再帰的下向き構文解析のようなものを手で書いても、じゅうぶん書ける範囲です。

スクリプト言語を作る場合など、構文自体が巨大なものになる場合は、構文解析器を作るツールを活用するのがいいでしょう。C/C++の場合はyacc/bisonあたりが定番ですし、C#用のものも存在します。

投稿2016/06/24 02:56

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

正規表現使ったらいいんじゃないですか?

投稿2016/06/24 02:42

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2016/06/24 02:45

正規表現を再帰的に適用せんならんだろけど...うまくいくかしら...
Zuishin

2016/06/24 02:49

カンマでスプリットしてリストに突っ込んで再帰でもループでも。 構文解析はそれが一番楽です。
Zuishin

2016/06/24 03:36

木を作るのには普通はノードとなるオブジェクトや構造体を作ってそれを繋いでいくんですが、この事例のように二分木で大きさが分かっている場合にはもっと簡単な方法が使えます。 まずはノードの数(カンマの数からわかるはずです)を数えて十分な大きさの配列を用意し、そこに埋めていくだけです。 配列の要素 0 はルートを表し、1 と2 は 0 の子、3 と 4 は1 の子、5 と 6 は 2 の子という風に、添え字をと節の位置が 1 対 1 対応しますので、位置を簡単に計算でき、極めて高速に処理できます。 これを使うと、ノードの親子関係をたどらなくても処理中のノードをどこに保存すればいいかわかるので、再帰を使わず簡単なループで処理できます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問