コードには、次のような多くの問題があります。
- 関数をチェックしない
scanf()
とデータが見つかります
- の誤った宣言
main()
- 未使用のポインタをに渡す
get_income()
- 機能のチェックからステータスを返さない
- 入力されたデータについて報告しない
- で変数を宣言しない
main()
- 目的と一致しない関数名
- 浮動小数点数に格納するための整数の読み取り
- 等
sscanf()
「データを読み取らせる」よりも、「行を読み取って解析する」方がよいでしょうscanf()
。エラー報告の処理が簡単です。
これらの観察結果は次のようになります。
#include <stdio.h>
int get_tuition_and_supplies(double *ptuition, double *psupplies);
int get_double(double *pvalue);
int main(void)
{
double tuition, supplies;
if (get_tuition_and_supplies(&tuition, &supplies) == 0)
printf("Tuition: %.2f; supplies %.2f\n", tuition, supplies);
return(0);
}
int get_tuition_and_supplies(double *ptuition, double *psupplies)
{
int rc = -1; // Failure
printf("Enter tuition: ");
if (get_double(ptuition) == 0)
{
printf("Enter supplies: ");
if (get_double(psupplies) == 0)
rc = 0;
}
return rc;
}
int get_double(double *pvalue)
{
char buffer[4096];
int rc = -1;
if (fgets(buffer, sizeof(buffer), stdin) == 0)
fprintf(stderr, "EOF (or error) reading data\n");
else if (sscanf(buffer, "%lf", pvalue) != 1)
fprintf(stderr, "Did not find a number in input (%.32s)\n", buffer);
/* Could check for no extracharacters (blanks allowed) up to newline */
else if (*pvalue < 0.0)
fprintf(stderr, "Value (%g) may not be negative\n", *pvalue);
else
rc = 0;
return rc;
}
「成功が証明されるまでリターンコード()を失敗に設定する」というイディオムは、rc
検証を処理するための効果的な手法の1つです。get_double()
関数にプロンプトを含めて、そのシグネチャが次のようになるようにする方がよい場合があります。
int get_double(const char *prompt, double *pvalue);
これにより、コードを次のように簡略化できますget_tuition_and_supplies()
。
int rc = -1; // Failure
if (get_double("Enter tuition: ", ptuition) == 0 &&
get_double("Enter supplies: ", psupplies) == 0)
rc = 0;
return rc;
これは、2つだけではなく、複数の値を処理するために適切に拡張されます。