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

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

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

CDNは、Webコンテンツをインターネット経由で配信するのに最適化されたネットワークを指します。Webサイトにある静的コンテンツをWebサイトが管理されているサーバーとは異なるサーバーにキャッシュし代わりに配信することで、負荷が分散し速度を向上する仕組みです。

C++

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

Q&A

解決済

1回答

1874閲覧

ungetc の使い道

doraemon1106

総合スコア18

CDN

CDNは、Webコンテンツをインターネット経由で配信するのに最適化されたネットワークを指します。Webサイトにある静的コンテンツをWebサイトが管理されているサーバーとは異なるサーバーにキャッシュし代わりに配信することで、負荷が分散し速度を向上する仕組みです。

C++

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

0グッド

0クリップ

投稿2019/05/05 04:49

main()

{

int c;

long

x, a, b;

init();

while ((c = getchar()) != EOF) {

if (isdigit(c)) {

ungetc(c, stdin);

scanf("%ld", &x);

push(x);

} else {

switch (c) {

case '+':

b = pop(); a = pop();

push(a + b);

break;

case '-':

b = pop(); a = pop();

push(a - b);

break;

case '*':

b = pop(); a = pop();

push(a * b);

break;

case '/':

b = pop(); a = pop();

push(a / b);

break;

case '\n':

if (! empty())

printf("答えは%ldです\n", pop());

init();

break;

case ' ':

case '\t':

/*

何もしないで読みとばす */

break;

default:

printf("不正な文字がありました。\n");

printf("入力しなおして下さい。\n");

while ((c = getchar()) != EOF && c != '\n')

;

break;

}

}

}

}

少し省いてますが、逆ポーランド記法を実現するためにスタックを用いています。

この序盤に出てくるungetc(c.stdin)の存在意義がわかりません。ストリームから読み込んだ文字を戻すという事がいまいち掴めないのです。その後のscanfで打ち直してるのともリンクしません。ご回答よろしくお願いします。

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

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

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

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

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

otn

2019/05/05 05:47

見にくいので、コードブロックで囲む、つまり、プログラムの前に ```C という行を置いて、プログラムの後に、 ``` という行を置いて、ちゃんとインデントが分かるようにしてプログラムを記述してください。
guest

回答1

0

ベストアンサー

例えば、123という入力があったとして、getchar1を読んで数字だと判断してscanfすると、読み込むのは23となり、1が欠けてしまいます。
そこで1をストリームに戻してやると、次のscanf123が読めます。
#コメントを読んでの追記
プログラムで端末から入力するというのがどういうことか理解できていないようなので、少し説明します。
(面倒くさいので、複数バイト文字のことは考えず、以下の説明では文字とバイトを同じような意味で使っています)

端末と、自分で書いたプログラムの間に、ライブラリで実現されているバッファという文字列領域があります。
バッファには、端末から文字が入力され、自分で書いたプログラムのgetcharscanfは、バッファにある文字を変数に代入します。
端末で文字を打って、Enterを押すと、文字が行単位でバッファに追加されます(改行コード付き)。
プログラムでgetcharすると先頭の1バイトをプログラムが得て、バッファからはその1バイトが消えます。
プログラムでscanfすると、フォーマット文字列に該当するバイト列が(必要なら変換されて)変数に入ります。その分のバイト列はバッファから消えます。

ここまで理解できたとして、動作を説明します。
まず最初に実行される入力関数は、c = getchar()のところです。これは、「バッファから1バイトよこせ」という命令ですが、バッファは最初は空です。空のバッファから読もうとした場合は、端末は1行入力状態になり、打った文字列はバッファに入ります。ここで、123Enterと打ったとします。この瞬間のバッファは"123\n"です。
で、getchar()は先頭の'1'を取ってcに代入します。この時点のバッファは"23\n"です。
isdigit(c)は真なので、ungetc(c,stdin)します。cをバッファに返すので、この時点でのバッファは"123\n"に戻ります。で、scanf("%ld",&x)が実行されますので、"%ld"によって文字列"123"long int型に変換されてxに入ります。この時点のバッファは"\n"ですので、次にgetchar()するとc'\n'になり、バッファは""つまり空になります。さらにgetchar()を行うと・・・・最初に戻る。

以下補足(蛇足?):
入力が端末じゃなくて、ファイルの場合は、バッファは行単位じゃなくて4096バイトとか8192バイトとかの領域になります。
また、端末属性を変更すると、行単位じゃなくてキー1つ単位での入力も可能です。

投稿2019/05/05 05:53

編集2019/05/05 11:16
otn

総合スコア84708

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

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

doraemon1106

2019/05/05 09:33

コードの書き方了解しました。コピペしたのでめちゃくちゃになってました。 ここでのscanfは入力ではなく読み取りになるということですか?getcharで入力してるのでなぜ二回入力してるのだろうということも思っていました
otn

2019/05/05 10:04

「入力」と「読み取り」は同じですが、あなたはどういう意味で使い分けていますか?
doraemon1106

2019/05/05 10:31

理解力乏しくてすみません。よく意味がわかってないようです。 getcharで入力した(仮に123)として、insightで1を読み、ungetcで1を返したというのはわかりました。 そこからもう一度scanfをするともう一度123をうつのか?とそこがいまいちわかってないです。 自分の思ってる読み取るはscanfがgetcharの文字を読み取るで入力はgetcharだと思ってます。
otn

2019/05/05 10:48

プログラムの入力という物が理解できていないようです。 端末からの入力という前提で、説明を追記します。
otn

2019/05/05 11:16

うあ、長くなっちゃった。
doraemon1106

2019/05/05 13:10

かなり理解しました。何も理解できてなかったです。助かりました!ありがとうございました????
otn

2019/05/05 13:23

ライブラリの実装はまた違ったりしますが、意味的には回答したとおりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問