• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przetwarzanie sygnału w C. Problem z zarządzaniem pamięcią.

Object Storage Arubacloud
0 głosów
484 wizyt
pytanie zadane 6 listopada 2016 w C i C++ przez Fenix7 Nowicjusz (210 p.)

Witam.

Jako projekt zaliczeniowy na studiach musze napisać program generujący i przetwarzający sygnał(sinus). Podczas sprawdzania testem gremlina zaczęły dziać sie rzeczy, których nie potrafie wytłumaczyć. Program jednym razem zadziała pięknie, innym wysypie sie podczas otwierania pliku, innym przy czyszczeniu tablicy, a jeszcze innym przy wyjściu ze switch'a. Sugeruje mi to jakiś problem z zarządzaniem pamięcią, jednak nie potrafie go zlokalizować.Do tej pory najczęściej wysypywał mi sie przy sekwencji: (w podkreślonych miejscach) 1.Generowanie>3.Zaszumienie>5.Filtracja>6.Zapis>7.Zamknięcie>Ponowne odpalenie>2.Wczytanie>3. Zaszumianie>5.Filtracja>6.Zapis>7.Zamknięcie. Niewykluczone, że popełniam jakiś banalny błąd. Prosze o analize, wskazówki co jest nie tak i jak to naprawić. :)

Kod w C:

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



void wspolczynniki(float *wsp)
{
		printf("Podaj parametry funkcji.\nAmplituda sin:\n");
		scanf("%f", &wsp[0]);
		printf("Omega:\n");
		scanf("%f", &wsp[1]);
		printf("Przesunięcie fazowe:\n");
		scanf("%f", &wsp[2]);
		printf("Stała c:\n");
		scanf("%f", &wsp[3]);
		printf("Podaj początek dziedziny:\n");
		scanf("%f", &wsp[4]);
		printf("Podaj koniec dziedziny:\n");
		scanf("%f", &wsp[5]);	
		wsp[6] = 0;
			while(*(wsp + 6)==0)
			{
				printf("Podaj ilość próbek:(różną od 0)\n");
				scanf("%f", &wsp[6]);
			}
		system("cls");
}

void funkcja(float *wsp, float *wynik)
{
	 float p, x, a, w, f, c, d1, d2;
	 a = *wsp;
	 w = *(wsp + 1);
	 f = *(wsp + 2);
	 c = *(wsp + 3);
	 d1 = *(wsp + 4);
	 d2 = *(wsp + 5);
	 p = (d2 - d1) / *(wsp+6);
	 x = d1;
	 printf("Wspołczynniki: %f %f %f %f\n", a, w, f, c);
	
	 int i;
	 for (i = 0; i < *(wsp+6); i++)
	 {
		 *wynik =a*(float)sin(w*x + f) + c;
		 wynik = wynik + 1;
		 x = x + p;
	 }
	 printf("Sygnał został wygenerowany.\n\n");
	  
}

int odczyt(float **tab1, float *wsp)
{
	float x, y, a;
	int i=2;
	int *temp;
	FILE *plik;
	
	plik = fopen("C:\\tablica1.csv", "r");
		if (plik == NULL)
			{
			printf("Nie można otworzyć pliku. Plik może być otwarty w innym programie.\n\n;");
			return 0;
			}
		
		if (!feof(plik))
		{
			fscanf(plik, "%f;%f\n", &x, &y);
			temp = realloc(*tab1, 1 * sizeof(float));
			if (temp != NULL)
				*tab1 = temp;
			else {
				printf("Błąd realokacji tablicy\n");
				return 0;
			}

			(*tab1)[0] = y;
			a = x;
			printf("%d\n", i);

		}
		
		if (!feof(plik))
		{
			fscanf(plik, "%f;%f\n", &x, &y);
			temp = realloc(*tab1, 2 * sizeof(float));
			if (temp != NULL)
				*tab1 = temp;
			else {
				printf("Błąd realokacji tablicy\n");
				return 0;
			}

			(*tab1)[1] = y;

			printf("%d\n", i);

		}
		wsp[4] = a;
		float k;
		k = x - a;
		
		while(!feof(plik))
		{
			i++;
			temp = realloc(*tab1, i * sizeof(float));
			if (temp != NULL)
				*tab1 = temp;
			else {
				printf("Błąd realokacji tablicy\n");
				return 0;
			}
			
			fscanf(plik, "%f;%f\n", &x, &y);
			(*tab1)[i - 1] = y;
			printf("%d\n", i);
		
		}

		wsp[5] = a + (i - 1)*k;
		wsp[6] = i;
	fclose(plik);
	
	

}

void szum(float tab[], float wsp[])
{
	srand(time(NULL));
	int p = (rand() % 21); //Procent zaszumionych próbek
	int zp = (p*wsp[6] / 100); //Ilość zaszumionych próbek
	int* np;
	np = calloc(zp, sizeof(int));//Tablica z numerami zaszumionych próbek
	int i;
	
	for (i = 0; i < zp; i++)
	{
		np[i] = rand() % ((int)wsp[6] + 1);
		printf("NUMER%d\n", np[i]);
	}
	
	for (i = 0; i < zp; i++)
	{
		tab[np[i]] = (((float)(rand() % 201) - 100)/100);
			printf("LICZBA%f\n", tab[np[i]]);
	}
	free(np);
	printf("Szum został dodany.\n\n");

}

void filtrs(float tab1[], float tab2[], float wsp[])
{
	float okno[5];
	int i;
	float s;
	tab2[0] = tab1[0];
	tab2[1] = tab1[1];

	for (i = 0; i < (wsp[6]-2); i++)
	{
		okno[0] = tab2[i];
		okno[1] = tab2[i + 1];
		okno[2] = tab1[i + 2];
		okno[3] = tab1[i + 3];
		okno[4] = tab1[i + 4];
		s = (okno[0] + okno[1] + okno[2] + okno[3] + okno[4]) / 5;
		tab2[i + 2] = s;
	}

	tab2[(int)wsp[6] - 2] = tab1[(int)wsp[6] - 2];
	tab2[(int)wsp[6] - 1] = tab1[(int)wsp[6] - 1];


}

void filtrm(float tab1[], float tab2[], float wsp[])
{
	float okno[5];
	int i;
	tab2[0] = tab1[0];
	tab2[1] = tab1[1];

	for (i = 0; i < (wsp[6] - 2); i++)
	{
		okno[0] = tab2[i];
		okno[1] = tab2[i + 1];
		okno[2] = tab1[i + 2];
		okno[3] = tab1[i + 3];
		okno[4] = tab1[i + 4];

		
		int m, n;
		float temp;
			for (m = 0; m<4; m++)
			{
				for (n = 0; n<4 - m; n++)
				{
					if (okno[n] > okno[n + 1])
					{
						temp = okno[n + 1];
						okno[n + 1] = okno[n];
						okno[n] = temp;
					}
				}
				
			}
			tab2[i + 2] = okno[2];
			
	}

	tab2[(int)wsp[6] - 2] = tab1[(int)wsp[6] - 2];
	tab2[(int)wsp[6] - 1] = tab1[(int)wsp[6] - 1];

}

int zapis(float tab1[], float tab2[], float tab3[], float wsp[])
{
	int i;
	float k;
	FILE *tablica1;
	FILE *tablica2;
	FILE *tablica3;
	
		tablica1 = fopen("C:\\tablica1.csv", "w");
			if (tablica1 == NULL)
				{
					printf("Nie można otworzyć pliku 'tablica1.csv'. Plik może być otwarty w innym programie.\n\n;");
					return 0;
				}
			else {
					for (i = 0; i < wsp[6]; i++)
					{
						k = *(wsp + 4) + i*((*(wsp + 5) - *(wsp + 4)) / *(wsp + 6)); //Przyrost argumentu
						fprintf(tablica1, "%f;%f\n", k, tab1[i]);
					}
					fclose(tablica1);
				}
	
		tablica2 = fopen("C:\\tablica2.csv", "w");
			if (tablica2 == NULL)
				{
					printf("Nie można otworzyć pliku 'tablica2.csv'. Plik może być otwarty w innym programie.\n\n;");
					return 0;
				}
			else {
					for (i = 0; i < wsp[6]; i++)
					{	
						k = *(wsp + 4) + i*((*(wsp + 5) - *(wsp + 4)) / *(wsp + 6));
						fprintf(tablica2, "%f;%f\n", k, tab2[i]);
					}
					fclose(tablica2);
				}
		
		tablica3 = fopen("C:\\tablica3.csv", "w");
			if (tablica3 == NULL)
				{
					printf("Nie można otworzyć pliku'tablica3.csv'. Plik może być otwarty w innym programie.\n\n;");
					return 0;
				}
			else {
					for (i = 0; i < wsp[6]; i++)
					{
						k = *(wsp + 4) + i*((*(wsp + 5) - *(wsp + 4)) / *(wsp + 6));
						fprintf(tablica3, "%f;%f\n", k, tab3[i]);
					}
					fclose(tablica3);
				}
}

void drukuj(float tab[], float wsp[])
{
	int i;
	for(i=0; i<wsp[6]; i++)
	{
		printf("%f\n", tab[i]);
	}
}

int main()
{
	setlocale(LC_ALL, "polish_poland");
	int n=0;
	float twsp[7];
	int *twynik;
	int *zwynik;
	int *owynik;
	int r = 0;
	twynik = calloc(1, sizeof(float));
	zwynik = calloc(1, sizeof(float));
	owynik = calloc(1, sizeof(float));
	

	do
	{
		printf("1.Generuj sygnał\n2.Wczytaj sygnał\n3.Zaszum sygnał\n4.Filtruj(średnia ruchoma)\n5.Filtruj(mediana)\n6.Zapisz sygnał\n7.Zakończ program\n");
		scanf("%d", &n);

		switch (n)
		{
		case 1:
			system("cls");
			wspolczynniki(twsp);


			int *temp;
			temp = realloc(twynik, twsp[6] * sizeof(float));
			if (temp != NULL)
				twynik = temp;
			else
				printf("Błąd realokacji tablicy\n");


			temp = realloc(zwynik, twsp[6] * sizeof(float));
			if (temp != NULL)
				zwynik = temp;
			else
				printf("Błąd realokacji tablicy\n");


			funkcja(twsp, twynik);
			r = 1;
			break;

		case 2:
			odczyt(&twynik, twsp);
			r = 1;
			printf("%f,%f,%f", *(twsp + 4), *(twsp + 5), *(twsp + 6));
			break;

		case 3:
			if (!r)
				{
					system("cls");
					printf("Brak danych do zaszumienia\n\n");
				}
			
			else
				{
					system("cls");
					int i;
					realloc(zwynik, twsp[6] * sizeof(float));
					for (i = 0; i < twsp[6]; i++)
						zwynik[i] = twynik[i];
					
					szum(zwynik, twsp);
				}
			break;
				
			
			case 4:
				if (!r)
				{
					system("cls");
					printf("Brak danych do filtracji\n\n");
				}

				else
				{
					system("cls");
					owynik = realloc(owynik, twsp[6] * sizeof(float));
					filtrs(zwynik, owynik, twsp);
					break;
				}
			
			case 5:
				if (!r)
				{
					system("cls");
					printf("Brak danych do filtracji\n\n");
				}

				else
				{
					system("cls");
					owynik = realloc(owynik, twsp[6] * sizeof(float));
					filtrm(zwynik, owynik, twsp);
				}
				break;
			
			case 6:
				if (!r)
				{
					system("cls");
					printf("Brak danych do zapisu\n\n");
				}

				else
				{
					system("cls");
					zapis(twynik, zwynik, owynik, twsp);
				}
				break;
				
			case 7:
				n = 7;
				break;
			
			case 8:
				drukuj(twynik, twsp);
				break;

			default:
				system("cls");
				printf("Nie ma takiej opcji\n\n");
				break;
			}

	} while (n != 7);
	
	free(owynik);
	free(twynik);
	free(zwynik);
	return 0;
}

 

2 odpowiedzi

0 głosów
odpowiedź 6 listopada 2016 przez draghan VIP (106,230 p.)

Hmm... Kod jest obszerny i naszpikowany wskaźnikami. Można się pomylić w wielu miejscach. :) Zastanawia mnie, dlaczego tak często występuje tam notacja *(wsk + x) w stosunku do tablic, zamiast po prostu operacji indeksowania, która jest o wiele czytelniejsza. Również przy deklaracjach funkcji lepiej jest jawnie pokazywać, który argument ma być tablicą (int tab[] zamiast int *tab), a który ewentualnym parametrem wyjściowym (a najlepiej w ogóle unikać parametrów wyjściowych).

Funkcje zapis() i odczyt() są zadeklarowane jako zwracające int, a istnieją w nich scenariusze wykonania, które nie zwracają nic. W C to tylko formalność, Ty nawet nie sprawdzasz co wywołana funkcja zwróciła (a powinieneś ;).

Coś poważniejszego co mi się rzuciło w oczy, to wskaźniki:

    int *twynik;
    int *zwynik;
    int *owynik;

które powinny mieć chyba inny typ.

komentarz 6 listopada 2016 przez Fenix7 Nowicjusz (210 p.)
Odnośnie notacji *(wsk + x): Osobiście też wole bezpośrednio jednak w projekcie mieliśmy nauczyć i przećwiczyć posługiwanie sie wskaźnikami, dlatego przez pierwszą część używałem takiego zapisu.

Deklaracja funkcji na int: z początku zadeklarowałem je jako void jednak musiałem zabezpieczyć sie na wypadek problemów z otworzeniem pliku. W proponowanym rozwiązaniem było zastosowanie if, które w przypadku niepowodzenia zwraca 0. Świadom jestem, że nie ma to większego znaczenia, a że czasu na projekt nie miałem zbyt dużo(jest już po terminie, teraz poprawki) to nie przywiązywałem do tego większej uwagi.

A co do ostatnich wskaźników: Nie jestem pewny w jaki sposób się to buduje. Deklaruje wskaźnik na tablice floatów jednak sam wskaźnik jest liczbą całkowitą więc nie powinien być zadeklarowany jako int?
komentarz 6 listopada 2016 przez draghan VIP (106,230 p.)

W proponowanym rozwiązaniem było zastosowanie if, które w przypadku niepowodzenia zwraca 0.

...to brakuje uzupełnienia o przypadek powodzenia - wtedy należy zwrócić liczbę różną od zera.

A co do ostatnich wskaźników: Nie jestem pewny w jaki sposób się to buduje. Deklaruje wskaźnik na tablice floatów jednak sam wskaźnik jest liczbą całkowitą więc nie powinien być zadeklarowany jako int?

To, że adres w pamięci jest liczbą, nie jest ważne. Ty chcesz mieć tablicę elementów float, więc zdefiniuj wskaźnik na float i alokuj dynamicznie (czy co tam z tymi wskaźnikami później robisz). Musisz wyraźnie powiedzieć kompilatorowi, z jakimi elementami będzie miał w tablicy do czynienia - jest to mu niezbędne, żeby wybrał poprawny zestaw arytmetyczny dla Twoich wskaźników - inaczej będzie inkrementowany wskaźnik na char, a inaczej na double, inaczej też będzie zachodzić interpretacja przy dereferencji.

komentarz 9 listopada 2016 przez draghan VIP (106,230 p.)
To może inaczej. Opisz, co robią Twoje funkcje zapisu i odczytu z pliku, bo to nie jest takie oczywiste.
0 głosów
odpowiedź 9 listopada 2016 przez Fenix7 Nowicjusz (210 p.)
Ma ktoś jeszcze jakieś pomysły co może być nie tak? Jakie mogą być przyczyny wysypywania sie programu podczas otwierania pliku lub funkcji free(), którą zwalniam pamięć?

Podobne pytania

0 głosów
2 odpowiedzi 218 wizyt
pytanie zadane 3 listopada 2016 w C i C++ przez Tinsonu Początkujący (280 p.)
+2 głosów
1 odpowiedź 148 wizyt
0 głosów
1 odpowiedź 2,301 wizyt

92,619 zapytań

141,468 odpowiedzi

319,786 komentarzy

62,001 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...