Wczytanie poszczególnych elementów tablicy

0

Mam mały problem. Stworzyłem klasę elementy, w której destruktor tworzy nowe zbiory(tablice dynamiczne). W mainie stworzyłem kilka, wszystko ładnie się wyświetla i mogę przypisywać wartości. Zastanawiam się teraz jak wywowłać poszczególne elementy. Np. chciałbym sprawdzić jakoś wartość ma drugi element zbioru a. Co powinienem wpisać? Miałby ktoś może pomysł gdzie i jak przechowywać ilość elementów w tych zbiorach/tablicach?

main.cpp

#include "stdafx.h"
#include <cstdlib>
#include "Elementy.h"
#include "Zbiory.h"
#include <string>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	Elementy<int> a(3);
	Elementy<string> b(2);
	Elementy<int> c(1);
	Elementy<int> d(2);

	system("pause");
	return 0;
}
#pragma once
#include <iostream>
using namespace std;

template<class typ>class Elementy
{
protected:
	typ *tab;

public:
	Elementy(int=1);
	~Elementy();
	
};

template<class typ> Elementy<typ>::Elementy(int i)
{
	tab = new typ[i];
	cout << "TWORZENIE NOWEGO ZBIORU!" << endl;
	for (int j = 0; j < i; j++)
	{
		cout << "Podaj wartosc elementu zbioru nr " << j + 1 << ": ";
		cin >> tab[j];
	}
}

template<class typ>Elementy<typ>::~Elementy()
{
	delete[] tab;
}
1

Możesz np przeciążyć sobie operator [].

0

.h

	int& operator[](int el);

.cpp

int& Zbiory::operator [](int el)
{ 
	return tab[el]; 
}

i jak w mainie np. piszę pod stworzonym a(3), a[1] to wyskakuje:

Error no operator [] matches these operands
operand types are: Elementy <int> [int]

Dopowiem tylko, że jak naceluję na a, jego typ: Elementy <int> a. Mógłby ktoś pomóc?

1

Skoro trzymasz elementy dowolnego typu, to dlaczego ten operator ma zwracać int?
I skąd się bierze Zbiory? Przecież ta klasa szablonowa to Elementy.

0

Rozpędziłem się. W dalszej części zadania mam różne operacje na tych zbiorach robić w klasie zbiory. No więc przenoszę wszystko do elementów.

typ operator[](unsigned int el);
template<class typ>Elementy<typ>::operator[](unsigned int el)
{
	tab[el];
}

? Teraz nie wyskakuje błąd z typem jednak gdy uruchamiam program wyskakują mi po kolei elementy tablicy do podania niestety przed kolejną utworzoną tablicą nie pojawia się żadna wartość.

0
typ &operator[](unsigned int el);

natomiast przy samej funkcji nie jestem pewien gdzie wstawić &. Mógłbyś pomóc? próbowałem różnie, wciąż nic nie pojawia się na ekranie, a błędów również nie wyrzuca.

1

w funkcji

 return tab[el];
0

Dodałem. Wciąż jednak nic mi nie wyskakuje poza samym tworzeniem tablic. Dodatkowo w liście błędów widnieje 3 razy następujący błąd:

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

0

Pokaż aktualny kod, bo może problem jest gdzie indziej?

0

AlgebraZbiorow.cpp

#include "stdafx.h"
#include <cstdlib>
#include "Elementy.h"
#include "Zbiory.h"
#include <string>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	Elementy<int> a(3);
	cout << "Drugi wyraz: " << a[1];
	Elementy<string> b(2);
	Elementy<int> c(1);
	Elementy<int> d(2);

	system("pause");
	return 0;
}

Elementy.cpp

#pragma once
#include <iostream>
using namespace std;

template<class typ>class Elementy
{
protected:
	typ *tab;

public:
	Elementy(int=1);
	~Elementy();
	typ &operator[](unsigned int el);
};

template<class typ> Elementy<typ>::Elementy(int i)
{
	tab = new typ[i];
	cout << "TWORZENIE NOWEGO ZBIORU!" << endl;
	for (int j = 0; j < i; j++)
	{
		cout << "Podaj wartosc elementu zbioru nr " << j + 1 << ": ";
		cin >> tab[j];
	}
}

template<class typ>Elementy<typ>::~Elementy()
{
	delete[] tab;
}

template<class typ>Elementy<typ>::operator[](unsigned int el)
{
	return tab[el];
}

Błąd pokazuje, że jest w Elementy.h w 35 lini. Jak na niego klikam dwukrotnie przenosi mnie przed ostatnią klamrę za "return tab[e1];" Btw. z konstruktorem wszystko w porządku? Dobrze przypisuję wartości?

1

zamiast

 
template<class typ>Elementy<typ>::operator[](unsigned int el)
{
    return tab[el];
}

daj:

 
template<class typ>
typ &Elementy<typ>::operator[](unsigned int el)
{
    return tab[el];
}

0

Kurcze min. próbowałem tak wcześniej, ale po wypisaniu wartości e[1] nie dałem endl i pewnie nie zauważyłem, że wypisuje, bo się się mi zlało z kolejnym napisem "TWORZENIE NOWEGO ZBIORU!" xDD W każdym razie wielkie dzięki! Pytałem jeszcze czy ktoś miałby jakieś pomysły na przechowywanie wielkości każdego ze zbiorów. Bo teraz będę musiał zrobić operacje na zbiorach jak dodawanie etc. I np. w przypadku dodawania to chciałem zrobić tak, że: tworzę zbiór o ilości elementów równej sumie elementów dodawanych zbiorów odjąć liczbę powtórzeń i do takie tablicy dodaję elementu z obu zbiorów bez powtórzeń(bo bez części wspólnej).

2

Ogólnie strategię należy przemyśleć i dostosować do warunków, jakie się ma. Czasem lepsza będzie lista/kolejka, czasem tablica, czasem lista tablic, czasem złożone struktury. Ogólnie zasada jest taka, że jeśli już robimy ręczną zabawę pamięcią, to należy pamiętać, że lepiej zaalokować troszkę z nadmiarem niż często alokować i zwalniać, bo jest to kosztowne, dodatkowo prowadzi do defragmentacji pamięci, a to w niektórych systemach może boleć.

0

Postanowiłem zacząć od iloczynu zbiorów(części wspólnej), bo przyda mi się przy sumie. Funkcje teraz będę tworzył w nowej klasie Zbiory, która dziedziczy po Elementach.
.h

void operator*(Elementy&);

.cpp

void Zbiory::operator*(Elementy& m, Elementy&b)
{
	Elementy c((sizeof(m) / sizeof(int)));
	int Licz = 0;
	cout << "Elementy czesci wspolnej: ";
	for (int p = 0; p<(sizeof(m) / sizeof(int)); p++)
	for (int o = 0; p < (sizeof(b) / sizeof(int)); o++)
	{
		if (m[p] == b[o])
		{
			c[Licz] = m[p];
			cout << c[Licz] << " ";
			Licz++;
		}
	}
}

Mógłby ktoś mi wytłumaczyć, co jest źle i jak to powinienem rozumieć? Chciałbym na tym przykładzie zrozumieć jak to działa i na następnych operacjach sobie to utrwalić.

0
Elementy c((sizeof(m) / sizeof(int))); 

Obawiam się, że nie zadziała tak jak tego oczekujesz, aczkolwiek mogę się tylko domyślać czego oczekujesz...

0

Chciałem stworzyć tablicę o wielkości jednego ze zbiorów. Obojętnie którego, ponieważ ilość elementów wspólnych nigdy nie będzie większa od ilości elementów mniejszej tablicy. Tutaj sobie akurat wstawiłem wielkość pierwszego zbioru. No i później za pomocą pętli chcę sprawdzić czy któreś są wspólne, jeśli tak dodać do nowo utworzonej tablicy. Ogólnie coś źle skonstruowałem, bo podkreśla mi słowo operator w cpp i mam błąd:

IntelliSense: declaration is incompatible with "void Zbiory::operator*(Elementy<int> &)

1

Wstawiłeś nie wielkość zbioru, a wielkość typu.....

0

Faktycznie. Wpadłem na taki trochę desperacki pomysł. :>
W konstruktorze przypisuję pierwszemu elementowi tablicy wielkość tej tablicy więc tworzę elementów o 1 więcej i zaczynam w pętli przypisywać im wartości od j=1. Czyli np. a[1] to wartość pierwszego elementu bd.
Konstruktor:

template<class typ> Elementy<typ>::Elementy(int i)
{ 
	tab = new typ[i+1];
	tab[0] = i;
	cout << "TWORZENIE NOWEGO ZBIORU!" << endl;
	for (int j = 1; j <= i; j++)
	{
		cout << "Podaj wartosc elementu zbioru nr " << j << ": ";
		cin >> tab[j];
	}
}
void operator*(Elementy&);

Wtedy tutaj wielkością nowej tablicy będzie c(m[0]) i tam odpowiednio zmieniłem zakres działania pętli.

void Zbiory::operator*(Elementy& m, Elementy&b)
{
	Elementy c(m[0]);
	int Licz = 0;
	cout << "Elementy czesci wspolnej: ";
	for (int p = 1; p<=m[0]; p++)
	for (int o = 1; p <=b[0]; o++)
	{
		if (m[p] = b[o])
		{
			c[Licz] = m[p];
			cout << c[Licz] << " ";
			Licz++;
		}
	}
}

Wciąż jednak pozostaje kwestia tego błędu.

0

A nie łatwiej po prostu wprowadzić dodatkowe pole - wielkość?

0

jeśli masz na myśli, że w operatorze to wydaje mi się, że nie, bo jeśli wprowadzę np. 2 a powtórzeń będzie 4 to wynikiem będzie zbiór bez tych elementów, czyli zły. Wracając do tego błędu, byłby ktoś w stanie pomóc?

1

Taka przykładowa propozycja na szybko:

template<class typ>class Elementy
{
protected:
    typ *tab;
    uint16_t usedsize;
    uint16_t fullsize;
public:
    Elementy(int=1);
    ~Elementy();
    uint16_t GetSize()
    {
        return  usedsize;
    }
 
}; 
0

Pierwszy raz się spotykam z typem uint16_t więc wolałbym sobie teraz tym nie zajmować kiedy nie potrafię naprawić operatora*. Przyjrzę się temu bliżej gdy zostanie mi czas. ;)

0

Przeniosłem do klasy Elementy, żeby sprawdzić czy problemem są obiekty klasy Elementy.
template<class typ="typ">
void Elementy<typ>::operator*(Elementy& m, Elementy&b)
{
Elementy c(m[0]);
int Licz = 0;
cout << "Elementy czesci wspolnej: ";
for (int p = 1; p <= m[0]; p++)
for (int o = 1; p <= b[0]; o++)
{
if (m[p] = b[o])
{
c[Licz] = m[p];
cout << c[Licz] << " ";
Licz++;
}
}
}
Teraz wyskakuje mi taki błąd:

C2244: 'Elementy<typ>::operator *' : unable to match function definition to an existing declaration

:(

0

void Elementy<typ>::operator*(Elementy<typ>& m, Elementy<typ>&b)

template<class typ>

void Elementy<typ>::operator*(Elementy<typ>&b)
{
{
    Elementy<typ> c(tab[0]);
[...]
}
 

Dodatkowo chyba chciales cos zwracac?

0

Dalej to samo. :(

0

Pisze z telefonu jak coś, bo prądu nie mam. ;_; No właśnie do tego doszedłem tylko zamiast b miałem m. A no o czasem jak wprowadzam c to zamiast elementy<typ> nie powinno być Elementy<int>? W końcu dopiero tworzę. No w pętli zawarłem, że wypisze je więc nie trzeba chyba nic więcej. Teraz problem kolejny, jak w mainie wymnożyć 2 tablice, a(3)*d(4) prowadzi do błędu kompilacji.

1

Wymnożyć musisz a*d, tylko, że to ci nie wiele da, bo nie zwracasz nigdzie nic - dlatego pytałem o to co chcesz zwrócić. Jeśli 3 tablice, to jeszcze trzeba by dopisać konstruktor kopiujący i operator=. Jako ćwiczenie spoko, ale ja dawno temu zrobiłbym to na wektorze.

0

Zrobiłem oba elementy, błędów nie wywala, mam nadzieję, że jest dobrze. Niestety nie do końca wiem, co co chodzi i jak mam się nimi posłużyć. :(

typ& operator= (typ const& x);
template<class typ>
typ& Elementy<typ>::operator=(typ const& x)
{
	tab = x.tab;
}

Konstruktor kopiujący:

Elementy(const Elementy &tab);
template<class typ> Elementy<typ>::Elementy(const Elementy &t)
{
	tab = new typ[c[0]+1];
	for (int j =1; j <= i; j++)
	{
		tab[i] = typ(t.tab[i]);
	}
}
0

Operator= w tym wypadku musi być taki jak konstruktor kopiujący (tyle, że zwraca *this). No i w konstruktorze kopiującym widzę 2 błędy 1) nie kopiujesz 0 (przecież rozmiar ma być taki sam, wiec powinieneś go skopiować, 2) wartości i, j oraz c[0] są chyba nie teges troszkę...

0

Faktycznie, mam nadzieję, że poprawiłem. Teraz mam po prostu zapisać ad? Właśnie tak zrobiłem i nic mi nie wyskoczyło źle poza tym, że m is undeclared, co w sumie faktycznie ma miejsce, bo przecież w operatorze mnożenia mam "operator(Elementy<typ>&b)" a jak dawałem m jako drugi to nie działało. :(
KK

Elementy(const Elementy &t);
template<class typ> Elementy<typ>::Elementy(const Elementy &t)
{
	tab = new typ[c[0]+1];
	for (int j =0; j <= c[0]; j++)
	{
		tab[j] = typ(t.tab[j]);
	}
}

=

typ& operator= (typ const& t);
template<class typ>
typ& Elementy<typ>::operator=(typ const& t)
{
	tab = new typ[c[0] + 1];
	for (int j = 0; j <= c[0]; j++)
	{
		tab[j] = typ(t.tab[j]);
	}
}

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