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

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

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

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

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

3回答

3018閲覧

C言語でL21有限オートマトンのプログラム

yukihirotahu

総合スコア8

C

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

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

0グッド

0クリップ

投稿2020/11/02 11:35

C言語でL21有限オートマトンのプログラムを作りたいのですが、どこを直せばうまく機能してくれるのでしょうか?
aのm乗bのn乗|m,n>0が成り立つプログラムを作りたいです。
例えばaaabだとしたらYESと表示され、
bbaとかだとNOと表示されるプログラムです。

C言語

1#define p 0 2#define q 1 3#define r 2 4#define d 3 5#include <stdio.h> 6int main(void) 7{ 8 int s; 9 char c[30]; 10 s=p; 11 scanf("%s",c); 12 while( c!='\0' ){ 13 if(( s==p ) && (s=='a')){ 14 s=q; 15 } else if(( s==p ) && ( c='b' )){ 16 s=d; 17 } else if(( s==q ) && ( c='a' )){ 18 s=q; 19 } else if(( s==q ) && ( c='b' )){ 20 s=r; 21 } else if(( s==r ) && ( c='a' )){ 22 s=d; 23 } else if(( s==r ) && ( c='b' )){ 24 s=r; 25 } else if(( s==d ) && ( c='a' )){ 26 s=d; 27 } else if(( s==d ) && ( c='b' )){ 28 s=d; 29 } 30 } 31 if( s==r ){ 32 printf("Yes"); 33 } else{ 34 printf("No"); 35 } 36}

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

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

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

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

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

y_waiwai

2020/11/02 11:39

提示のコードではどういう不具合があるんでしょうか
kazuma-s

2020/11/02 13:53

質問では「m,n>0が成り立つ」となっていますが、 「m - n > 0」または「m > n」の間違いではありませんか?
yukihirotahu

2020/11/02 16:05

m、n>0が成り立つで合っています。 最初が必ずaから始まってbで終わらなければいけなく、aが1でbが2だったらabbです。
kazuma-s

2020/11/02 16:53 編集

「m,n>0」と書かれたら「m>0 かつ n>0」と普通は解釈しませんか? それなら、m=1 かつ n=2 でどちらも正なので YES になってしまいます。 「m > n > 0」の間違いではありませんか? aabb は YES ですか、NO ですか? それから、「L21有限オートマトン」とはなんですか? 普通の有限オートマトンなら分かるんですが、L21 が何を意味しているのかが分かりません。 さらに、aがm個と b がn個で m > n ということは、受理できる文字列は次の BNF で表せるのはないでしょうか? 非終端記号を {S, T, U}、終端記号を {a, b}、開始記号を S とし、 S := T U T := a | a T U := a b | a U b するとこれは文脈自由文法であり、プッシュダウンオートマトンなのではありませんか? 有限オートマトンではないように思います。
guest

回答3

0

ベストアンサー

質問のコードは変数の型と値が完全におかしいのでダメです。

次のように書けば、入力文字列を受理できるかどうか判定できると思います。

C

1#include <stdio.h> 2 3int automaton(const char *s) 4{ 5 int m = 0, n = 0, i = 0; 6 for (; s[i] == 'a'; i++) m++; 7 for (; s[i] == 'b'; i++) n++; 8 return s[i] == '\0' && m > n && n > 0; 9} 10 11int main(void) 12{ 13 char s[100]; 14 while (printf(">> "), scanf("%99s", s) == 1) 15 puts(automaton(s) ? "YES" : "NO"); 16}

実行例

test

1$ ./a.out 2>> a 3NO 4>> b 5NO 6>> aa 7NO 8>> ab 9NO 10>> ba 11NO 12>> bb 13NO 14>> aaa 15NO 16>> aab 17YES 18>> abb 19NO 20>> aba 21NO 22>> baa 23NO 24>> aaab 25YES 26>> ^D 27$

追記
状態変数 s と状態 { p, q, d } で有限オートマトン風に書き直してみました。

C

1#include <stdio.h> 2 3enum { p = 0, q = 1, d = -1 }; 4 5int automaton(const char *str) 6{ 7 int s = p, c; 8 while (s != d && (c = *str++)) 9 if (s == p && c == 'a') s = q; 10 else if (s == p && c == 'b') s = d; 11 else if (s == q && c == 'a') s++; 12 else if (s == q && c == 'b') s = d; 13 else if (s > q && c == 'a') s++; 14 else if (s > q && c == 'b') s = -s; 15 else if (s < d && c == 'a') s = d; 16 else if (s < d && c == 'b') s++; 17 return s < d; 18} 19 20int main(void) 21{ 22 char s[100]; 23 while (printf(">> "), scanf("%99s", s) == 1) 24 puts(automaton(s) ? "YES" : "NO"); 25}

しかし、状態は { p, q, d, >q, <d } であり、
q より大きい数は無数にあるので、 これを有限状態とは言えません。

追記2

例えばaaabだとしたらYESと表示され、

bbaとかだとNOと表示されるプログラムです。

私はこれを読み違えて、aaab は YES、abb は NO と書かれているものだと
信じ込んでいました。
だから、m > n という条件を勝手に想定していました。
そして、それは有限オートマトンにはなりえないと言ってしまいました。

m > 0 かつ n > 0 という条件があるだけで m と n の大小が無関係なら
それは "a+b+" または "aabb" という正規表現で表せるので、
4つの状態を持つ有限オートマトンになります。

質問のコードを修正するとすれば、

C

1#include <stdio.h> 2 3#define p 0 4#define q 1 5#define r 2 6#define d 3 7 8int main(void) 9{ 10 int s = p, c; 11 char str[30]; 12 scanf("%s", str); 13 for (int i = 0; c = str[i]; i++) { 14 if (s == p && c == 'a') s = q; 15 else if (s == p && c == 'b') s = d; 16 else if (s == q && c == 'a') s = q; 17 else if (s == q && c == 'b') s = r; 18 else if (s == r && c == 'a') s = d; 19 else if (s == r && c == 'b') s = r; 20 else if (s == d && c == 'a') s = d; 21 else if (s == d && c == 'b') s = d; 22 } 23 if (s == r) 24 puts("Yes"); 25 else 26 puts("No"); 27}

投稿2020/11/02 17:13

編集2020/11/03 14:50
kazuma-s

総合スコア8224

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

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

0

cが¥0になるまで続けるときどのように条件分式を書けばいいのでしょうか?
==にしても=にしてもエラーが出てしまいます。

投稿2020/11/02 16:03

yukihirotahu

総合スコア8

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

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

kazuma-s

2020/11/02 18:33

char c[30]; と宣言されているので、c の型は配列です。 これを c[i] という形ではなく、c で参照すると、c はポインタ型の値に変換され、その値は c[0] のアドレスです。c[0] のアドレスは固定されているので、その値が '\0' になることはありません。 配列 c の中の文字列を 1文字ずつ参照するのは、c[i] です。i を 1つずつ増やすことによって、 全部の文字を参照でき、c[i] == '\0' となったときがループの終了です。
guest

0

まず、

while( c!='\0' ){

これおかしいですね
cは配列です

} else if(( s==p ) && ( c='b' )){

cに代入になってますが、
cは配列です

投稿2020/11/02 11:41

編集2020/11/02 11:43
y_waiwai

総合スコア87774

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

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

yukihirotahu

2020/11/02 16:03

cが¥0になるまで続けるときどのように条件分式を書けばいいのでしょうか? ==にしても=にしてもエラーが出てしまいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問