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

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

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

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

Q&A

解決済

4回答

4105閲覧

C言語 コメントの数

marry0129

総合スコア51

C

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

0グッド

0クリップ

投稿2015/11/05 05:22

標準入力で、/~/のようなコメントの数を数えるプログラムです。
一行ごとの読み込みしかわからず、どうやって複数行にまたがるコメントを認識できるのかわかりません。また、/*/ も一つに数えてしまっているみたいです。
具体的にどこをどうしたらいいのか教えて下さい!

以下コードです。

#include<stdio.h>

#define BUFSIZE 1000

int comment(char buf[], int *flag){ // 関数を用意
int check = 0;
int i;

for (i = 0; '\0' != buf[i]; i++) { //受け取った文字が終端文字でなければループ if (0 == *flag) { //0を受け取る=前に*/があった or いままでフラグがたってない if ('/' == buf[i] && '*' == buf[i+1]){ // 受け取った配列に /* があればフラグを立てる flag=1 *flag = 1; } } else { if ('*' == buf[i] && '/' == buf[i+1]){ // */がきたらフラグを0に戻す *flag = 0; check = 1; //フラグが1,0と変化したらcheck=1 } } } return check;

}

int main(){
char buf[BUFSIZE]; //文字を入れていく配列
int line = 0; //コメントの行数を記録する変数
int flag = 0; //フラグ

while (NULL != fgets(buf, BUFSIZE, stdin)) { //標準入力された一行で読み込めるだけ文字を読み込む if (0 != comment(buf, &flag)) //comment関数にとぶ 配列とフラグを渡してcheckが1なら line++; } printf("%d/n", line); return 0;

}

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

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

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

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

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

coco_bauer

2015/11/05 06:19

「/*/ も一つに数えて」しまうのは、2文字が/*や*/に一致した場合にiを1余分に増加させていないからです。*flga=1;の列の次と、*flag=0;の列の次に、i++:の行を追加すると解決されます。
bob_heuer0925

2015/12/16 00:52

こちらの質問が他のユーザから「質問の範囲が広すぎる」という評価を受けています わからない点を明確にし、調査したこと・試したことと共に記入していただくと、回答が得られやすくなります。
guest

回答4

0

Chironianさんに賛成します.
状態の数が多くなるのでenumか何かで状態を定義しておいて,
分岐するコードを見やすくしておくと良いと思います.

ただ,もっと大雑把に調べたければ,行で読みこんでもいいと思います.
状態は,コメントアウトの中にいるか,外にいるかだけを使います.
(投稿者さんのコードに近くなります)
①外の状態
strstr(buf, "/");がNULL以外を返した→bufの位置をずらして状態②に移行
②中の状態
strstr(buf, "
/");がNULL以外を返した→コメントカウントを上げて状態①に移行
ただし,1行をバッファ内に必ず収められるという前提が必要です.
これができない場合,バッファの最後に「/」が来て,次に読み込んだバッファが「*」だった,
といった場合に正しく判定できないかもしれないからです.

以下,comment()関数の大雑把な設計です.
同じ行の中に複数のコメントアウトがあることも想定して,
checkは行の中に含まれるコメントアウトの数を返しています.
main()の方も修正しておいてください.

c

1int comment(char *buf, int *flag){ 2 int check = 0; 3 4 while (1) { 5 if (*flag == 0) { 6 /* コメントアウトの外にいる */ 7 if ((buf = strstr(buf, "/*") == NULL) { 8 /* この行にはコメントアウトなし */ 9 return check; 10 } 11 else { 12 /* この行にコメントアウトの開始がある */ 13 *flag = 1; 14 buf += 2; //「/*/」を誤カウントしないために必要 15 } 16 } 17 else { 18 /* コメントアウトの中にいる */ 19 if ((buf = strstr(buf, "*/") == NULL) { 20 /* この行ではコメントアウトは終了しない */ 21 return check; 22 } 23 else { 24 /* この行にコメントアウトの終了がある */ 25 check++; 26 buf += 2; 27 } 28 } 29 } 30 /* 本来この行には来ない */ 31 return 0; 32}

コードを見て頂ければわかりますが,冗長な部分がたくさんあります.
char com[][] = {"/", "/"};
とかを使えば,この関数は約半分にできます.

c

1const char com[][] = {"/*", "*/"}; 2int comment(char *buf, int *flag){ 3 int check = 0; 4 5 while (1) { 6 if ((buf = strstr(buf, com[*flag]) == NULL) { 7 return check; 8 } 9 else { 10 check += *flag; 11 *flag = (*flag) ? 0 : 1; /* フラグを反転 */ 12 buf += 2; //「/*/」を誤カウントしないために必要 13 } 14 } 15 return 0; 16}

投稿2015/11/05 06:25

編集2015/11/05 07:49
KenTerada

総合スコア751

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

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

0

C言語は原則として「行」の概念がないので、1行ずつ読んで処理するとかなり面倒です。
1文字ずつ処理してはだめでしょうか?
状態として、下記を用意すればできるだろうと思います。

①Idle
②①状態で'/'を検出
③②状態でを検出
④③状態で
を検出

そして、④の状態で'/'を検出したらコメントの数をインクリメントして①へ戻る感じですね。
なお、②状態で*以外を検出した時に①へ戻す等の処理も忘れないように。

以上だけですと、""や//の中に/* */があると正常にカウントできないですが、それは次の課題とした方がよいと思います。

投稿2015/11/05 05:30

Chironian

総合スコア23272

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

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

0

//の1行コメントには対応していません。

C

1#include <stdio.h> 2 3int main(){ 4 /* コメントカウント */ 5 int count = 0; 6 int c1, c2; 7 /* 注釈モードをオフに初期化 */ 8 int c_mode = 0; 9 /* 文字定数モードをオフに初期化 */ 10 int quote1 = 0; 11 /* 文字列リテラルモードをオフに初期化 */ 12 int quote2 = 0; 13 14 for ( c1 = getchar(); ( c2 = getchar()) != EOF; c1 = c2 ) { 15 if ( !c_mode ) { 16 /* 注釈モードがオフのとき */ 17 /* 文字定数又は文字列リテラルの中で文字 ¥ を検出 */ 18 if ( (quote1 || quote2) && c1 == '¥¥' ) { 19 c2 = getchar(); 20 continue; 21 } 22 /* 文字列リテラル以外のところで一重引用符を検出 */ 23 else if ( !quote2 && c1 == '¥'' ) 24 quote1 = !quote1; 25 /* 文字定数以外のところで二重引用符を検出 */ 26 else if ( !quote1 && c1 == '¥"' ) 27 quote2 = !quote2; 28 /* 文字定数及び文字列リテラル以外で / と * を検出 */ 29 else if ( (!quote1 && !quote2) && c1 == '/' && c2 == '*' ) { 30 c_mode = !c_mode; 31 c2 = getchar(); 32 count++; 33 continue; 34 } 35 } else { 36 /* 注釈の終端か? */ 37 if ( c1 == '*' && c2 == '/' ) { 38 c_mode = !c_mode; 39 c2 = getchar(); 40 } 41 } 42 } 43 return 0; 44} 45

投稿2015/11/05 10:30

編集2015/11/06 17:40
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

raccy

2015/11/10 10:16

一行コメントに対応していないって、いつの時代のC言語の話でしょうか? 16年も前のC99の時点で対応しているんですけど…。
退会済みユーザー

退会済みユーザー

2015/11/11 12:08

「標準入力で、/*~*/のようなコメントの数を数えるプログラムです。」 とのことでしたので、問題ないかと
guest

0

自己解決

/*/も数えず、複数行にまたがってカウントできました

投稿2015/11/05 06:21

marry0129

総合スコア51

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

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

mhashi

2015/11/06 02:23

どうやって実現できたのでしょうか。同じ問題が発生した人のために解決方法を記載していただけますでしょうか。(他の回答により解決したならそれをベストアンサーに選んでもらえると助かります)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問