関数型言語としてのC

本日はコードを載せてみるテストも兼ねて投稿.

C言語の関数は実行されると戻り値を返す.知っている人にとって今更な内容である.
大学時代でいかに勉強をしていないかを露呈することになるが気にせず記そう.

研修で出題された問の発展的な処理として,Cに詳しい同期に指導していただいた.
まず,欲しい実行例はコチラ

四則演算を行います。'q'で終了
1+1
[ 2.00 ]
+3
[ 5.00 ]
*5
[ 25.00 ]
−7
[ 18.00 ]
/6
[ 3.00 ]


ここで,問題となるのは
最初に"数""演算子""数"というフォーマットで入力されるが,
以降は"演算子""数"と入力されて,直前の結果に対して操作を行う.
今回,fgetsとsscanfを使うとして,上記の処理を1回のフローで
実現することは可能であろうか? (模範回答では別フロー)

その鍵は関数の戻り値だ.
  sscanf(文字列, "%d%c%d", &数1, &演算子, &数2);
これに,"数""演算子""数"が入力されて,上記のフォーマットで
代入しようとするとき,このsscanfの戻り値は3だ.
しかし,"演算子""数"が入力されたなら,戻り値は2だ.
そんなときは,分岐処理を行い,
  sscanf(文字列, "%c%d", &演算子, &数2);
とすればよい.(ただしscanfではできない).

書いてみたコードはコチラ

#include
int main()
{
double ans = 0;
double n1 = 0;
double n2 = 0;
char s[100];
char enzan = 'a';
int chk = 0;

printf("四則演算を行います。'q'で終了\n");

do{
fgets(s, sizeof(s), stdin);
chk = sscanf(s, "%lf%c%lf", &n1, &enzan, &n2);
if(chk == 3) {
ans = n1;
}else {
sscanf(s, "%c%lf", &enzan, &n2);
}

switch(enzan) {
case '+':
ans += n2;
break;
case '-':
ans -= n2;
break;
case '*':
ans *= n2;
break;
case '/':
ans /= n2;
break;
default:
if(enzan != 'q')
printf("入力が不正です。\n");
break;
}

printf("[ %.2lf ]\n", ans);
}while(enzan != 'q');

return 0;
}

いかがだっただろうか.工夫次第でかなりシンプルになると実感した.