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

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

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

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

5回答

3296閲覧

C言語 getchar関数 と Enter

makkasa

総合スコア11

C

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2020/03/09 13:59

現在「(),[],{}のつりあいがとれていないといったプログラムの基本的な構文エラーのチェックを行うプログラムを書け。引用符・2重引用符・コメントなどの処理も忘れないこと。」 という問題を解いています。
その上で、getchar関数から入力を行い 「ctrl + d」を入力することで出力結果を得たいのですが、getchar関数の入力中にエンターキーを押すと、先にエンターキーを入力する時点までの出力がされてしまいます。
EOF(ctrl + d)を認識する前に、エンターキーを押すことでwhile文内の処理が進むのはなぜでしょうか。
どなたかご教授いただけますと幸いです。

・実行したいこと

abc//abcを入力\n //'\n'はエンターキー
cde\n
(ctrl + d)

↓上記を入力し、下記の出力結果を得たい。

abc
cde


・発生する事象

abc//abcを入力\n //'\n'はエンターキー

↓最初のエンターを押した時点で結果が出力されてしまう。

abc


int main(void) { int c, counter1 = 1, counter2 = 1; int kakko1 = 0, kakko2 = 0, kakko3 = 0; int count = 0; int a[2]; while((c = getchar()) != EOF){ if(a[0] == '/' && c != '/'){ putchar('/'); a[0] = 0; } if(c == '('){ kakko1 += 1; }else if(c == ')'){ kakko1 -= 1; }else if(c == '['){ kakko2 += 1; }else if(c == ']'){ kakko2 -= 1; }else if(c == '{'){ kakko3 += 1; }else if(c == '}'){ kakko3 -= 1; } if(c == '\''){ counter1 *= -1; putchar(c); count = 0; }else if(c == '\"'){ counter2 *= -1; putchar(c); count = 0; }else if(c == '/'){ count += 1; a[count-1] = '/'; }else{ putchar(c); count = 0; } if(counter1 == 1 && counter2 == 1 && count == 2){ while(c != '\n'){ c = getchar(); } printf("\n"); a[0] = '\0'; } } if(kakko1 != 0 || kakko2 != 0 || kakko3 != 0){ printf("カッコの釣り合いが取れてない"); } return 0; }

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

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

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

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

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

guest

回答5

0

getchar()しながらputchar()しているので、途中で表示されるのは当然というか、出力してますよね。

最後にまとめて表示したいのなら、途中でputchar()せずに、charの配列に書き込んでいって、最後に表示すればいいかと思います。

投稿2020/03/09 14:23

otn

総合スコア85901

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

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

0

すでに回答しているのに、間違って新規の回答をしてしまいましたので、削除します。

投稿2020/03/10 11:12

編集2020/03/10 11:20
kazuma-s

総合スコア8224

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

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

0

テストしやすい形になっていないし、テストもしてませんが、
こんな感じで書いていっては如何でしょう?
// このコードでは { } の処理、コメントの処理はしていません。

parse.c

c

1#include<stdio.h> 2#include <string.h> 3 4// TODO: 5// * {} の組をチェックすること 6// * コメントを処理すること 7 8#define MAX_TOKEN_LEN (100) 9#define MAX_BLAKET_NEST (10) 10 11#define TYPE_BLAKET_10 (10) // ( 12#define TYPE_BLAKET_11 (11) // ) 13#define TYPE_BLAKET_20 (20) // [ 14#define TYPE_BLAKET_21 (21) // ] 15#define TYPE_CHAR (100) // 一般の文字 16#define TYPE_S_QUOTED_STR (200) 17#define TYPE_D_QUOTED_STR (201) 18 19#define ERR_GENERAL (-10) 20#define ERR_BLAKET_NEST_OVER (-11) 21#define ERR_BLAKET_NEST_UNDER (-12) 22#define ERR_BAD_BLAKET_PAIR (-13) 23#define ERR_BAD_S_QUOTED_PAIR (-14) 24#define ERR_BAD_D_QUOTED_PAIR (-15) 25#define ERR_ESQUAPE (-16) 26#define ERR_ESCAPE (-17) 27#define ERR_TOO_LONG_STRING (-18) 28 29char blakets[MAX_BLAKET_NEST]; 30int blaket_nest = 0; 31 32void show_error(int err); 33int push_blaket(int blaket_type); 34int pop_blaket(int blaket_type); 35int get_token(char * token); 36int get_quoted_str(char * token, int quot); 37 38void show_error(int err) { 39 if (err == 0) { ; } 40 else if (err == ERR_GENERAL) {printf("ERR_GENERAL\n");} 41 else if (err == ERR_BLAKET_NEST_OVER) {printf("ERR_BLAKET_NEST_OVER\n");} 42 else if (err == ERR_BLAKET_NEST_UNDER) {printf("ERR_BLAKET_NEST_UNDER\n");} 43 else if (err == ERR_BAD_BLAKET_PAIR) {printf("ERR_BAD_BLAKET_PAIR\n");} 44 else if (err == ERR_BAD_S_QUOTED_PAIR) {printf("ERR_BAD_S_QUOTED_PAIR\n");} 45 else if (err == ERR_BAD_D_QUOTED_PAIR) {printf("ERR_BAD_D_QUOTED_PAIR\n");} 46 else if (err == ERR_ESQUAPE) {printf("ERR_ESQUAPE\n");} 47 else if (err == ERR_ESCAPE) {printf("ERR_ESCAPE\n");} 48 else if (err == ERR_TOO_LONG_STRING) {printf("ERR_TOO_LONG_STRING\n");} 49} 50 51int push_blaket(int blaket_type) { 52 if (blaket_nest + 1 >= MAX_BLAKET_NEST ) { 53 return ERR_BLAKET_NEST_OVER; 54 } 55 56 blakets[blaket_nest] = blaket_type; 57 blaket_nest++; 58 return 0; 59} 60 61int pop_blaket(int blaket_type) { 62 if (blaket_nest == 0) { 63 return ERR_BLAKET_NEST_OVER; 64 } 65 blaket_nest--; 66 if (blakets[blaket_nest] != blaket_type - 1) { 67 return ERR_BAD_BLAKET_PAIR; 68 } 69 return 0; 70} 71 72int get_token(char * token) { 73 int c; 74 token[0] = '\0'; 75 token[1] = '\0'; 76 c = getchar(); 77 if (c == EOF) { 78 return EOF; 79 } else if (c == '(') { 80 token[0] = c; 81 return TYPE_BLAKET_10; 82 } else if (c == ')') { 83 token[0] = c; 84 return TYPE_BLAKET_11; 85 } else if (c == '[') { 86 token[0] = c; 87 return TYPE_BLAKET_20; 88 } else if (c == ']') { 89 token[0] = c; 90 return TYPE_BLAKET_21; 91 } else if (c == '\"') { 92 return get_quoted_str(token, c); 93 } else if (c == '\'') { 94 return get_quoted_str(token, c); 95 } 96 token[0] = c; 97 return TYPE_CHAR; 98} 99 100int get_quoted_str(char * token, int quot) { 101 int c; 102 int cp = 0; 103 while (1) { 104 c = getchar(); 105 if (c == EOF) { 106 if (quot == '"') { 107 return ERR_BAD_D_QUOTED_PAIR; 108 } 109 return ERR_BAD_S_QUOTED_PAIR; 110 } 111 if (c == quot) { 112 break; 113 } 114 115 if (quot == '\') { 116 c = getchar(); 117 if (c == EOF) { 118 if (quot == '"') { 119 return ERR_BAD_D_QUOTED_PAIR; 120 } 121 return ERR_BAD_S_QUOTED_PAIR; 122 } 123 } 124 125 if (cp + 1 >= MAX_TOKEN_LEN) { 126 return ERR_TOO_LONG_STRING; 127 } 128 token[cp] = c; 129 cp++; 130 } 131 132 token[cp] = '\0'; 133 if (quot == '\') { 134 return TYPE_S_QUOTED_STR; 135 } 136 return TYPE_S_QUOTED_STR; 137} 138 139int parse(void) { 140 int type; 141 char token[MAX_TOKEN_LEN]; 142 int err = 0; 143 144 while((type = get_token(token)) != EOF) { 145 if (type < 0) { 146 err = type; 147 } else if (type == TYPE_BLAKET_10) { 148 err = push_blaket(type); 149 } else if (type == TYPE_BLAKET_11) { 150 err = pop_blaket(type); 151 } else if (type == TYPE_BLAKET_20) { 152 err = push_blaket(type); 153 } else if (type == TYPE_BLAKET_21) { 154 err = pop_blaket(type); 155 } else if (type == TYPE_S_QUOTED_STR) { 156 ; 157 } else if (type == TYPE_D_QUOTED_STR) { 158 ; 159 } else { 160 ; 161 } 162 if (err) { 163 break; 164 } 165 } 166 return err; 167} 168 169int main(void) { 170 int ret = parse(); 171 if (ret) { 172 show_error(ret); 173 } else { 174 printf("#--- OK\n"); 175 } 176 return 0; 177}

実行例
イメージ説明

投稿2020/03/10 08:42

katoy

総合スコア22324

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

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

0

問題の意味を取り違えています。
出力は「構文エラーあり」または「構文エラーなし」のどちらかだけでよいでしょう。
したがって、putchar(c); や printf("\n"); は不要です。

さらに、括弧の釣り合いを括弧の個数だけでは判断できません。
例えば、abc)def(ghi や ab(cd[ef)gh]ij はエラーにしないといけないでしょう。

また、コメントには // から \n まで以外に、/* から */ までというのもあります。

追記
コードを追記しようとしたら、間違って新規の回答にしてしまい、それが削除できません。
改めてここに追記します。

C

1#include <stdio.h> // getchar, printf, puts 2#include <stdlib.h> // exit 3#include <string.h> // strchr 4 5void error(const char *s) { printf("Error: %s\n", s); exit(1); } 6 7void error2(int d) 8{ 9 error(d == '"' ? "string literal not closed" :"character constant not closed"); 10} 11 12int parse(int e) 13{ 14 static char pa[] = "([{", ren[] = ")]}"; 15 int c; 16 char *p; 17 18 while ((c = getchar()) != EOF) { 19 if (c == '/') { 20 if ((c = getchar()) == EOF) return c; 21 if (c == '/') // skip "// comment" 22 while ((c = getchar()) != EOF && c != '\n') ; 23 else if (c == '*') // skip "/* */ comment" 24 do { 25 while ((c = getchar()) != EOF && c != '*') ; 26 if (c == EOF || (c = getchar()) == EOF) 27 error("comment not closed"); 28 } while (c != '/'); 29 } 30 else if (c == '"' || c == '\'') { 31 int d = c, k = 0; // skip string literal or charcter constant 32 do { 33 if ((c = getchar()) == EOF || c == '\n') error2(d); 34 if (c == '\') { 35 if ((c = getchar()) == EOF) error2(d); 36 if (c == d) c = 0; 37 } 38 k++; 39 } while (c != d); 40 if (d == '\'' && (k < 2 || k > 5)) error("bad character constant"); 41 } 42 else if ((p = strchr(pa, c))) { // parse parentheses 43 int r = ren[p - pa]; 44 if (parse(r) != r) error("paren not closed"); 45 } 46 else if (strchr(ren, c)) break; 47 } 48 return c; 49} 50 51int main(void) 52{ 53 if (parse(EOF) != EOF) error("unexpected closing paren"); 54 puts("OK"); 55}

バグのご指摘お待ちしています。

追記2
最後のところにバグがありました。次のように訂正します。

C

1 else if ((p = strchr(pa, c))) { // parse parentheses 2 int r = ren[p - pa]; 3 if (parse(r) != r) error("paren not closed"); 4 } 5 else if (strchr(ren, c)) { 6 if (c == e) break; 7 error("unexpected closing paren"); 8 } 9 } 10 return c; 11} 12 13int main(void) 14{ 15 parse(EOF); 16 puts("OK"); 17}

投稿2020/03/10 03:16

編集2020/03/10 15:52
kazuma-s

総合スコア8224

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

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

0

ベストアンサー

getchar関数は、入力文字をそのまま画面に表示し、EnterやEOFを入力した時点で、入力文字を1文字づつ返す動作となります
また、Enter文字(\r)も関数から帰ってきます
そこらへんも踏まえて、あなたのコードがどう動くのか、を追いかけてみてください。

EclipseやVisualStudioなどの環境を整えて、ステップ実行などさせてどう動くのか、を確認してみてはどうでしょう

投稿2020/03/09 23:48

y_waiwai

総合スコア88042

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問