Sprawdzenie definicji metod oraz pomysł na funkcję main

0

class Uczestnik
{
private:
char *name; //nazwisko uczesnika
int punkty; //ilosc zdobytych punktow
public:
Uczestnik(char *, int); //konstruktor
Uczestnik(const Uczestnik &); //konstruktor kopiujacy
~Uczestnik(); //destruktor
Uczestnik & operator=(const Uczestnik &); //operator przypisania
void print(ostream &) const; //drukuj dane uczestnika
};

I mam następujące polecenia:
Prócz implementacji metod, napisać operator wyjscia.
Funkcja main ma:
Pierwsza linia ilosc uczestnikow, kolejne linie opisy uczestników. Opis uczestnika składa się z nazwiska i imienia. Funkcja main powinna przeczytać dane oraz umieścić je w tablicy obiektót typu uczestnik

Nie jestem pewien czy dobrze zdefiniowałem metody. Ale nie mam pojecia jak napisać funkcje main.

#include <iostream>

#ifndef PLIK_H_
#define PLIK_H_

class Uczestnik
{
private:
	char *name; //nazwisko uczesnika
	int punkty; //ilosc zdobytych punktow
public:
	Uczestnik() {}; //konstruktor domyslny
	Uczestnik(char *, int); //konstruktor
	Uczestnik(const Uczestnik &st); //konstruktor kopiujacy
	~Uczestnik(); //destruktor
	Uczestnik & operator=(const Uczestnik &st); //operator przypisania
	void print(std::ostream &os, const Uczestnik & st) const; //drukuj dane uczestnika
};

#endif
#include <iostream>
#include <cstring>
#include "plik1.h"

Uczestnik::Uczestnik(char *, int) //konstruktor
{
	name = new char[30];
	punkty = 0;
	std::cout << "Konstruktor" << std::endl;
}

Uczestnik::Uczestnik(const Uczestnik &st) //konstruktor kopiujący
{
	Uczestnik tab2;
	tab2.
	std::cout << "Konstruktor kopiujacy" << std::endl;
}

Uczestnik::~Uczestnik() //destruktor
{
	delete [] name;
	std::cout << "Dekonstruktor";
}
//metody przeciazajace operatory
//przypisanie obiektu klasy String do innego obiektu tej samej klasy
Uczestnik & Uczestnik::operator =(const Uczestnik &st)
{
	if (this == &st)
		return *this;
	punkty = st.punkty;
	name = new char[30];
	std::strcpy(name, st.name);
	std::cout << "Operator przypisania" << std::endl;
	return *this;
}
//wyprowadzanie ciagu na wyjscie
void Uczestnik::print(std::ostream &os, const Uczestnik & st) const
{
	os << st.name << std::endl;
	os << st.punkty << std::endl;
}
#include <iostream>
#include "plik1.h"
const int MAX = 10;
int main()
{
	using std::cout;
	using std::endl;
	using std::cin;
	
	
	cout << "Podaj ilosc uczestnikow: ";
	int ilosc;
	cin >> ilosc;

	Uczestnik tablica[MAX];
	for (int i = 0; i < ilosc; i++)
	{
	
	}

	cin.get();
	return 0;
}

Prosze o jaką pomoc.

0

Brakuje Ci przeciążenia operatora wejścia dla tej klasy. Jeśli go napiszesz, main stanie się trywialnie proste.

Funkcja przeciążająca operator wejścia może zostać zdefiniowana na dwa sposoby : jednym jest zadeklarowanie jej jako funkcji zaprzyjaźnionej z klasą i napisanie jej poza klasą (tj. jako funkcję "globalną"), drugiego nie pamiętam. Dlatego napiszę to w sposób "pierwszy".

Do sekcji "public" w klasie dopisz :

friend std::istream& operator>>(std::istream&,Uczestnik&);

A w "wolnym kawałku źródła" dopisz funkcję :

std::istream& operator>>(std::istream &input, Uczestnik &ucz)
{
std::cout << "Wpisz imie uczestnika : ";
std::string nazw; // nazwisko uczestnika. do std::string sie najwygodniej wczytuje, pewnie bedziesz musial #include <string> dodac zeby to zadzialalo
if(!(input >> nazw)) // wczytywanie nie powiodlo sie
{
std::cout << "Blad!\n";
return input;
}
std::cout << "Wpisz ilosc zdobytych punktow : ";
int punkty;
if(!(input >> punkty))
{
std::cout << "Blad!\n";
return input;
}
ucz.name = nazw.c_str(); // nie jestem na 100% pewny czy to bedzie dzialac, nie wiem jak dlugo pamiec alokowana przez ta metode jest utrzymywana w pamieci
ucz.punkty = punkty;
return input;
}

Wtedy pętla w main będzie mogła wyglądać mniej więcej tak :

for(int i=0;i<ilosc;++i)
{
std::cout << (i+1) << ". uczestnik :\n";
std::cin >> tablica[i];
}

Oczywiście te pomysły to tylko propozycje, równie dobrze mógłbyś używać do tego metod klasy zwanych setterami (ustawiających wartość danej zmiennej w klasie na wartość przekazaną w parametrze takiej funkcji). Jak jeszcze jakieś pytania to pisz dalej. ;)

0

Dodałem to i prawie wszystko śmiga tylko dwie rzeczy nie.
1.ucz.name = nazw.c_str();
2.to operator wyjścia. nie wypisuje mi nic:( a jak robię na rożne sposoby to są errory.

0
  1. ABSOLUTNIE się tak nie robi. Wartość ta jest jedynie chwilowa i nie wolno z niej korzystać później niż w chwili wywołania. Skopiuj po prostu ten string do nowego char[]
  2. Mial być operator WYJŚĆIA a nie WEJŚCIA
friend ostream& operator<<(ostream& s, Uczestnik& u)
{
  s<<name<<" "<<punkty;
  return s;
}
0

Tak to zrobiłem, ale są błędy ;/

#include <iostream>

#ifndef PLIK_H_
#define PLIK_H_

class Uczestnik
{
private:
	char *name; //nazwisko uczesnika
	int punkty; //ilosc zdobytych punktow
public:
	Uczestnik() {}; //konstruktor domyslny
	Uczestnik(char *, int); //konstruktor
	Uczestnik(const Uczestnik &st); //konstruktor kopiujacy
	~Uczestnik(); //destruktor
	Uczestnik & operator=(const Uczestnik &st); //operator przypisania
	friend std::ostream& operator<<(std::ostream &, const Uczestnik &) const; //drukuj dane uczestnika
	friend std::istream& operator>>(std::istream &, Uczestnik &);//funkcja przeciążająca operator wejścia
};

#endif
#include <iostream>
#include <cstring>
#include <string>
#include "plik1.h"

Uczestnik::Uczestnik(char *, int) //konstruktor
{
	name = new char[30];
	punkty = 0;
	std::cout << "Konstruktor" << std::endl;
}

Uczestnik::Uczestnik(const Uczestnik &st) //konstruktor kopiujący
{
	Uczestnik tab2;
	tab2.
	std::cout << "Konstruktor kopiujacy" << std::endl;
}

Uczestnik::~Uczestnik() //destruktor
{
	//delete [] name;
	std::cout << "Destruktor";
}
//metody przeciazajace operatory
//przypisanie obiektu klasy String do innego obiektu tej samej klasy
Uczestnik & Uczestnik::operator =(const Uczestnik &st)
{
	if (this == &st)
		return *this;
	punkty = st.punkty;
	name = new char[30];
	std::strcpy(name, st.name);
	std::cout << "Operator przypisania" << std::endl;
	return *this;
}
//wyprowadzanie ciagu na wyjscie
std::ostream& operator<<(ostream & os, Uczestnik & st)
{
  os<<name<<" "<<punkty;
  return os;
}

std::istream& operator>>(std::istream &input, Uczestnik &ucz)
{
std::cout << "Wpisz imie uczestnika : ";
std::string nazw; // nazwisko uczestnika
if(!(input >> nazw)) // wczytywanie nie powiodlo sie
{
std::cout << "Blad!\n";
return input;
}
std::cout << "Wpisz ilosc zdobytych punktow : ";
int punkty;
if(!(input >> punkty))
{
std::cout << "Blad!\n";
return input;
}
tab = new char = nazw.c_str();
//ucz.name = nazw.c_str(); // nie jestem na 100% pewny czy to bedzie dzialac, nie wiem jak dlugo pamiec alokowana przez ta metode jest utrzymywana w pamieci
//ucz.name = nazw;
ucz.punkty = punkty;
return input;
}
#include <iostream>
#include "plik1.h"
const int MAX = 10;
int main()
{
	using std::endl;
	std::cout << "Podaj ilosc uczestnikow: ";
    int ilosc;
    std::cin >> ilosc;

    Uczestnik tablica[MAX];
	for(int i=0; i < ilosc; ++i)
	{
		std::cout << (i+1) << ". uczestnik :\n";
		std::cin >> tablica[i];
	}

	
	std::cin.get();
	return 0;
}
0

Nie wiem (jako że w C++ dawno już nie pisałem) czy nie jest wymagane, aby każda funkcja operująca na klasach std::istream i std::ostream zwracała aktualny stan tego strumienia. W takim przypadku Twój print() wyglądałby mniej więcej tak (pamiętaj też o zmianie prototypu tej funkcji w deklaracji klasy) :

std::ostream& print(std::ostream &os, const Uczestnik & st) const
{
        os << st.name << std::endl;
        os << st.punkty << std::endl;
        return os;
}

Co nie zmienia faktu że ja zrobiłbym to na standardowym operatorze wyjścia dla strumienia, czyli << (wydaje mi się to bardziej eleganckim rozwiązaniem). Wtedy funkcja ta przybrałaby taką postać (oczywiście, znowu, po zmianie prototypu w deklaracji klasy i zaprzyjaźnieniu jej) :

std::ostream& operator<<(std::ostream &os, const Uczestnik & st) const
{
        os << st.name << std::endl;
        os << st.punkty << std::endl;
        return os;
}

Co do zamiany std::string na Cstring, czyli char[]...nie wiem co Ci poradzić. Na chłopski rozum najłatwiej byłoby po prostu przekopiować to wszystko element po elemencie, ale to średnio eleganckie rozwiązanie. Jedyne co mi w tym momencie przychodzi do głowy to po prostu wczytanie ciągu znaków prosto z std::cin do tego char[], ale za cholerę nie mogę sobie przypomnieć jak ograniczyć możliwą ich maksymalną ilość (coby uniknąć ewentualnego przepełnienia bufora). Czyli funkcja ta wyglądałaby w takim razie tak :

std::istream& operator>>(std::istream &input, Uczestnik &ucz)
{
std::cout << "Wpisz imie uczestnika : ";
if(!(input >> ucz.name)) // wczytywanie nie powiodlo sie
{
std::cout << "Blad!\n";
return input;
}
std::cout << "Wpisz ilosc zdobytych punktow : ";
int punkty;
if(!(input >> punkty))
{
std::cout << "Blad!\n";
return input;
}
ucz.punkty = punkty;
return input;
}
0
#include <iostream>
#include <cstring>
#include <string>
#include <string.h>
#include "plik1.h"
using namespace std;

Uczestnik::Uczestnik(char * nazwa, int pkt)
{
  name = new char[30]; //alokujesz pamięć
  strncpy(name, nazwa,30); //kopiujesz dane! same sie nie skopiują!
  punkty = pkt;
}

Uczestnik::Uczestnik(const Uczestnik &st) //konstruktor kopiujący
{
  return Uczestnik tab2(st.nazwa,st.pkt);
}

Uczestnik::~Uczestnik() //destruktor
{
  delete [] name; //to trzeba zwalniać!
}

Uczestnik & Uczestnik::operator =(const Uczestnik &st)
{
  if (this == &st)
    return *this;

  delete[] name; // tą pamięć musisz zwolnić!!
  punkty = st.punkty;
  name = new char[30];
  strncpy(name, st.name,30);
  return *this;
}

ostream& operator<<(ostream & os, Uczestnik & st)
{
  os<<st.name<<" "<<st.punkty;
  return os;
}

istream& operator>>(istream& input, Uczestnik &ucz)
{
  string nazw;
  int punkty;
  input>>nazw;

  while(!(input>>punkty))
    {
      cout << "Podaj liczbe!"<endl;
      input.sync();
      input.clear();
    }
  delete [] ucz.name;
  ucz.name = new char[30];
  strncpy(ucz.name,nazw.c_str(),30);
  ucz.punkty = punkty;
  return input;
}

Coś tam moze nie byc do konca tak, bo pisane z palca, nie chciało mi się tego wszystkiego przeklejać. Jak coś nie będzie działać to wstaw na pastebina cały kod w jednym pliku i moze rzuce na to okiem.

0

Dużo błędów jest, nie do okiełznania;/
Został jeden "error C2064: term does not evaluate to a function taking 2 arguments" w metodzie

Uczestnik::Uczestnik(const Uczestnik &st) //konstruktor kopiujący
{
	Uczestnik tab2;
	return tab2(st.name, st.punkty);
}
0

Aj to moja wpadka :P to przeciez konstruktor jest :P

Uczestnik::Uczestnik(const Uczestnik &st)
{
  name = new char[30];
  strncpy(name,st.name,30);
  punkty = st.punkty;
}

A błędów to miałeś multum. A to nie nazwane argumenty w funkcji, a to jakieś inne cuda. Tak się nie programuje! Powinieneś wstawić sama deklarację klasy i sprawdzić czy się kompiluje. Potem dopisać jedną metodę i znów testować. A nie naklepać 200 linii bezsensownego kodu który ciężko poprawić nawet. Jak wstawisz cały kod na pastebina w jednym pliku to łatwiej będzie poprawiac.

0

Na pastebin.pl ? http://pastebin.pl/19478

0

albo na http://pastebin.4programmers.net/ co za różnica? ;]

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