|
Polski Portal COLOBOTa COLOBOT Polish Portal |
 |
C, C#, C++ - Tablica[ZMIENNA][ZMIENNA]
Simbax - 30-05-2011, 19:42 Temat postu: Tablica[ZMIENNA][ZMIENNA] Natknąłem się na malutki problemik. Mam już napisaną całą grę w kółko i krzyżyk. Wykonałem (bardzo trudne wg. tutoriala) ćwiczenie, żeby móc zmienić rozmiar planszy za pomocą stałej w pliku nagłówkowym.
Teraz chciałbym zrobić tak, żeby użytkownik sam na początku ustalał ten rozmiar. I tu pojawia się problem. Rozmiar jest stałą. Zapytacie - to co za problem zrobić z niego zwykłą zmienną? Otóż taki problem, że ta zmienna jest potrzebna do ustalenia rozmiaru tablicy dwuwymiarowej, a rozmiar tablicy musi być... stały.
Prościej:
Na początku programu chce się spytać o rozmiar planszy do gry. Musi to być zmienna.
cin wywala błąd, bo rozmiar planszy jest stałą.
Robię z tej stałej zmienną.
PewnaTablica[RozmiarPlanszy][RozmiarPlanszy] <- błąd! Rozmiar tablicy musi być stałą!
I co ja mam zrobić z tym, zdaje mi się nierozwiązywalnym, problemem? Może to dla was błahe, ale ja się uczę jeszcze
Raptor - 30-05-2011, 21:14 Temat postu: Re: Tablica[ZMIENNA][ZMIENNA]
Simbax napisał/a: | Może to dla was błahe, ale ja się uczę jeszcze |
Dla mnie nie jest to wcale błahe. I tak jesteś na bardziej zaawansowanym poziomie, niż ja...
krzys_h - 30-05-2011, 21:14
Polecam lekturę dotyczącą dynamicznej allokacji pamięci. W wolnej chwili może dam jakiś przykładzik.
Simbax - 30-05-2011, 21:54
To ma związek ze wskaźnikami? Jeszcze daleka droga zanim dojdę do rozdziału o nich... Cóż... Będę wdzięczny za przykład.
adiblol - 30-05-2011, 22:37
Kod: | int width, height;
puts("Podaj szerokosc i wysokosc oddzielone spacja.");
scanf("%i %i", &width, &height);
T* tab = (T*)malloc(sizeof(T)*width*height);
#define tab2d(x, y) (tab[(x)+(y)*width])
|
Pod T podstawiamy typ tablicy.
Użycie:
Kod: |
tab2d(0, 0) = jakas_zmienna;
if (tab2d(666, 1337) == jakas_inna_zmienna) poraz_uzytkownika_pradem();
|
Oczywiście można to zrobić lepiej na klasach.
Simbax - 31-05-2011, 16:59
ERROR '(typ ENUM)' does not define this operator or a conversion to a type acceptable to the predefined operator
Chyba sobie podziękuje. Taka drobna modyfikacja, a tyle problemów...
adiblol - 31-05-2011, 18:22
Simbax napisał/a: | ERROR '(typ ENUM)' does not define this operator or a conversion to a type acceptable to the predefined operator | Nie podałeś w której linii.
Simbax - 31-05-2011, 19:41
W takiej, w której chcę użyć tablicy ;P
(pętle for)
g_aPlansza[i][j] = FLD_EMPTY; //błąd.
W dodatku podkreśla drugi nawias kwadratowy "No operator "[]" matches these operands". I taki błąd jest jeszcze w kilkunastu innych linijkach, w których używam tablicy.
Myślałem, że dałoby radę zrobić tak, żebym nie musiał zmieniać reszty kodu. Zresztą użycie tablica(x, y) też wywołuje błąd w kompilacji
Więc jak użyć tej tablicy w linijce takiej jak ta:
Kod: | if (g_aPlansza[uY][uX] == FLD_EMPTY) g_aPlansza[uY][uX] = static_cast<FIELD>(g_AktualnyGracz); |
Po zmianie nadal jest błąd:
Kod: | if (g_aPlansza(uY, uX) == FLD_EMPTY) g_aPlansza(uY, uX) = static_cast<FIELD>(g_AktualnyGracz); |
A najlepiej to daje kod źródłowy, bo już nie wyrabiam z tym...
http://dl.dropbox.com/u/16682532/CrossCircle.zip
adiblol - 31-05-2011, 20:20
Simbax napisał/a: | bo już nie wyrabiam z tym | A w Minecrafcie wychodzi Ci wszystko od razu? Nie poddawaj się.
Berserker - 31-05-2011, 20:49
Kod: | srand(time(NULL));
int x = rand()%5+1;
int y = rand()%5+1;
Label1->Caption = x;
Label2->Caption = y;
AnsiString **w;
*w = new (AnsiString*)[y];
for(int i = 0; i < y; i++) w[i] = new AnsiString[x];
int a, b;
for(a = 0; a < y; a++) for(b = 0; b < x; b++) w[a][b] = "LOL "; |
C++ Builder mi kompiluje, zamiast AnsiString wpisz sobie inny typ.
Swoja droga dziwny problem, pamietam, ze Dev-Cpp kompilowal mi zwykle tablice ze zmiennym rozmiarem bez problemu, tylko nie mozna bylo przy deklaracji odrazu nadawac wartosci.
Simbax - 31-05-2011, 21:19
Ech. Na razie daje sobie z tym spokój. Potrzebuję większej wiedzy żeby to wszystko ogarnąć.
adiblol napisał/a: | Oczywiście można to zrobić lepiej na klasach. |
A więc lecę się dalej uczyć.
konrad-fligier@wp.pl - 17-06-2011, 23:47
(też robiłem kółko i krzyżyk - sam)
A tak trochę inaczej.
Mi działa takie coś:
Kod: |
const int zmienna=10;
tab[zmienna+2][zmienna+1];
|
(Potrzebowałem takie coś w jednym programie)
Wiec czy zadziała to coś:
Kod: |
const int zmienna=0;
int a;
cin>>a;
tab[zmienna+a];
|
Berserker - 18-06-2011, 01:50
Nie zadziala.
adiblol - 18-06-2011, 14:50
Simbax napisał/a: | PewnaTablica[RozmiarPlanszy][RozmiarPlanszy] <- błąd! Rozmiar tablicy musi być stałą! |
A do stałej nie można zapisywać. No chyba że się uprzesz i użyjesz wskaźników ale wtedy cuda się będą działy...
Simbax - 18-06-2011, 14:59
Dałoby się wykorzystać dynamiczne tablice? Kiedyś takiego czegoś użyłem, tylko nie pamiętam w jakim celu. I jak Właściwie to w ogóle nie rozumiałem jak tamten kod działał, ale dobra...
Berserker - 18-06-2011, 15:26
Ja wlasnie dalem przyklad z dynamicznymi tablicami
Phitherek_ - 10-07-2011, 23:07
Hmmm... Postaram się prosto napisać, jak stworzyć dwuwymiarową tablicę dynamiczną. Piszę na sucho bez sprawdzania, więc mogę coś pomylić, bo dawno już tego nie używałem... Kod jest w C++:
Kod: |
//...
int** tab = NULL; // Tworzę wskaźnik na wskaźnik na int, na razie pusty;
int x, y; // Rozmiar tablicy x*y.
cin >> x >> y; // Wprowadzenie rozmiaru;
tab = new int*[x]; // Tworzę tablicę wskaźników o rozmiarze x.
for(int i = 0; i < x; i++) {
tab[x] = new int[y];
}
// Powyższa pętla tworzy drugi wymiar tablicy o rozmiarze y.
//...
|
Jeżeli nigdzie się nie pomyliłem, to powyższy kod tworzy dynamiczną tablicę dwuwymiarową o rozmiarze x*y, przy czym x i y wprowadza użytkownik z klawiatury. Tak stworzonej tablicy można potem używać tak jak tablicy statycznej - różnica jest w tym, że rozmiar może być zmienną, a nie stałą.
Mam nadzieję, że pomogłem.
Simbax - 11-07-2011, 12:30
Dzięki wszystkim za pomoc. Już powolutku rozkminiam OOP i wskaźniki. Na pewno każdy z waszych programów działa, tylko nie umiem ich wykorzystać :<
@up Bardzo ładnie, a teraz powiedz mi jak mam teraz taką tablicę wsadzić w plik nagłówkowy?
Phitherek_ - 11-07-2011, 13:18
Poczytaj sobie o zmiennych globalnych, polecam "Thinking in C++", strona 122 (http://helion.pl/online/thinking/index.html). Ja postaram się jeszcze zaraz napisać jakiś przykład (a tym razem siedzę na Linuxie, więc będzie to sprawdzone).
A oto i obiecany przykład:
dyntable.cpp:
Kod: |
#include <iostream>
#include <cstdlib>
using namespace std;
int** tab = NULL; // Tworzę wskaźnik na wskaźnik na int
void create(int x, int y) { // Funkcja tworząca tablicę x*y
tab = new int*[x];
for(int i = 0; i < x; i++) {
tab[i] = new int[y];
}
return;
}
void init(int x, int y) { // Funkcja inicjalizująca tablicę
for(int i = 0; i < x; i++) {
for(int j = 0; j < y; j++) {
tab[i][j] = 0;
}
}
return;
}
|
dyntable.h
Kod: |
extern int** tab; // Zmienna globalna zawarta w pliku dyntable.cpp
void init(int x, int y); // Funkcja inicjalizująca tablicę
void create(int x, int y); // Funkcja tworząca tablicę x*y
|
tableuse.cpp:
Kod: |
#include <iostream>
#include <cstdlib>
#include "dyntable.h" // Dołączony plik nagłówkowy
using namespace std;
int main() {
int x, y; // Rozmiar tablicy x*y
// Wprowadzenie danych:
cout << "x: ";
cin >> x;
cout << "y: ";
cin >> y;
create(x,y); // Stworzenie tablicy x*y (funkcja z pliku nagłówkowego)
init(x,y); // Inicjalizacja tablicy (funkcja z pliku nagłówkowego)
for(int i = 0; i < x; i++) {
for(int j = 0; j < y; j++) {
cout << "tab[" << i <<"][" << j << "] = " << tab[i][j] << endl; // Wyświetlenie tablicy. Zwróć uwagę, że nie ma w tym programie wzmianki o zmiennej tab, jest to zmienna globalna dołączona przez plik nagłówkowy.
}
}
return EXIT_SUCCESS;
}
|
Kompiluję to poleceniem: Kod: | g++ -o tableuse tableuse.cpp dyntable.cpp | - uwaga, ważne - te dwa pliki trzeba skompilować w ten sposób, to jest tzw. rozłączna kompilacja.
Program w działaniu wygląda mniej więcej tak:
Kod: |
phitherek@stary-kubuntu global_test $ ./tableuse
x: 4
y: 5
tab[0][0] = 0
tab[0][1] = 0
tab[0][2] = 0
tab[0][3] = 0
tab[0][4] = 0
tab[1][0] = 0
tab[1][1] = 0
tab[1][2] = 0
tab[1][3] = 0
tab[1][4] = 0
tab[2][0] = 0
tab[2][1] = 0
tab[2][2] = 0
tab[2][3] = 0
tab[2][4] = 0
tab[3][0] = 0
tab[3][1] = 0
tab[3][2] = 0
tab[3][3] = 0
tab[3][4] = 0
|
Mam nadzieję, że dzięki temu zrozumiesz, jak użyć takiej tablicy w pliku nagłówkowym .
Simbax - 11-07-2011, 14:25
Ooo, dzięki. Wreszcie coś zrozumiałem
Phitherek_ - 11-07-2011, 14:37
Nie ma sprawy, też dzięki temu odświeżyłem trochę moją wiedzę .
adiblol - 11-07-2011, 18:38
A ja wciąż brzydko łączę pliki przez #include "plik.cpp" bez nagłówków. Działa.
Istnieje może jakiś generator kodu żeby nie pisać ręcznie .h?
Phitherek_ - 11-07-2011, 18:49
Hmmm... Szczerze mówiąc to nie wiem, jak na razie nie pracowałem za dużo z plikami nagłówkowymi, bo moje programy są jak na razie małe i jednoplikowe, więc nie interesowałem się... Musiałbyś poszukać...
A co do łączenia plików, to w sumie do zmiennych globalnych niepotrzebne są pliki nagłówkowe, w "Thinking in C++" jest przykład rozłącznej kompilacji bez tego, wystarczy tylko to co jest w pliku nagłówkowym wstawić zamiast tego w pliku, który ma korzystać z tych zmiennych (logiczne, co nie?). Wtedy nie potrzebujesz nawet #include, tylko wystarczy rozłączna kompilacja. Pliki nagłówkowe są bardzo przydatne, jeśli chcesz używać zmiennych i funkcji w wielu plikach (czytaj: w większych projektach albo bardzo modularnych), ale takie małe programiki w ogóle ich nie potrzebują w sumie, tylko więcej roboty z ich pisaniem...
EDIT: A tak swoją drogą to przydałoby się zamknąć temat, skoro problem został rozwiązany .
Simbax - 11-07-2011, 19:31
Wiesz, to jest "programik" z kursu. Właśnie miałem się nauczyć jak korzystać z plików nagłówkowych I tak się zgadzam, to wystarczyłoby mieć w jednym pliku, ale cóż... Uczę się
|
|