Problem z instrukcją switch case w petli while oraz z zapisaniem kolejnych tablic w pliku csv.

0

Witam mam na studiach za zadanie napisanie pewnego projektu którego polecenia wkleję niżej dla szerszego rozeznania w temacie:
Napisz program, który zawiera:

  1. Funkcję generującą przebieg funkcji matematycznej (będzie podany dla każdego indywidualnie).
    Jako parametry wejściowe funkcji wchodzą: tablica współczynników funkcji, dwa parametry
    określające dziedzinę, tablica wynikowa oraz wielkość tablicy wynikowej.
    DLA AMBITNYCH: wygeneruj funkcję piłokształtną lub trójkątną;
  2. Funkcję wczytującą z konsoli współczynniki funkcji (jako tablicę);
  3. Funkcję wczytującą zakres dziedziny;
  4. Funkcję generującą losowy szum (zakłócenia) na sygnale i zapisującą zaszumiony sygnał w
    osobnej tablicy. Szum powinien być losowy w kilku dziedzinach, tzn. na przykład losowo wybrane
    zaszumione próbki, losowa ilość zaszumionych próbek, losowa amplituda o określonych
    granicach itp.;
  5. Funkcję zapisującą tablicę wyników lub zaszumioną tablicę wyników do pliku .CSV z możliwością
    otwarcia w arkuszu kalkulacyjnym;
  6. Funkcję wczytującą rozmiar tablicy wynikowej;
  7. Dynamiczną alokację pamięci dla tablicy wynikowej za pomocą funkcji malloc() lub calloc().
  8. Funkcję odczytującą dane (sygnał) z pliku .CSV z użyciem funkcji realloc() – bez liczenia długości
    pliku;
  9. Funkcję filtrującą wygenerowany lub wczytany sygnał z szumu (filtr medianowy i średniej ruchomej).
    DLA AMBITNYCH: okno filtra o dowolnej szerokości;
  10. Zabezpieczenia programu przed błędnym wprowadzaniem danych;
  11. Menu użytkownika – możliwość generowania, wczytania, zaszumienia i filtracji sygnału, zapisania
    sygnału w każdym z tych stanów itd.

Jak w temacie mam problem ze stworzeniem menu ponieważ w poniższym kodzie gdy w konsoli wejdę np w podawanie parametrów nie mogę wyjść z pętli i program ciągle prosi o wartości parametrów. Kolejny problem to zapis przefiltrowanych danych do pliku .csv. jeżeli dajmy na to rozmiar tablic to 50 to przefiltrowane wyniki zapisują się od 51. komórki w pliku excel. Kombinowałem coś fseek ale bezskutecznie. Będę wdzięczny za wszelką pomoc i rady.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <locale.h>
#include <time.h>

void parametry(float wspolczynniki[])
{
    float parA, parB, parC, parD;

    printf("Podaj parametr A: ");
    scanf("%f", &parA);                                     //pobranie parametrow od uzytkownika

    printf("Podaj parametr B (nie 0): ");
    scanf("%f", &parB);
    while(parB == 0)
    {
        printf("Wprowadziles niepoprawna liczbe podaj liczbe > 0. Parametr B: ");
        scanf("%f", &parB);
    }

    printf("Podaj parametr C: ");
    scanf("%f", &parC);
    while(parC < 0)
    {
        printf("Wprowadziles niepoprawna liczbe podaj liczbe >= 0. Parametr C: ");
        scanf("%f", &parC);
    }

    printf("Podaj parametr D (nie 0): ");
    scanf("%f", &parD);
    while(parD == 0)
    {
        printf("Wprowadziles niepoprawna liczbe podaj liczbe > 0. Parametr D: ");
        scanf("%f", &parD);
    }

    *(wspolczynniki) = parA;                                //przypisanie parametrow do odpowiednich miejsc w tablicy
    *(wspolczynniki+1) = parB;
    *(wspolczynniki+2) = parC;
    *(wspolczynniki+3) = parD;
}

void dziedzina(float *dMin, float *dMax)                    //X ma nalezec do (-1 , 1)
{
    printf("Podaj dolna granice dziedziny: ");
    scanf("%f", dMin);

    printf("Podaj gorna granice dziedziny: ");
    scanf("%f", dMax);

    while(*dMin > *dMax)
    {
        printf("Dolna granica jest wyzsza od gornej podaj nowe wartosci pamietajac ze dMin < dMax\n");

        printf("Podaj dolna granice dziedziny: ");
        scanf("%f", dMin);

        printf("Podaj gorna granice dziedziny: ");
        scanf("%f", dMax);
    }
}

void rozmiar_tablic(int *rozmiar_tablicy)
{
    printf("Podaj liczbe elementow funkcji: ");
    scanf("%d", rozmiar_tablicy);
    while(*rozmiar_tablicy < 0 || *rozmiar_tablicy == 0)
    {
        printf("Wprowadziles niepoprawna liczbe podaj liczbe > 0. Liczba elementow funkcji: ");
        scanf("%d", rozmiar_tablicy);
    }
}

void generator(float wspolczynniki[], float dMin, float dMax, float wyniki[], int rozmiar_tablicy)
{
    float x;
    int i;
    float krok;

    krok = (fabs(dMin) + fabs(dMax)) / rozmiar_tablicy;

    for(i=0; i<rozmiar_tablicy; i++)
    {
        x = dMin + i * krok;            //x jest wyliczany na biezaco
        wyniki[i] = (*(wspolczynniki) * sin(x / *(wspolczynniki+1))) * cos((sqrt( *(wspolczynniki+2))/ *(wspolczynniki+3)) * x);
    }
}

void zapisz(float wyniki[], int rozmiar_tablicy, float wyniki_szumu[], float wyniki_szumu_wlasciwa[])
{
    FILE* arkusz;
    arkusz = fopen("arkusz.CSV", "w");
    if (arkusz == NULL)
    {
        printf("Ups, cos nie dziala! Nie udało się otworzyc pliku CSV. Sprawdz kod i sprobuj zresetowac program\n");
    }

    for(int i=0; i<rozmiar_tablicy; i++)
    {
        wyniki_szumu_wlasciwa[i] = wyniki[i] + wyniki_szumu[i];                     //zapisanie zaszuminej tablicy(suma wynikow i szumow)
        fprintf(arkusz,"%f; %f\n", wyniki[i], wyniki_szumu_wlasciwa[i]);
    }

    fclose(arkusz);
}

void szum (float wyniki[], int rozmiar_tablicy, float wyniki_szumu[])
{
    srand(time(NULL));
    int liczba_zaszumionych;
    int max = (0.21*rozmiar_tablicy);                  //gorna granica losowania
    int min = (0.1*rozmiar_tablicy);                   //dolna granica losowania

    liczba_zaszumionych = (rand()%max+min);
    printf("Liczba zaszumionych probek = %d\n", liczba_zaszumionych);

    float amplituda;
    float najwieksza = wyniki[0];              //ustalamy, że największą wartością jest (póki co) pierwszy element tablicy
    float najmniejsza = wyniki[0];             //ustalamy, że najmniejszą wartością jest (póki co) pierwszy element tablicy

    for( int i = 0; i < rozmiar_tablicy; i++ )         //szukanie amplitudy
    {
        if( wyniki[i] > najwieksza )
        najwieksza= wyniki[i];                 //jeśli sprawdzany element tablicy jest większy od tego (dotychczas) największego, to on staje się tym największym

        if( wyniki[i] < najmniejsza )
        najmniejsza = wyniki[i];               //jeśli sprawdzany element tablicy jest mniejszy od tego (dotychczas) najmniejszego, to on staje się tym najmniejszym
    }

    amplituda = fabs(najwieksza) + fabs(najmniejsza);

    printf("Najwieksza wartosc funkcji to: %f\n", najwieksza);
    printf("Najmniejsza wartosc funkcji to: %f\n", najmniejsza);
    printf("Amplituda wynosi: %f\n", amplituda);

    int i2;
    float wartosc_szumu;
    int max_szum = 31*amplituda*2;
    int min_szum = -31*amplituda;
    int numer_tablicy;

    for(i2 = 0; i2 < liczba_zaszumionych; i2++)
    {
        numer_tablicy = (rand()%rozmiar_tablicy+1);
        wartosc_szumu = rand()%max_szum/100.+min_szum/100.;
        wyniki_szumu[numer_tablicy] = wartosc_szumu;
       // wyniki_szumu_wlasciwa[numer_tablicy] = wyniki_szumu[numer_tablicy] + wyniki[numer_tablicy];
    }
}

void otwarcie_pliku(float **wyniki, float **wyniki_szumu_wlasciwa, int rozmiar_tablicy)
{
    float pierwsza_liczba;
    float druga_liczba;
    int nowy_rozmiar;
    nowy_rozmiar = 1;

    FILE* arkusz;
    arkusz = fopen("arkusz.CSV", "r");
    if (arkusz == NULL)
    {
        printf("Ups, cos nie dziala! Nie udalo sie otworzyc pliku CSV. Sprawdz kod i sprobuj zresetowac program\n");
    }

    printf("Wartosc prawdziwa:                  Wartosc po zaszumieniu:\n");
    while (fgetc(arkusz) != EOF)            //odczytuje znak i przesuwa kursor o 1
    {
        fseek(arkusz, -1, SEEK_CUR);
        fscanf(arkusz, "%f  ; ", &pierwsza_liczba);
        *wyniki = realloc(*wyniki, nowy_rozmiar * sizeof(int));
        printf("%f                            ", pierwsza_liczba);      //dlaczego nie ma minusów, sprobowac cofnac o 1 fseek argument -1 seek cur
        *(*wyniki + nowy_rozmiar - 1) = pierwsza_liczba;
        fscanf(arkusz, "%f  ;  ", &druga_liczba);
        *wyniki_szumu_wlasciwa = realloc(*wyniki_szumu_wlasciwa, nowy_rozmiar * sizeof(int));
        printf("%f\n", druga_liczba);
        *(*wyniki_szumu_wlasciwa + nowy_rozmiar - 1) = druga_liczba;
        nowy_rozmiar++;
    }
    fclose(arkusz);
}

float sortowanie_babelkowe(float *tab, int szerokosc_okna_filtra)
{
    float temp;
    int i;
    do
    {
        for(i = 0; i < szerokosc_okna_filtra - 1; i++)      //x-1 zeby warunek mniejszosci j nie wyszedł do 6
        {
            if(tab[i] > tab[i+1])
            {
                temp = tab[i+1];
                tab[i+1] = tab[i];
                tab[i] = temp;
            }
        }
        szerokosc_okna_filtra--;
    }while(szerokosc_okna_filtra > 1);

    return tab[2];   //zwracamy wyraz środkowy
}

void filtr_medianowy(float *wyniki, float *wyniki_szumu_wlasciwa,float *wyniki_po_medianowym, int rozmiar_tablicy)
{
    float tab[5];

    wyniki_po_medianowym[0] = wyniki_szumu_wlasciwa[0];         //przepisanie dwoch pierwszych i ostatnich wyrazow tabeli do tabeli przefiltrowanych danych
    wyniki_po_medianowym[1] = wyniki_szumu_wlasciwa[1];
    wyniki_po_medianowym[rozmiar_tablicy-1] = wyniki_szumu_wlasciwa[rozmiar_tablicy-1];
    wyniki_po_medianowym[rozmiar_tablicy-2] = wyniki_szumu_wlasciwa[rozmiar_tablicy-2];

    for (int j = 2; j < rozmiar_tablicy; j++)         //j=2 bo olewamy pierwsze dwa przepisane wczesniej miejsca
    {
        tab[0] = wyniki_szumu_wlasciwa[j-2];        //przypisujemy wartosci do tablicy ktora potem sortujemy babelkowo
        tab[1] = wyniki_szumu_wlasciwa[j-1];
        tab[2] = wyniki_szumu_wlasciwa[j];
        tab[3] = wyniki_szumu_wlasciwa[j+1];
        tab[4] = wyniki_szumu_wlasciwa[j+2];
        wyniki_po_medianowym[j] = sortowanie_babelkowe(tab, 5);    //przypisanie wartosci przesortowanej babelkowo do itego miejsca w tablicy po filtrowaniu
    }

    FILE* arkusz;
    arkusz = fopen("arkusz.CSV", "a");          //jak dopisac ta tablice od poczatku a nie tak na koncu
    fseek(arkusz, 3, SEEK_SET );

    if (arkusz == NULL)
    {
        printf("Ups, cos nie dziala! Nie udalo sie otworzyc pliku CSV. Sprawdz kod i sprobuj zresetowac program\n");
    }

    for(int j2 = 0; j2<rozmiar_tablicy; j2++)
    {
        fprintf(arkusz,";;%f\n", wyniki_po_medianowym[j2]);
    }

    fclose(arkusz);
}
float srednia_okna(float *tab)
{
    float srednia;

    srednia = (tab[0] + tab[1] + tab[2] + tab[3] + tab[4])/5;

    return srednia;   //zwracamy srednia 5 wyrazow
}

void filtr_srednia_ruchoma(float *wyniki, float *wyniki_szumu_wlasciwa,float *wyniki_po_sredniej, int rozmiar_tablicy)
{
    float tab[5];

    wyniki_po_sredniej[0] = wyniki_szumu_wlasciwa[0];         //przepisanie dwoch pierwszych i ostatnich wyrazow tabeli do tabeli przefiltrowanych danych
    wyniki_po_sredniej[1] = wyniki_szumu_wlasciwa[1];
    wyniki_po_sredniej[rozmiar_tablicy-1] = wyniki_szumu_wlasciwa[rozmiar_tablicy-1];
    wyniki_po_sredniej[rozmiar_tablicy-2] = wyniki_szumu_wlasciwa[rozmiar_tablicy-2];

        for (int j = 2; j < rozmiar_tablicy-2; j++)         //j=2 bo olewamy pierwsze dwa przepisane wczesniej miejsca
    {
        tab[0] = wyniki_szumu_wlasciwa[j-2];        //przypisujemy wartosci do tablicy ktora potem sortujemy babelkowo
        tab[1] = wyniki_szumu_wlasciwa[j-1];
        tab[2] = wyniki_szumu_wlasciwa[j];
        tab[3] = wyniki_szumu_wlasciwa[j+1];
        tab[4] = wyniki_szumu_wlasciwa[j+2];
        wyniki_po_sredniej[j] = srednia_okna(tab);
    }

    FILE* arkusz;
    arkusz = fopen("arkusz.CSV", "a");          //jak dopisac ta tablice od poczatku a nie tak na koncu
    fseek(arkusz, 4, SEEK_SET );

    if (arkusz == NULL)
    {
        printf("Ups, cos nie dziala! Nie udalo sie otworzyc pliku CSV. Sprawdz kod i sprobuj zresetowac program\n");
    }

    for(int j2 = 0; j2<rozmiar_tablicy; j2++)
    {
        fprintf(arkusz,";;;%f\n", wyniki_po_sredniej[j2]);
    }

    fclose(arkusz);
}
int main()
{
    setlocale(LC_ALL, "polish_poland");

    float tablica_par[4];           //tablica_par to nazwa tablicy w ktorej sa parametry A B C D
    //parametry(tablica_par);         //wywo³anie funkcji wprowadzania parametrow

    float dMin;
    float dMax;
   // dziedzina(&dMin, &dMax);            //wywolanie funkcji okreslania granic x

    int rozmiar_tablicy;
   // rozmiar_tablic(&rozmiar_tablicy);

    float *wyniki;
    wyniki = malloc(rozmiar_tablicy * sizeof(*wyniki));
    float *wyniki_szumu;
    wyniki_szumu = malloc(rozmiar_tablicy * sizeof(*wyniki_szumu));
    float *wyniki_szumu_wlasciwa;
    wyniki_szumu_wlasciwa = malloc(rozmiar_tablicy * sizeof(*wyniki_szumu_wlasciwa));

   // generator(tablica_par, dMin, dMax, wyniki, rozmiar_tablicy);

    float *wyniki_po_medianowym;
    wyniki_po_medianowym = malloc(rozmiar_tablicy * sizeof(*wyniki_po_medianowym));
    float *wyniki_po_sredniej;
    wyniki_po_sredniej = malloc(rozmiar_tablicy * sizeof(*wyniki_po_sredniej));

    int wybor;
        wybor = 0;
        int wybor_filtra;
        wybor_filtra = 0;
printf("1)Podaj wspolczynniki\n2)Podaj dziedzine x\n3)Podaj illosc probek\n4)Generuj funkcje\n5)Zapisz funkcje\n6)Zaszum\n7)Odczytaj z pliku\n8)Filtruj\n9)Zakoncz\n");
scanf("%d",&wybor);
while(wybor != 9)
{
    switch(wybor)
    {
        case 1:
            parametry(tablica_par);
            break;
        case 2:
            dziedzina(&dMin, &dMax);
            break;
        case 3:
            rozmiar_tablic(&rozmiar_tablicy);
            break;
        case 4:
            generator(tablica_par, dMin, dMax, wyniki, rozmiar_tablicy);
            break;
        case 5:
            zapisz(wyniki, rozmiar_tablicy, wyniki_szumu, wyniki_szumu_wlasciwa);
            break;
        case 6:
            szum(wyniki, rozmiar_tablicy, wyniki_szumu);
            break;
        case 7:
            otwarcie_pliku(&wyniki, &wyniki_szumu_wlasciwa, rozmiar_tablicy);
            break;
        case 8:

            printf("Wybierz rodzaj filtra\n1)Filtr medianowy\n2)Filtr sredniej ruchomej\n");
            scanf("%d",&wybor_filtra);

            switch(wybor_filtra)
            {
                case 1:
                filtr_medianowy(wyniki, wyniki_szumu_wlasciwa,wyniki_po_medianowym, rozmiar_tablicy);
                break;
                case 2:
                filtr_srednia_ruchoma(wyniki, wyniki_szumu_wlasciwa,wyniki_po_medianowym, rozmiar_tablicy);
                break;
            }
            break;

        case 9:
            exit( EXIT_SUCCESS );
            break;
        default:
            while(wybor < 1 || wybor > 8)
            {
                printf("Nie udalo Ci sie wybrac poprawnej opcji sprobuj jeszcze raz :)");
                scanf("%d",&wybor);
            }
    }
}

   // szum(wyniki, rozmiar_tablicy, wyniki_szumu);

    //zapisz(wyniki, rozmiar_tablicy, wyniki_szumu, wyniki_szumu_wlasciwa);

    //otwarcie_pliku(&wyniki, &wyniki_szumu_wlasciwa, rozmiar_tablicy);

    //filtr_medianowy(wyniki, wyniki_szumu_wlasciwa,wyniki_po_medianowym, rozmiar_tablicy);

    //filtr_srednia_ruchoma(wyniki, wyniki_szumu_wlasciwa,wyniki_po_medianowym, rozmiar_tablicy);

    //printf("Po filtrze: %f\n", wyniki_po_medianowym[0]);      cos nie dziala


    wyniki = NULL;
    wyniki_szumu = NULL;
    wyniki_szumu_wlasciwa = NULL;
    wyniki_po_medianowym = NULL;
    wyniki_po_sredniej = NULL;
    free(wyniki);
    free(wyniki_szumu);
    free(wyniki_szumu_wlasciwa);
    free(wyniki_po_medianowym);
    free(wyniki_po_sredniej);

    return 0;
}

1
Sab Fil napisał(a):

gdy w konsoli wejdę np w podawanie parametrów nie mogę wyjść z pętli i program ciągle prosi o wartości parametrów

To dlatego, że wczytujesz wartość wybor tylko przed rozpoczęciem pętli i później ona się nie zmienia.
Pętla w sekcji default jest zbędna.

do
{
    scanf("%d", &wybor);
    switch (wybor)
    {
        // ...
        default:
            printf("Nie udalo Ci sie wybrac poprawnej opcji sprobuj jeszcze raz :)");
    }
} while (wybor != 9);
Sab Fil napisał(a):

Kolejny problem to zapis przefiltrowanych danych do pliku .csv. jeżeli dajmy na to rozmiar tablic to 50 to przefiltrowane wyniki zapisują się od 51.

Nie dodawaj znaku końca linii do ostatniego wiersza:

fprintf(arkusz,"%f; %f", wyniki[i], wyniki_szumu_wlasciwa[i]);
if (i + 1 < rozmiar_tablicy)
{
    fprintf(arkusz, "\n");
}
0

Zmieniłem menu zgodnie z teoimi wskazówkami. Działa ale do czasu. Moge wprowadzic wszystkie potrzebne dane ale gdy chce wygenerować funkcję to program się wysypuje. Nie wiem co moze byc nie tak z case 4.

0

Trochę dla mnie zbyt skomplikowana całość, nie wszystko pojmuję ale taka jedna kosmetyczna rzecz, a może pomoże.

W case4 w funkcji - czy nie potrzebujesz nawiasu? Chodzi o kolejność wykonywania działań dla x

0

Dzięki, ale to nic nie zmienia.

0

Postaw sobie breakpointa w funkcji generator() na linijce krok = ...
Uruchom debugger
Sprawdź czy np rozmiar_tablicy nie jest zerem. Jeśli jest - to masz winowajcę, jest nim próba dzielenia przez zero na co procesor/system odpowiada rzuceniem wyjątku, który jeśli nie jest obsłużony powoduje wykrzaczenie programu.
Następnie korzystając z funkcji "Step over" debuggera wykonuj ciało funkcji generator() krok po kroku aż program się wywali - wtedy będziesz wiedział która linia powoduje błąd. Analiza stosu wywołań oraz wartości zmiennych w tym momencie pozwoli na zdiagnozowanie problemu.

0

Ok niby wszystko działa ale pozostała kwestia tego apisu w excelu. Sposób opisany wyżej zapisuje wyniki w wierszach wiec koniec końców mamy 4 bardzo długie wiersz. Chciałbym aby wyniki były w czterech kolumnach. No i mam tez problem z zapisem danych, ponieważ chciałbym aby można było wybrać tylko jedną rzecz do zapisu np. same wyniki bez szumów be pisania 4 osobnych funkcji i zmuszania użytkownika do wybrania poprawnej. Miałem pomysł z przesłaniem do excela tablicy dwuwymiarowej [rozmiar_tablicy][4] i potem fseek żeby zacząć zapisywanie kolumn od odpowiedniego miejsca np dla szumów fseek(arkusz, 1, SEEK_SET)

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