[C++] Sortowania - program się sypie


(Claire) #1

Witam :) 

Moje C++ narazie raczkuje, więc proszę Was o pomoc.

Poniższy program wysypuje mi się w momencie generowania tablicy. Co jest źle?

#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <time.h>

using namespace std;

class ciag
{
	int n;
	int* tab;
public:
	ciag() : n(0) {};
	ciag(int a) : n(a) 
	{
		tab=new int [a];
	};
	~ciag()
	{
		free (tab);
	}

	friend istream& operator>> (istream&, ciag&);
	friend ostream& operator<< (ostream&, ciag&);

}A, B, C, D;

istream& operator>> (istream &in, ciag &A)
{
	int a;
	cout << "Podaj dlugosc ciagu: ";
	in >> A.n;
	cout << endl << "Czy chcesz, aby program wygenerowal ciag? 1/0 ";
	cin >> a;
	if(a==0)
	{
		cout << "Podaj wyrazy ciagu: ";
		for(int i=0; i<A.n; i++)
		{
			cout << "A[" << i+1 << "] = ";
			in >> A.tab[i];
			cout << endl;
		}
	}
	else
	{
		srand((unsigned)time(NULL));
		for(int i=0; i<A.n; i++)
			{
				A.tab[i]=(rand()%100);
				in >> A.tab[i];
			}
	}
	return in;
}

ostream& operator<< (ostream &out, ciag &A)
{
	if(A.n>0)
	{
		out << "|";
		for(int i=0; i<A.n-1; i++)
		{
			out << A.tab[i] << ", ";
		}
		out << A.tab[A.n-1] << "| " << endl;
	}
	else 
	{
		out << "Ciag zerowy";
	}
	return out;
}

int main()
{
	cin >> A;
	cout << A;
	system("pause");
}

(Copycona) #2

Jak new[], to nie free, tylko delete[].

 

Każda instancja tej klasy, która została zadeklarowana wykonała konstruktor domyślny. Ten u Ciebie do zmiennej "n" wpisał 0, natomiast "tab" nadal jest niezainicjalowane.

 

Sama modyfikacja składowej n nic tu nie daje, gdyż nie wiąże się to z przydzieleniem pamięci na ciag. Nadal składowa "tab" jest niezainicjalizowana. Dalej w kodzie piszesz po pamięci, której nie masz, w miejsce zupełnie losowe.


(Claire) #3

Ok, zmieniłam to wszystko i cin, cout działa, ale nadal nie losuje mi ciągu. Co teraz? 

#include <iostream>
#include <cmath>
#include <time.h>
#include <math.h>

using namespace std;

class ciag
{
	int n;
	int* tab;
public:
	ciag() : n(0) 
	{
		tab=new int [n];
	};
	
	
	friend istream& operator>> (istream&, ciag&);
	friend ostream& operator<< (ostream&, ciag&);

}C, D;

istream& operator>> (istream &in, ciag &A)
{
	int a;
	cout << "Podaj dlugosc ciagu: ";
	cin >> A.n;
	cout << endl << "Czy chcesz, aby program wygenerowal ciag? 1/0 ";
	cin >> a;
	if(a==0)
	{
		cout << "Podaj wyrazy ciagu: ";
		for(int i=0; i<A.n; i++)
		{
			cout << "A[" << i+1 << "] = ";
			in >> A.tab[i];
			cout << endl;
		}
	}
	else
	{
		srand((unsigned)time(NULL));
		for(int i=0; i<A.n; i++)
			{
				A.tab[i]=(rand()%100);
				in >> A.tab[i];
			}
	}
	return in;
}

ostream& operator<< (ostream &out, ciag &A)
{
	if(A.n>0)
	{
		out << "|";
		for(int i=0; i<A.n-1; i++)
		{
			out << A.tab[i] << ", ";
		}
		out << A.tab[A.n-1] << "| " << endl;
	}
	else 
	{
		out << "Ciag zerowy";
	}
	return out;
}


int main()
{
	cin >> D;
	cout << D;
	system("pause");
	return 0;
}

(xm2) #4

Generujesz ciąg w ten sposób:

for(int i=0; i<A.n; i++)
{
	A.tab[i]=(rand()%100);
	in >> A.tab[i];
}

Druga linia nie jest poprawna i przedewszystkim zbędna. Zakomentować i ma działać.

 

BTW Kodowanie takiej logiki w przeciążeniu operatora jest złem i trochę brakuje logiki, żeby zakopać w niej generator ciągu. Lepiej wynieść to na zewnątrz. Chyba, że tak Wam kazali, ale jeżeli tak Wam kazali, to jest mi przykro z tego powodu :frowning:


(Copycona) #5

No raczej nie. Przecież problem z pisaniem po pamięci której nie ma nadal występuję.


(Claire) #6

xm2 - skoro przeciążam >>, to zwraca mi właśnie to "in". Inaczej co ma zwrócić? Tak mi się wydaje...

177 - W takim razie jak to naprawić?

 

@edit: Zrobiłam funkcję losującą osobno, nie w przeciążeniu >> i jest ok, losuje i wypisuje. 177 - nadal jest błąd?

class ciag
{
	int n;
	int* tab;
public:
	ciag()
	{
		n=0;
		tab=new int [n];
	};

	void wylosuj(int);
	friend istream& operator>> (istream&, ciag&);
	friend ostream& operator<< (ostream&, ciag&);
};

	
void ciag::wylosuj(int a)
{
	n=a;
	srand((unsigned)time(NULL));
		for(int i=0; i<n; i++)
			tab[i]=rand()%100;
}

istream& operator>> (istream &in, ciag &A)
{
	cout << "Podaj dlugosc ciagu: ";
	in >> A.n;

		cout << "Podaj wyrazy ciagu: ";
		for(int i=0; i<A.n; i++)
		{
			cout << "A[" << i+1 << "] = ";
			in >> A.tab[i];
			cout << endl;
		}
	return in;
}

ostream& operator<< (ostream &out, ciag &A)
{
	if(A.n!=0)
	{
		out << "|";
		for(int i=0; i<A.n-1; i++)
		{
			out << A.tab[i] << ", ";
		}
		out << A.tab[A.n-1] << "| " << endl;
	}
	else 
	{
		out << "Ciag zerowy";
	}
	return out;
}

int main()
{
	ciag C, D;
	C.wylosuj(10);
	//cin >> D;
	cout << C;
	system("pause");
	return 0;
}

(Copycona) #7

xm2 nie miał na myśli tego, co ten operator zwraca, tylko co robi.

Najprościej: wykonaj new[] dopiero jak będzie znana długość ciągu. W tym przykładzie ta informacja jest dostępna dopiero po 3 instrukcji w operator>>.


(Claire) #8

Ok, dziękuję Wam.

Mam do tego programu dopisane sortowanie szybkie. Jak widać, programistką nie będę :wink: Ale mam niedługo kolokwium, więc proszę Was jeszcze o zobaczenie co tu się psuje.

void sort(ciag A, int a, int b)
{
	int i, j, x, y;
	i=a; j=b; x=A.tab[(i+j)/2];

	while(i<=j)
	{
		while((i<b)&&(A.tab[i]<x))	i++;
		while((j>a)&&(A.tab[j]>x)) j++;

		if(i<=j)
		{
			y=A.tab[i]; A.tab[i]=A.tab[j]; A.tab[j]=y;
		}

		if(j>a)	sort(A, a, j);
		if(i<b) sort(A, i, b);

	}

}

(kostek135) #9

Prościej ci go będzie zrozumieć, jeżeli rozbijesz go na dwa etapy: podział i wywołanie rekursywne "połówek". Tu masz przykładowy kod: http://www.algorytm.org/algorytmy-sortowania/sortowanie-szybkie-quicksort/quick-1-c.html