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

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

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

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

Q&A

解決済

3回答

912閲覧

コメントの数の出力について

YuhiKUROIWA

総合スコア9

C

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

0グッド

1クリップ

投稿2020/05/23 13:10

編集2020/05/24 01:17

入力の中で、C言語での注釈として扱われる部分の個数を出力するプログラムを作れ。

C言語では、入力を前から見て行って、/* が現れそれ以後に / が現れているとき、その最初の / に始まりそれ以後で最初に現れた */ で終わる部分を注釈とよび、入力から取り除く。この操作は、残りの入力がある限り繰り返して行われる。

入力は、1行かもしれず複数行かもしれない。 (キーボードから入力するときは、最後に C-d を入力する。)

出力は、個数を1行に書き出す。

が問題です。
コードは何となくで書いてみました。
開幕見当がつかずめちゃくちゃだと思いますが丁寧に教えていただけると助かります。

コンパイルは通りましたが出力を
This is /* a comment,
which /* continues to
here */ /// * *./**/
/***a/ /*a * */
にすると、何も出ずに終わります。何が原因でしょうか。

#include <stdio.h> #define N 1000 int main(void){ int a[N]; int i; int b=0; int c=0; scanf("%s", a[i]); for(i=0;i<N;i++){ if(a[i]=='/' && a[i+1]=='*'){ b++; }else{ if(a[i]=='*' && a[i+1]=='/'){ c++; } } } if(b<c){ printf("%d", b); }else{ printf("%d", c); } return 0; }

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

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

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

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

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

y_waiwai

2020/05/23 13:17

で、しつもんはなんでしょうか
elsewhere

2020/05/23 13:57

「コンパイルしてみると◯◯というエラーが出る。その原因は××だと思うから、◇◇と対応してみたが同じエラーが出る。これ以上の対応が思いつかないが、見落としているポイントが有れば教えて欲しい」 せめてこれくらいには具体的に質問しないと 「丸投げ」 と誤解される可能性が高いと思います。 そこで逆に質問ですが、このコードはコンパイルしてみましたか? その結果はどうでしたか?
otn

2020/05/23 15:59

まずテストしてみましょう。全然駄目なのが分かると思います。
YuhiKUROIWA

2020/05/24 01:19

質問を追加しました。 もう一度検討していただけると嬉しいです。
episteme

2020/05/24 01:24

int a[N] に文字列をセットするみたいだけど、だったらなぜに int なの? char のマチガイ? # あてずっぽでコード書いてるでしょ。
dodox86

2020/05/24 02:00

> コードは何となくで書いてみました。開幕見当がつかずめちゃくちゃだと思いますが 何となく書いた、と自認するコードを第三者にフォローしてもらおうとするのは、さすがにあんまりなのではないでしょうか。
guest

回答3

0

状態を変数で持たず、制御の流れだけで解決してみました。

C

1#include <stdio.h> 2 3int comment(void) 4{ 5 int c; 6 while ((c = getchar()) != EOF) 7 while (c == '*') 8 if ((c = getchar()) == '/') return 1; 9 return 0; 10} 11 12int main(void) 13{ 14 int c, count = 0; 15 while ((c = getchar()) != EOF) 16 while (c == '/') 17 if ((c = getchar()) == '*') count += comment(); 18 printf("%d\n", count); 19}

別解
コメントの開始と終了が 2文字なので面倒なんですね。
だったら、2文字同時に比較すればよいでしょう。

C

1#include <stdio.h> 2 3int main(void) 4{ 5 int b, c = 0, count = 0; 6 while (b = c, (c = getchar()) != EOF) 7 if (b == '/' && c == '*') { 8 c = 0; 9 while (b = c, (c = getchar()) != EOF) 10 if (b == '*' && c == '/') { count++; c = 0; break; } 11 } 12 printf("%d\n", count); 13}

追記
/*/ をコメントの開始と終了と解釈し、
/ をコメントの終了と開始と解釈するバグがあったので、修正しました。

投稿2020/05/24 14:22

編集2020/05/24 15:53
kazuma-s

総合スコア8224

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

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

YuhiKUROIWA

2020/05/24 14:26

ありがとうございます。 自分でも試してみます。
guest

0

ベストアンサー

状態遷移を実装してみた。

C

1// このコード自身を食わすと "6 comments" が得られる。 2#include<stdio.h> 3 4typedef enum { 5 OUT, /* コメントの外 */ 6 SLASH, /* コメントはじめの'/' */ 7 IN, /* コメントの中 */ 8 STAR, /* コメントおわりの'*' */ 9} state_t; 10 11/* コメントを 12 勘定する */ 13 14int main(void) { 15 int count = 0; 16 17 state_t state = OUT; 18 int ch; 19 while ( (ch = getchar()) != EOF ) { 20 switch ( state ) { 21 case OUT: 22 if ( ch == '/' ) state = SLASH; 23 break; 24 case SLASH: 25 if ( ch == '*' ) state = IN; 26 else if ( ch != '/' ) state = OUT; 27 break; 28 case IN: 29 if ( ch == '*' ) state = STAR; 30 break; 31 case STAR: 32 if ( ch == '/' ) { state = OUT; ++count; } 33 else if ( ch != '*' ) state = IN; 34 break; 35 } 36 } 37 /*** 結果の出力 ***/ 38 printf("%d comments\n", count); 39 return 0; 40}

投稿2020/05/24 13:19

episteme

総合スコア16614

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

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

YuhiKUROIWA

2020/05/24 13:52

詳しい説明ありがとうございます。 よくわかりました。
episteme

2020/05/24 13:55 編集

よくわかった? ホント? このコードがコメントを抽出するカラクリを説明できる?
YuhiKUROIWA

2020/05/24 14:23

enumで文字列を宣言? コメントが入力されて一文字ずつループさせていくイメージじゃないでしょうか? //が続くといけないからcase SLASHでelseを使ってうまく回避してると考えてます。 解釈合っていますか?
episteme

2020/05/24 20:48

> enumで文字列を宣言? わかってなかったね。
YuhiKUROIWA

2020/05/25 02:02

違いましたか、、、 説明していただけると嬉しいです
episteme

2020/05/25 02:11

ではまず「状態遷移」を学んでください。
YuhiKUROIWA

2020/05/25 02:28

条件に対して特定の意味を持たせるイメージであってますか?
episteme

2020/05/25 02:31

「条件に対して特定の意味を持たせる」とはどーゆーことですか?
YuhiKUROIWA

2020/05/25 02:36

例えばoutはコメントの外 みたいな感じで意味を持たせるのかと、、
episteme

2020/05/25 02:38

はい、今(一文字読みこんだ時点で)どんな状態にあるかを enum で表現しています。
YuhiKUROIWA

2020/05/25 02:39

なるほど、詳しい説明ありがとうございます。
episteme

2020/05/25 03:21

で、各状態ごとに、「この文字を読んだら次の状態はなにか」を判断してます。 んでもって コメントの中から外に遷移するタイミングでコメント個数を+1する、と。
YuhiKUROIWA

2020/05/25 05:31

丁寧にありがとうございました。
guest

0

詳しくは見てないですが、、、

以下のループ内の処理

C

1 if(a[i]=='/' && a[i+1]=='*'){ 2 b++; 3 }else{ 4 if(a[i]=='*' && a[i+1]=='/'){ 5 c++; 6 } 7 }

ここで、 /*/ が来た場合、どうなるでしょうか?
まず、/* が検出されますが、次のループ(i+1)で、*/が検出されますが、それは期待する動作ですか? (* が重複する。)
*/*の場合も同様に、 */ の検出直後に /*が検出されます。

おっと、その前に、

scanf("%s", a[i]);

文字列を読み込もうしていると思いますが、 a は、整数(int)の配列で、さらに、iは初期化されていません。
また、 for(i=0;i<N;i++){ も読み込んだ文字列と無関係に、配列サイズでループ... 結構、問題ありですね。

投稿2020/05/24 01:32

pepperleaf

総合スコア6383

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問