Problem z tablicą stringów i przeciążonym operatorem +

0

Witam. Od razu mówię, ze jestem początkujący jeśli chodzi o programowanie. Podczas pisania programu na zaliczenie, który ma wykonywać operacje na zbiorach napotkałem pewien problem. Program pisany w Visualu 2010, w MFC.

W obiekcie typu ZbiorNazw:
S - jest wskaźnikiem na tablicę stringów
n - liczbą elementów (tablicy)

Podczas wszystkie operacje na zbiorach są przeprowadzane w przeciążonych operatorach. Wywołanie operatora + w programie powoduje zawieszenie się programu bez błędów kompilacji. Z tego co sam zdołałem wywnioskować błąd powoduje linijka

tab[q]=s.S[j];

Po jej usunięciu zbiór sumy wyświetla się tylko w zbiorze znajdują się tylko elementy pierwszego

Program zatrzymuje się na pliku mlock.c w funkcji:

void __cdecl _unlock (
        int locknum
        )
{
        /*
         * leave the critical section.
         */
        LeaveCriticalSection( _locktable[locknum].lock );
}

Poniżej cały algorytm dodawania zbioru.

ZbiorNazw& ZbiorNazw::operator + (const ZbiorNazw& s) const
{
	ZbiorNazw *x = new ZbiorNazw("suma");	//stworzenie nowego obiektu (zbioru liczbowego) na sumę
	int ilosc=s.n + n;
	string *tab=new string[ilosc];		//utworzenie dodatkowej tablicy na elementy pierwszego zbioru, 
										//niepowtarzające się w drugim
	int q=0;
	int p=0;
	int j, i, z=0;						//zmienne tymczasowe, używane w pętlach
	for (i=0; i<ilosc; i++)
		tab[i]="cos";
	for (i=0; i<n; i++)
	{
		for(j=0; j<s.n; j++)
		{
			if(S[i]==s.S[j])
			{
				ilosc--;			//pętla licząca ilość elementów niepowtarzających się w obu zbiorach
			}
		}
	}
	for (j=0; j<s.n; j++)
	{
		p=0;
		for(i=0; i<n; i++)
		{
			if(S[i]==s.S[j])
			{
				p++;
			}
		}
		if (p==0)				//pętla zapisująca do tymczasowej tablicy elementy drugiego zbioru,
								//niepowtarzające się w pierwszym
		{
			tab[q]=s.S[j]; 
			q++;
		}	
	}
	x->n=ilosc;
	x->S = new string[ilosc];	//utworzenie tablicy na sumę 	
	for (i=0; i<n; i++)
		x->S[i]=S[i];			//wpisanie do tymczasowej tablicy wszystkich elementów pierwszego zbioru
	for (i=n, q=0; i<ilosc; i++, q++)
		x->S[i]=tab[q];			//wpisanie do tymczasowej tablicy tych elementów tablicy tymczasowej
	delete []tab;				//usunięcie tymczasowej tablicy z pamięci
	return *x;
}

Proszę o jakieś wskazówki w rozwiązaniu problemu. Forma programu jest narzucona z góry, więc nie mogę stosować innych rozwiązań.

0
ZbiorNazw x("suma");
...
return x;

Musisz koniecznie dorobić konstruktor kopiujący i z bardzo dużym prawdopodobieństwem operator przypisania.

0

Jest stworzony operator przypisania.

ZbiorNazw& ZbiorNazw::operator = (ZbiorNazw& s)
{
	if(&s == this) 
		return *this;	// gdy obiekty takie same, zwracamy zbiór
	n = s.n;			//w przeciwnym razie ustalamy liczbę elementów
	strcpy(nazwa, s.nazwa);
	delete [] S;
	S = new string[n];	//wpisujemy poszczególne elementy do tablicy
	for(int i = 0; i < n; i++) 
		S[i]=s.S[i];	
	return *this;
}

Zaraz dorobię konstruktor kopiujący, bo faktycznie w tej klasie zapomniałem.

0

Utworzenie konstruktora kopiującego nic nie zmienia.

0

Konstruktor kopiujący:

ZbiorNazw::ZbiorNazw(const ZbiorNazw &s)
{
	n=s.n;
	strcpy(nazwa, s.nazwa);
	if(S)
		for(int i=0; i<n; i++) S[i]=s.S[i];		//utowrzenie kopii całego obiektu
	else
		n=0;
} 

W operatorze + nic nie zmieniłem. A wywoływany jest w klasie dialogowej, mniej więcej tak:

if (suma_nr)
{
zapisz << "Suma zbiorów: "<< suma_nr_pierw << " oraz " << suma_nr_drugi << ": "
<< zbiory[suma_nr_pierw-1]+zbiory[suma_nr_drugi-1];
}

i gdzieś tam wyżej jest

ZbiorNazw *zbiory = new ZbiorNazw [LiczbaZbiorow];

Zmienne LiczbaZbiorow jest wczytywana z pliku. Mogę jeszcze dodać, ze taka sama sytuacja jest z operatorami * i -.

0

A gdzie przydzielasz pamięć pod S ?

0

Faktycznie nie dopisałem jednej linijki :)

ZbiorNazw::ZbiorNazw(const ZbiorNazw &s)
{
	n=s.n;
	strcpy(nazwa, s.nazwa);
	S = new string [n];
	if(S)
		for(int i=0; i<n; i++) S[i]=s.S[i];		//utworzenie kopii całego obiektu
	else
		n=0;
} 

Niestety program dalej łapie freeza po wywołaniu operatora +.
Ciekawe jest to, że w takiej formie:

ZbiorNazw& ZbiorNazw::operator + (const ZbiorNazw& s) const
{
	ZbiorNazw *x = new ZbiorNazw("suma");	//stworzenie nowego obiektu (zbioru liczbowego) na sumę
	int ilosc=s.n + n;
	string *tab=new string[ilosc];		//utworzenie dodatkowej tablicy na elementy pierwszego zbioru, 
										//niepowtarzające się w drugim
	int q=0;
	int p=0;
	int j, i, z=0;						//zmienne tymczasowe, używane w pętlach
	for (i=0; i<n; i++)
	{
		for(j=0; j<s.n; j++)
		{
			if(S[i]==s.S[j])
			{
				ilosc--;			//pętla licząca ilość elementów niepowtarzających się w obu zbiorach
			}
		}
	}
	for (j=0; j<s.n; j++)
	{
		p=0;
		for(i=0; i<n; i++)
		{
			if(S[i]==s.S[j])
			{
				p++;
			}
		}
		if (p==0)				//pętla zapisująca do tymczasowej tablicy elementy drugiego zbioru,
								//niepowtarzające się w pierwszym
		{
			//tab[q]=s.S[j]; 
			q++;
		}	
	}
	x->n=ilosc;
	x->S = new string[ilosc];	//utworzenie tablicy na sumę 	
	for (i=0; i<n; i++)
		x->S[i]=S[i];			//wpisanie do tymczasowej tablicy wszystkich elementów pierwszego zbioru
	for (i=n, q=0; i<ilosc; i++, q++)
		x->S[i]=tab[q];			//wpisanie do tymczasowej tablicy tych elementów tablicy tymczasowej
	delete []tab;				//usunięcie tymczasowej tablicy z pamięci
	return *x;
}

Nic się nie zawiesza, choć nie wykonuje wszystkiego czego trzeba.Wystarczy usunąć linijkę: //tab[q]=s.S[j];
Zauważyłem jeszcze jedno, za każdym razem jak program się sypie zatrzymują się gdzieś w plikach bibliotecznych związanych z wielkością bufora przy stringach.

0

Bo zignorowałeś to:

_13th_Dragon napisał(a):
ZbiorNazw x("suma");
...
return x;
0

W jakim sensie ? Możesz napisać coś więcej ?
Ciekawostka jest taka, ze identyczny operator z ta różnicą, że typ tablicy "tab" jest double, dla zbioru liczbowego działa poprawnie.

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