Prośba o sprawdzenie poprawnosci programu

0

Witam
w sieci znalazlem zadanie do napisania w języku c.

Napisac program, który czyta ciag liczb ze standardowego wejscia az do wystapienia
znaku konca pliku (kombinacja klawiszy Ctrl–D na klawiaturze), a nastepnie oblicza
srednia˛ arytmetyczna i odchylenie standardowe, po czym wyprowadza wyniki na
standardowe wyjscie. W pierwszej wersji programu, dane moga byc przechowywane w
jednowymiarowej tablicy liczb zmiennoprzecinkowych o ustalonym rozmiarze maksymalnym
(np. SIZE = 1000) zadeklarowanym jako stała całkowita.

Poniżej zamieszczam kod:

 
#include <stdio.h>
#include <math.h>
#include <conio.h>

#define NMAX 1000

int main()
{
        double TablicaWartosci[NMAX];
        int i;
        int LiczbaProb;
        double c;
        double SredniaArytmetyczna;
        double Wariancja;

        c=0.0;
        i=0;
        SredniaArytmetyczna=0;
        Wariancja = 0.0;

        while(scanf("%lf",&c)!=EOF)
        {
                TablicaWartosci[i]=c;
                i++;
        }

        LiczbaProb = i;
        --i;
        while(i>=0)
        {
                SredniaArytmetyczna+=TablicaWartosci[i];
                --i;
        }
        SredniaArytmetyczna = SredniaArytmetyczna/LiczbaProb;
        printf("Srednia arytmetyczna podanych wartosci wynosi: %lf\n",SredniaArytmetyczna);

        i = 0;
        while(i<LiczbaProb)
        {
                Wariancja = Wariancja + pow((TablicaWartosci[i] - SredniaArytmetyczna),2.0);
                i++;
        }
        Wariancja = Wariancja/LiczbaProb;
        printf("Wariancja podanych warosci wynosi: %lf\n",Wariancja);
        printf("Odchylenie standardowe wynosi: %lf\n",sqrt(Wariancja));

        getch();
        return 0;
}
 

Wydaje się, że program produkuje poprawne wyniki, ale mam pytanie odnośnie tego czy program jest prawidłowo napisany czy prawidłowe jest użycie funkcji scanf do testowania warunku pętli i czy program można by uprościc.

1

Kod wygląda generalnie ok. Ale są "ale" (przy czym jeśli pisałeś to podczas nauki w szkole to kod jest bardzo ładny imo):

  1. Nie obsługujesz błędnego inputu do stdin, np. literek. Dlatego porównywałbym wynik scanfa z 1 (zwraca ilość poprawnie wczytanych wartości lub EOF)
  2. Optymalizujesz przypisania do zmiennych i ich ilość. Zamiast dziwnych zabaw z i, użyj for(int i = 0; i < LiczbaProb; ++i)
  3. Polskie nazwy zmiennych. Nie.
  4. Inicjalizujesz zmienne po ich definicji. Możesz i powinieneś to robić od razu. Np. double c = 0.0;
  5. Wstrzymujesz wykonanie za pomocą getch. (co to w ogóle ma robić skoro stdin już zamknięty?)

Tyle na szybko.

0

Dziękuję za odpowiedź
odnośnie punktu 1. Czy można wczytac wartosc do c i ewentualnie potem testowac czy nie została wprowadzona bledna wartosc np

 
while(scanf(%lf,&c)!=EOF)
{
        if(c>='a'&&c<='Z')
               break;
               //Przejdz do obslugi błędu na zewnątrz pętli 
}

tyle że trzeba by jeszcze dodac kawałek kodu
w oczy rzuciło mi się też, że nie dodałem sprawdzenia limitu liczb do warunku pętli bo może ich by tylko NMAX czyli
while((scanf(%lf,&c)!=EOF)&&(i<NMAX)

Dalszym pytaniem do zadania jest czy można by napisac taki program bez narzucenia limitu na liczbę danych i bez korzystania z tablic.
Według mnie można policzyc srednią arytmetyczna przechowując ją w jednej zmiennej (sumując kolejne proby) i dzielac przez ilosc prob ale zeby obliczyc wariancje i odchylenie standardowe musimy miec dostęp do kolejno wprowadzanych danych. Nawet dynamicznie alokując pamięc trzeba podac funkcji malloc rozmiar. Czy jest jakis sposob zeby to obejsc.

0

Jeśli to musi być C to realloc. W C++ std::vector.

Co do sprawdzenia: jak wczytanie się nie uda to zostanie tam poprzednio wprowadzona poprawna liczba.

0

Jestem ponownie.
Testowałem działanie funkcji scanf. Zauważyłem, ze kontrole poprawnosci danych moglbym sprawdzac za pomoca następującego kawałka kodu:

 
int test;
while(((test = scanf("%f",&c))!=EOF)&&(test!=0)&&i<10)
//
if(test==EOF)
//Przejdz do obliczen
if(test==0)
//Nieprawidlowa wartosc zakoncz program

czyli scanf zwraca EOF jeśli napotka koniec pliku i zwraca wartosc 0 jeśli wystąpił błąd.
To jest dla mnie dziwne bo w książce "Język ANSI C" Kernighana i Ritchiego jest napisane, że scanf zwraca EOF jeśli napotka koniec danych lub wystąpi błąd. Proszę o jakieś wyjaśnienie. Dodam, że korzystam z kompilatora Borland c++ builder 6, system operacyjny windows, ale przecież standard nie zależy ani od kompilatora ani od sytemu operacyjnego.

2
kq napisał(a)

Dlatego porównywałbym wynik scanfa z 1 (zwraca ilość poprawnie wczytanych wartości lub EOF)

while(scanf("%lf", &c) == 1) //...

K&R ostatni update miała przed standaryzacją C89. Wyszły od tego czasu 2 nowe wersje języka, zmieniło się dwóch papieży, upadł komunizm i ogółem minęło sporo czasu. http://en.cppreference.com/w/c/io/fscanf - nowsza dokumentacja.

A BCB jest z 2002 roku. Również wymienić.

0

Dziękuję za odpowiedzi

1 użytkowników online, w tym zalogowanych: 0, gości: 1