Funkcje, przekazywanie przez referencje.

0

Witam,

Mam takie zadanie:

Na dysku jest plik, gdzie dane są zapisane w takim formacie

4

11 22 33 44

3

11 222 22

gdzie, pierwsza liczba określa ilość liczb w pierwszym ciągu, następnie są liczby z tego ciągu, później liczba określająca ilość liczb w drugim ciągu i poniżej te liczby. Mam je odczytać z pliku, sprawdzić czy liczby w ciągu się powtarzają oraz dać na wyjście ile liczb się powtórzyło i je wypisać np.

2

11

22

Napisałem taki kod:

 
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void otworz(ifstream &file)
  {
   while(true)
     {
      string nazwa_pliku;
			
	  cout << "Podaj nazwe pliku : ";      
	  getline(cin,nazwa_pliku);
      file.open(nazwa_pliku.c_str());
	  if(file.is_open()) return;
      file.open((nazwa_pliku+".txt").c_str());
	  if(file.is_open()) return;
      cout<<"Podana nazwa pliku jest nieprawidłowa! Plik nie istnieje"<<endl;
     }
  };


unsigned odczyt (ifstream &file, int &m, int &n)
{
	int i;
	file >> m;
	unsigned int *T_1 = new unsigned int [m];
			
			for (i=0; i<=m; i++)
			{
				file >> T_1[i];									
			};
			
			file >> n;	
	unsigned int *T_2 = new unsigned int [n];
			
			for (i=0; i<=n; i++)
			{
				file >> T_2[i];
			};	
};

void porownaj (ifstream &file, int &m, int &n, unsigned *T_1, unsigned *T_2)
{
	int a,b,c,liczba_powtorzen;
	unsigned int *T_3= new unsigned int [m]; 

	liczba_powtorzen=0;

	for (a=0; a<=m; a++)
	{
		for(b=0; b<=n; b++)
		{
			if (T_1[a] == T_2[b])
				for (c=0; c<liczba_powtorzen || T_2[c] == T_3[liczba_powtorzen]; c++)
				{
					if (T_2[c] != T_3[liczba_powtorzen])
					T_2[c] = T_3[liczba_powtorzen];
				};
		};
	};
	cout<<"liczba powtorzen to: "<<liczba_powtorzen;
};

int main()
{
	int m,n;
	ifstream file;
	
	otworz(file);
	odczyt(file,m,n);
	porownaj(file,m,n);
	
	getchar();
	getchar();
	return 0;
}

Zamieszałem się jednak kompletnie w przekazywaniu zmiennych pomiędzy funkcjami, jak to rozpisać, żeby działało?

Z góry dzięki za pomoc,

0
  1. nie przekazuj prymitywow przez referencje chyba że jest jakiś cel
  2. po klamrach funkcji nie daje się srednika
  3. funkcje wczytujace powinny zwracać wskaźnik do wczytanej tablicy który potem przekażesz tam gdzie robisz porównanie
  4. wszędzie robisz błąd off-by-one bo tablicą n-elementowa ma elementy o indeksach od 0 do n-1 a nie do n
0

to samo czytane z wejscia:
http://ideone.com/Y8uJdS

tu z pliku (dlatego runtime error):
http://ideone.com/EqEMsW

dziala tylko dla poprawnych danych wejsciowych

0

krwq dzięki za napisanie programu. Mam jednak wykonać dwa założenia do programu, w sumie mój błąd powinienem napisać o nich od razu.

Otóż:

  1. Elementy na wyjściu nie mogą się powtarzać,
  2. Kolejność w ciągu wyjściowym musi być zgodna z kolejnością ich wystąpień w pierwszym ciągu danych wejściowych.

czyli jak mam w pliku np.

5
1 3 2 1 2
7
2 4 3 3 2 1 1

to mam dostać na wyjście:

liczby powtarzające się: 3
1
3
2

Nie wiem jak to zmodyfikować samemu, bo do końca nie potrafię zrozumieć kodu.

0

Uparcie staram się jeszcze poprawić swój własny projekt według rad kolegi Shalom. Poprawiłem punkty 1,2,4 (tak mi się wydaje przynajmniej). Nadal jednak nie daje rade z punktem 3, czyli jak poprawnie to przekazać między funkcjami. Byłbym bardzo wdzięczny, gdyby ktoś to rozpisał tak jak ma być zrobione.

EDIT:

Niby się kompiluje, ale po uruchomieniu dostaje błąd:

"Invalid allocation size: 4294967295 bytes."

W czym problem?

 
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void otworz(ifstream &file)
  {
   while(true)
     {
      string nazwa_pliku;
			
	  cout << "Podaj nazwe pliku : ";      
	  getline(cin,nazwa_pliku);
      file.open(nazwa_pliku.c_str());
	  if(file.is_open()) return;
      file.open((nazwa_pliku+".txt").c_str());
	  if(file.is_open()) return;
      cout<<"Podana nazwa pliku jest nieprawidłowa! Plik nie istnieje"<<endl;
     }
  }


unsigned odczyt (ifstream &file, int m, int n, unsigned int *T_1, unsigned int *T_2)
{
	int i;
	file >> m;
	

	cout <<"Wartosci pierwszego ciagu : "<<endl;
			
			for (i=0; i<=m-1; i++)
			{
				file >> T_1[i];	
				cout<<T_1[i]<<endl;
			};
			
		cout<<"Wartosci drugiego ciagu :"<<endl;
			file >> n;	
	
			
			for (i=0; i<=n-1; i++)
			{
				file >> T_2[i];
				cout<<T_2[i]<<endl;
			};	
			return 0;
}

void porownaj (ifstream &file, int m, int n, unsigned *T_1, unsigned *T_2)
{
	int a,b,c,liczba_powtorzen;
	unsigned int *T_3= new unsigned int [m-1]; 

	liczba_powtorzen=0;

	for (a=0; a<=m-1; a++)
	{
		for(b=0; b<=n-1; b++)
		{
			if (T_1[a] == T_2[b])
				for (c=0; c<liczba_powtorzen || T_2[c] == T_3[liczba_powtorzen]; c++)
				{
					if (T_2[c] != T_3[liczba_powtorzen])
					T_2[c] = T_3[liczba_powtorzen];
				};
		};
	};
	cout<<"liczba powtorzen to: "<<liczba_powtorzen;
}

int main()
{
	int m,n;
	ifstream file;

	m=0,n=0;

	  unsigned int *T_1 = new unsigned int [m];
	  unsigned int *T_2 = new unsigned int [n];

	otworz(file);
	odczyt(file,m,n,T_1,T_2);
	porownaj(file,m,n,T_1,T_2);
	
	getchar();
	getchar();
	return 0;
}
0

Ech szkoda słów. Zrób JEDNĄ funkcje "wczytaj" bo przecież wczytywanie obu tablic jest IDENTYCZNE. Niech ta funkcja zwraca tablicę którą wczyta (polecam też ZAALOKOWAĆ gdzieś pamięć na tą tablicę...)
Jeśli funkcja ma w sygnaturze N argumentów to musisz do niej tyleż argumentów podać. To nie jest język funkcyjny gdzie mozesz się bawić w jakis currying, a przynajmniej nie w ten sposób.

0
for (i=0; i<=m-1; i++)
for (i=0; i<m; i++)

będzie czytelniej.

unsigned odczyt (ifstream &file, int m, int n, unsigned int *T_1, unsigned int *T_2)

co to za tajemnicze T_1 i T_2, skoro w wywołaniu ich nie podajesz?:

odczyt(file,m,n);
0

ludzie to maja problemy:
sposob 1
http://ideone.com/YoZspd (na plikach)
http://ideone.com/MKvtne (z wejscia)

sposob 2
http://ideone.com/tBuWLX (na plikach)
http://ideone.com/icDYxO (z wejscia)

0

Poprawiony jeszcze raz kod, poprawnie odczytuje z pliku i porównuje. Po dodaniu funkcji zapisz wysypuje błąd alokacji pamięci, gdzie jest błąd?

 
#include <iostream>
#include <fstream>
#include <string>
 
using namespace std;
 
void otworz(ifstream &file)
  {
   while(true)
     {
      string nazwa_pliku;
 
	  cout << "Podaj nazwe pliku : ";      
	  getline(cin,nazwa_pliku);
 
 
	  file.open(nazwa_pliku.c_str());
	  if(file.is_open()) return;
      file.open((nazwa_pliku+".txt").c_str());
 
	  if(file.is_open()) return;
      cout<<"Podana nazwa pliku jest nieprawidłowa! Plik nie istnieje"<<endl;
     };
}
 
unsigned *odczytaj_porownaj(ifstream&file, int &lpowtorek)
{
	int i,m,n;
	lpowtorek=0;
	bool powtorka;
	unsigned *T_3,*T_1,*T_2;
 
        file >> m;
        T_1 = new unsigned int [m-1];
 
                        for (i=0; i<=m-1; i++){
                                file >> T_1[i];                                                                        
                        };
 
                        file >> n;        
        T_2 = new unsigned int [n-1];
 
                        for (i=0; i<=n-1; i++){                        
                                file >> T_2[i];
                        };   
 
		T_3 = new unsigned int [(m<n) ? m-1 : n-1];
 
 
 
		for (i=0; i<=m-1; i++){
			for (int i = 0; i < m; ++i)	{	
				for (int j = 0; j < n; ++j)
					if (T_1[i] == T_2[j]) {		
						powtorka = false;		
							for (int k = 0; k < lpowtorek && !powtorka; ++k) 
								if (T_1[i] == T_3[k])							
									powtorka = true;
										if (!powtorka)	
											T_3[lpowtorek++] = T_1[i];
											};
												};
													}; 
		cout<<"Liczba powtorek : "<<lpowtorek<<endl;
		for(i=0; i<lpowtorek; i++){		
			cout<<T_3[i]<<endl;
		};
 
return T_3;
}
 
void zapisz_wynik(int lpowtorek, unsigned int *T_3) {
	ofstream file;
	string nazwa_pliku2;
 
	cout << "Podaj nazwe pliku : ";      
	cin >> nazwa_pliku2;
 
	file.open(nazwa_pliku2);
 
    file << lpowtorek << endl;
	for (int i = 0; i < lpowtorek; ++i)
	file << T_3[i] << " ";
 
}
 
int main()
{
	ifstream plik;
	int lpowtorek;
 
	unsigned *ciag = odczytaj_porownaj(plik,lpowtorek);
 
	otworz(plik);
	odczytaj_porownaj(plik,lpowtorek);
	zapisz_wynik(lpowtorek,ciag);
 
	delete [] ciag;
	getchar();
	return 0;
}
0

To uruchom pod debugerem i zobacz co się dzieje. Mamy to zrobić za ciebie?

1

C++11

#include <iostream>
#include <iterator>
#include <algorithm>
#include <set>
 
std::set<int> read(std::istream& is) {
    std::set<int> set;
    int count;
    is >> count;
    std::copy_n(std::istream_iterator<int>(is), count, std::inserter(set, set.end()));
    return set;
}
 
int main() {
    std::set<int> s1 = read(std::cin);
    std::set<int> s2 = read(std::cin);
    std::set<int> result;
    std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(result, result.end()));
    std::cout << "Powtarza sie " << result.size() << " liczb\n";
    std::copy(result.begin(), result.end(), std::ostream_iterator<int>(std::cout, "\n"));
}

http://ideone.com/4DUOSa

Edit Dla czytania z pliku pierwsze dwie linijki w main() należy zamienić na:

std::ifstream fin("plik.txt");
if (!fin.is_open()) {
    std::cerr << "Nie mozna otworzyc pliku\n";
    return 1;
}
std::set<int> s1 = read(fin);
std::set<int> s2 = read(fin);
fin.close();

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