2017-12-25 14 views
0

測定温度を記録するプログラム、新しい測定値を入力できる 、または以前の測定値から計算した統計値を表示する必要があります。統計情報を印刷する場合、記録された最低温度と最高温度を見つけて表示し、平均温度を計算する必要があります。構造の測定と最小温度、最大温度、平均温度の検索

#include <stdio.h> 

int least_in_array(int array[], int n) 
{ 
    int i, least=array[0]; 
    for(i=0; i<n; i++) 
    { 
     if(array[i]<least) 
     { 
      least=array[i]; 
     } 
    } 
    return least; 
} 

int largest_in_array (int array[], int n) 
{ 
    int i, largest=array[0]; 
    for(i=0; i<n; i++) 
    { 
     if(array[i]>largest) 
     { 
      largest=array[i]; 
     } 
    } 
    return largest; 
} 

float average_array(int array[], int n) 
{ 
    int amount=0, i; 

    for(i=0; i<n; i++) 
    { 
     amount+=array[i]; 
    } 
    return (1.0*amount)/n; 
} 


int main() { 

    int choose; 

    struct Data1 { 
     int dayInMonth; 
     int month; 
     float temperature; 
    } da; 

    printf("New measurement(1) or statistic(2)?\n"); 
    scanf("%d", &choose); 

    if(choose==1) { 

     printf("Enter the day in month : "); 
     scanf("%d", &da.dayInMonth); 
     printf("Enter month : "); 
     scanf("%d", &da.month); 
     printf("Enter temperature (*C) : "); 
     scanf("%f", &da.temperature); 

     printf("Data saved!"); 
     printf("-----------\n"); 

     return 0; 
    } 

    if(choose==2) { 

     //printf("Least temperatures in quarter: %d", least_in_array(dayInMonth)); 

     return 0; 
    } 

    else { 

     printf("----------------\n"); 
     printf("Wrong choose!\n"); 

    } 

    return 0; 
} 

ケース2では、エラーが発生した行をコメントしました。誰も私にこの問題を解決する助言を与えることができますか?

| 71 |エラー: 'dayInMonth' 宣言されていない(最初にこの関数で使用)

| 71 |エラー:機能するには少なすぎる引数のleast_in_array "

+1

具体的にする。エラーは何ですか? 'least_in_array'の署名を見て、どのように呼び出すのかを見てください。 – Galen

+0

宣言されていない、私は問題がどこでも関数の構造体に参加していることを知っていますが、idk、私は初心者です、私はカウントするためにint nを使用する必要があるので任意の関数で2つを要求します – jovkm

+0

完全なエラーメッセージ。また、 'least_in_array'に関する私の前のコメントを見てください。 – Galen

答えて

3

それはクリスマスイブですので、手伝っすることができます仲間...明らかに困っている人。 arrayleast_in_arrayに、largest_in_arrayaverage_arrayに渡すことになっているコードの場合、配列はありません!それは、 "Go!"という言葉から8ボールの後ろにいくらかあなたを置きます。

stuctを使用してdayInMonth,monthtemperatureをキャプチャして調整すると考えられます。 (ただし、Cスタイルでは、一般的には小文字を使用して変数名がcamelCaseになります)。また、struct Data1main()の範囲内に定義すると、そのポイントより上の関数は、struct Data1が何であるかを知ることができません。したがって、構造体の定義をファイルの先頭に移動する必要があります。ちょうどあなたのData1最上部に移動させ、(または前方宣言を提供し、私たちは、後のためにそれを保存します)今のところ(私は、それぞれがstuctで使用接頭辞に持つ軽減するためにtypedefを使用してData1data名前を変更:

#define NDAYS 365 

typedef struct { 
    int day, 
     month; 
    double temperature; 
} data; 

NDAYS定数定義され。あなたは配列が必要になるだろう、と動的に割り当ておよび再割り当てアプローチ以来数について、最大、ちょうど定数を定義してみましょう、ここにあなたのニーズをはるかに超えているようですされているので私たちは私が持っている要素の私たちの配列。

さらに進んで前に、私たちの配列について考えてみましょう。関連する日付と温度の測定値を保持するためにstructを使用する場合は、配列を必要とします。 structの配列。また定数がNDAYSの場合、配列内に最大で365要素が宣言されます。それではどうしたの?私たちは、stuctがdataにtypedeffed持っているので、我々はdataの配列をしたい場合、我々は必要です:

data da[NDAYS] = {{0, 0, 0.0}}; 

注:各フィールドを初期化し、古い初期化形式を使用すると、C89を使用することができるかどうか、それは不明であるとしましたコンパイラ。 C99以降の名前付きイニシャライザが追加されました。 {{.day = 0}}と初期化されていない要素は、暗黙的にゼロに初期化されます。

ここでは、dataという配列があり、測定値を取得できます。もちろん、あなたが書き込むインデックスを追跡する責任があります。たびに増加簡単なカウンタは、入力されたで成功した測定が

はどのように我々はleast_in_arraylargest_in_arraydataの配列とaverage_array作品作ります(ndxが以下で使用される)あなたが必要なすべてのですか?思い出して、構造体の定義をソースファイルの先頭に移動したので、それぞれの関数はdataが何であるかを知るようになりました。パラメータとして配列dataを渡すだけです。

float least_in_array (data *array, int n) 
{ 
    int i; 
    float least = INT_MAX; /* sufficiently high temp */ 

    for (i = 0; i < n; i++) 
     if (array[i].temperature < least) 
      least = array[i].temperature; 

    return least; 
} 

音符least_in_arrayの量のそれぞれ、largest_in_arrayaverage_arraytemperature値を参照し、したがって、タイプfloatを返す必要がある。)

一緒largest_in_arrayを置くの残りとaverage_array以下同じパターン。

残りの問題の要点は、ユーザーの入力を処理すること、およびユーザー入力を受け取ることに関連する落とし穴(scanf)です。それは行うことができますが、あなたは常にリターンを検証し、EOFのためのテストによって入力のユーザキャンセルのためのテストはCtrl + dを(またはwindoze上はCtrl + zをを押下する(結果)しなければなりません)。

あなたは期待される変換の数が実際に行われなかった、またはあなたがエラーを処理しなければならない、そして最も重要なのは、あなたが入力バッファ(例えばstdin)に残された文字のアカウントがなければならないことを検証する必要があり、そうでない場合、無効なエントリが作成されていて、それをstdinから削除しないと、永遠にループします。またはの入力と一致する場合、scanfでエラーが発生します。どこですか?(oh、in stdin

空のstdinにいくつかのヘルパ関数を宣言し、ユーザからの整数や浮動小数点を比較的安全に取得する通常の処理を行うと、これを簡単に行うことができます。たとえば、stdinを空白にするには、'\n'またはEOFになるまで残りの文字をすべて読み込むだけです。

/** simple function to empty all characters that remain 
* in stdin. Needed when using scanf for user input. 
*/ 
void empty_stdin() 
{ 
    int c = getchar(); 

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

EOFは、ユーザーによって生成されたかどうかをチェックし、成功した変換の数(何scanfリターン)をチェックし、あなたは、単にリターンを検証し、intまたはfloatをユーザーに尋ね、そして最終的に場合にエラーを処理するには無効な入力が与えられ、必要に応じてempty_stdinが入力されました。通常、ユーザーが有効な入力を提供するか、またはキャンセルするまでループします。 (無効な入力はあなたには良いことではありません)。

たとえば、整数入力を取得することは、次のように処理できます。 (注意:私はあなたのコードの本体に取り、各入力のためのコードブロックを繰り返すことから保つための機能でそれを置く...フロートのための

/** abbreviated function to read integer value from user. 
* returns value on success, exits if user cancels. 
* empties stdin after call to scanf. 
*/ 
int getint() 
{ 
    int n = 0; 

    for (;;) {    /* loop until valid input or EOF */ 
     int rtn = 0;  /* variable to capture return of scanf */ 
     rtn = scanf ("%d", &n); 
     if (rtn == 1) {  /* we got an integer */ 
      empty_stdin(); 
      break; 
     } 
     else if (rtn == EOF) { /* if user cancels, exit */ 
      fprintf (stderr, "user canceled input.\n"); 
      exit (EXIT_FAILURE); 
     } 
     if (rtn == 0)  /* handle error */ 
      fprintf (stderr, "getint() error: invalid integer input.\n"); 

     empty_stdin();  /* empty all chars remaining in stdin */ 
    } 

    return n; 
} 

(服用入力が同じように動作します) 。

最後に、あなたは一般的にちょうど原因23-bit仮数と浮動小数点数を表現するための精度と制限の損失に、代わりにdoubleを使用して、ほとんどの場合、floatを使用しないようにしたいです。ただし、ここでは温度を使用しており、floatで十分です。

このようにまとめると、次のようなことができます。注、私はあなたがそれらを持っていたとしてmain()前に、あなたの機能を残し、そしてmain()定義ヘルパー関数を追加しましたが、main()宣言を提供してきたので、彼らはmain()に見える:

#include <stdio.h> 
#include <stdlib.h> 
#include <limits.h> 

#define NDAYS 365 

typedef struct { 
    int day, 
     month; 
    double temperature; 
} data; 

float least_in_array (data *array, int n) 
{ 
    int i; 
    float least = INT_MAX; /* sufficiently high temp */ 

    for (i = 0; i < n; i++) 
     if (array[i].temperature < least) 
      least = array[i].temperature; 

    return least; 
} 

float largest_in_array (data *array, int n) 
{ 
    int i; 
    float largest = INT_MIN; /* sufficiently low temp */ 

    for (i = 0; i < n; i++) 
     if (array[i].temperature > largest) 
      largest = array[i].temperature; 

    return largest; 
} 

float average_array (data *array, int n) 
{ 
    int i; 
    float sum = 0.0; 

    for (i = 0; i < n; i++) 
     sum += array[i].temperature; 

    return sum/(float)n; 
} 

void empty_stdin(); 
int getint(); 
float getfloat(); 

int main (void) { 

    int ndx = 0; 
    float max = 0.0, min = 0.0, avg = 0.0; 
    data da[NDAYS] = {{0, 0, 0.0}}; 

    for (;;) { 

     int choose = 0; 

     printf ("\n (1) New measurement\n" 
       " (2) Statistics\n" 
       " (3) Exit\n\n" 
       " choice: "); 
     choose = getint(); 
     putchar ('\n'); 

     switch (choose) { 
      case 1: if (ndx == NDAYS) { 
         fprintf (stderr, "error: array full.\n"); 
         break; 
        } 
        printf (" Enter day in month : "); 
        da[ndx].day = getint(); 
        printf (" Enter month  : "); 
        da[ndx].month = getint(); 
        printf (" Enter temperature : "); 
        da[ndx].temperature = getfloat(); 
        printf (" da[%3d] saved\n" 
          " ----------------------------\n", ndx++); 
        break; 
      case 2: if (ndx == 0) { 
         fprintf (stderr, "error: no measurements taken.\n"); 
         break; 
        } 
        min = least_in_array (da, ndx); 
        max = largest_in_array (da, ndx); 
        avg = average_array (da, ndx); 
        printf (" minimum temp : %.2f\n" 
          " maximum temp : %.2f\n" 
          " average temp : %.2f\n" 
          " ----------------------------\n", 
          min, max, avg); 
        break; 
      case 3: 
        goto done; 
        break; 
      default: 
        fprintf (stderr, "error: invalid choice.\n"); 
        empty_stdin(); 
        break; 
     } 
    } 
    done:; 

    return 0; 
} 

/** simple function to empty all characters that remain 
* in stdin. Needed when using scanf for user input. 
*/ 
void empty_stdin() 
{ 
    int c = getchar(); 

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

/** abbreviated function to read integer value from user. 
* returns value on success, exits if user cancels. 
* empties stdin after call to scanf. 
*/ 
int getint() 
{ 
    int n = 0; 

    for (;;) {    /* loop until valid input or EOF */ 
     int rtn = 0;  /* variable to capture return of scanf */ 
     rtn = scanf ("%d", &n); 
     if (rtn == 1) {  /* we got an integer */ 
      empty_stdin(); 
      break; 
     } 
     else if (rtn == EOF) { /* if user cancels, exit */ 
      fprintf (stderr, "user canceled input.\n"); 
      exit (EXIT_FAILURE); 
     } 
     if (rtn == 0)  /* handle error */ 
      fprintf (stderr, "getint() error: invalid integer input.\n"); 

     empty_stdin();  /* empty all chars remaining in stdin */ 
    } 

    return n; 
} 

/** abbreviated function to read float value from user. 
* returns value on success, exits if user cancels. 
* empties stdin after call to scanf. 
*/ 
float getfloat() 
{ 
    float v = 0.0; 

    for (;;) {    /* loop until valid input or EOF */ 
     int rtn = 0;  /* variable to capture return of scanf */ 
     rtn = scanf ("%f", &v); 
     if (rtn == 1) {  /* we got an float */ 
      empty_stdin(); 
      break; 
     } 
     else if (rtn == EOF) { /* if user cancels, exit */ 
      fprintf (stderr, "user canceled input.\n"); 
      exit (EXIT_FAILURE); 
     } 
     if (rtn == 0)  /* handle error */ 
      fprintf (stderr, "getint() error: invalid float input.\n"); 

     empty_stdin();  /* empty all chars remaining in stdin */ 
    } 

    return v; 
} 

注:コードのテイク測定部分で配列境界が365以下に制限されていること、および統計が提供される前に少なくとも1つの測定値が存在することを確認する方法。プロセスの各ステップを常に検証する必要があります。コーナーケースを探し、何が入力に間違っているのか(猫がキーボードを踏んだ場合はどうなるか)を考え、検証とチェックを行い、それぞれのケースを処理します。上記の検証はごくわずかですが、各エラー条件をより完全にレポートして処理するために、常に追加することができます。

使用例/出力

$ ./bin/tempmxmnavg 

    (1) New measurement 
    (2) Statistics 
    (3) Exit 

    choice: 2 

error: no measurements taken. 

    (1) New measurement 
    (2) Statistics 
    (3) Exit 

    choice: 1 

    Enter day in month : 8 
    Enter month  : 2 
    Enter temperature : 20.0 
    da[ 0] saved 
    ---------------------------- 

    (1) New measurement 
    (2) Statistics 
    (3) Exit 

    choice: 1 

    Enter day in month : 9 
    Enter month  : 2 
    Enter temperature : 30.0 
    da[ 1] saved 
    ---------------------------- 

    (1) New measurement 
    (2) Statistics 
    (3) Exit 

    choice: 1 

    Enter day in month : 10 
    Enter month  : 2 
    Enter temperature : 70.0 
    da[ 2] saved 
    ---------------------------- 

    (1) New measurement 
    (2) Statistics 
    (3) Exit 

    choice: 2 

    minimum temp : 20.00 
    maximum temp : 70.00 
    average temp : 40.00 
    ---------------------------- 

    (1) New measurement 
    (2) Statistics 
    (3) Exit 

    choice: 3 

ルック物事を超えると、ご不明な点がある場合は私に知らせて(夜与えられ、私ははるかに長くここにいないでしょうが...)

+0

Davidこれはすばらしいです、ありがとう、男!!!! – jovkm