wiecie z jakiego powodu kompilator może zgłaszać errory o braku deklaracji dla zmiennych i enumów w funkcji, skoro deklaracje są (w main) i przed wywołaniem funkcji? jak ten error naprawić?
POKAŻ KOD
wiecie z jakiego powodu kompilator może zgłaszać errory o braku deklaracji dla zmiennych i enumów w funkcji, skoro deklaracje są (w main) i przed wywołaniem funkcji? jak ten error naprawić?
Czytając ten fragment, nawet bez kodu powiem ci tak: powodem jest brak deklaracji zmiennych i enumów!
Załóż, że kompilator jest mądrzejszy od ciebie, i rzucany błąd nie jest nieuzasadniony. Zastanów się nad tym.
Poza tym, zmienne zadeklarowane w main nie są w magiczny sposób zadeklarowane na zawsze i wszędzie w każdym miejscu programu. Musisz je przekazać do funkcji.
int KolejnyAkt(string NazwaAktu, char Sciezka)
{
cout << "---------------------------------------------------" << endl;
cout << NazwaAktu << " - ";
if (Sciezka == 'p') cout << Przyborow.strCaloscNazwy << endl;
else if (Sciezka == 's') cout << Slonsk.strCaloscNazwy << endl;
cout << "---------------------------------------------------" << endl;
cout << "Imie i nazwisko bohatera: " << Gracz.strImie << " " << Gracz.strNazwisko << endl;
cout << "Przydomek bohatera: " << Gracz.strPrzydomek << endl;
cout << "Gra po stronie: ";
if (Sciezka == 'p') cout << "Ksiestwa Przyborowskiego" << endl;
else if (Sciezka == 's') cout << "Imperium Slonska" << endl;
cout << "Punkty zycia: " << Gracz.nZycie << endl;
cout << "Stan zdrowia: ";
if (Gracz.nZycie = 100) cout << "Wysmienity" << endl;
else if (Gracz.nZycie > 90 && Gracz.nZycie < 100) cout << "Bardzo dobry" << endl;
else if (Gracz.nZycie > 60 && Gracz.nZycie < 90) cout << "Dobry" << endl;
else if (Gracz.nZycie > 45 && Gracz.nZycie < 60) cout << "Przecietny" << endl;
else if (Gracz.nZycie > 30 && Gracz.nZycie < 45) cout << "Zly" << endl;
else if (Gracz.nZycie > 15 && Gracz.nZycie < 30) cout << "Bardzo zly" << endl;
else if (Gracz.nZycie > 5 && Gracz.nZycie < 15) cout << "Tragiczny" << endl;
else if (Gracz.nZycie <= 5) cout << "Na lozu smierci" << endl;
cout << "Reputacja w ";
if (Sciezka == 's') cout << "Imperium";
else if (Sciezka == 'p') cout << "Ksiestwie Przyborowskim";
cout << ": ";
if (Gracz.repReputacja == REP_OBCY) cout << "obcy" << endl;
if (Gracz.repReputacja == REP_ZNANA_TWARZ) cout << "znana twarz" << endl;
if (Gracz.repReputacja == REP_MIEJSCOWY) cout << "miejscowy" << endl;
if (Gracz.repReputacja == REP_ZOLNIERZ) cout << "zolnierz" << endl;
if (Gracz.repReputacja == REP_DORADCA) cout << "doradca" << endl;
if (Gracz.repReputacja == REP_GENERAL) cout << "general" << endl;
if (Gracz.repReputacja == REP_OFICER) cout << "oficer" << endl;
if (Gracz.repReputacja == REP_SZLACHCIC) cout << "szlachcic" << endl;
if (Gracz.repReputacja == REP_WLADCA) cout << "wladca" << endl;
cout << "---------------------------------------------------" << endl;
}
int main()
{
// bardzo ważne enum'y
enum NASTAWIENIE_DO_GRACZA { NDG_PRZYJAZNE, NDG_WROGIE, NDG_NEUTRALNE };
enum REPUTACJA { RG_OBCY, RG_ZNANA_TWARZ, RG_MIEJSCOWY, RG_ZOLNIERZ, RG_SZLACHCIC, RG_DORADCA, RG_GENERAL, RG_OFICER, RG_WLADCA };
enum OBYWATELSTWO { OB_PRZYBOROW, OB_SLONSK, OB_KOSTRZYN, OB_FRANKFURT, OB_OWNICE, OB_KRZESZYCE };
enum STAN_FIZYCZNY { STF_ZYWY, STF_MARTWY, STF_CHORY };
enum RELACJE_MIEDZYNARODOWE { REL_WOJNA, REL_POKOJ, REL_ZAWIESZENIE_BRONI };
// bardzo ważne klasy definiujące postacie w grze
struct cPOSTAC {
string strImie, strNazwisko, strPrzydomek;
NASTAWIENIE_DO_GRACZA ndgNastawienie;
REPUTACJA repReputacja;
OBYWATELSTWO obObywatelstwo;
STAN_FIZYCZNY stfStan;
unsigned int nZycie;
};
struct cPANSTWO {
string strNazwa, strTytul, strCaloscNazwy;
RELACJE_MIEDZYNARODOWE relRelacje;
unsigned int nMieszkancy, nSurowce;
int nZloto;
};
struct cREGION {
string strNazwa;
OBYWATELSTWO obRegionNalezyDo;
};
// Przypisanie elementom rozgrywki ze struktur odpowiednich wartości DOMYŚLNYCH NA POCZĄTKU
// UWAGA! Wartości będą zmieniać się w trakcie rozgrywki
/* tutaj byłoby te przypisanie wartości, tyle że dość długie jest i nie wiem czy zamieszczać, NA PRZYKŁAD...
Slonsk.strNazwa = "Slonsk";
Slonsk.strTytul = "Imperium";
Slonsk.strCaloscNazwy = "Imperium Slonskie";
Slonsk.relRelacje = REL_POKOJ;
Slonsk.nMieszkancy = 1455;
Slonsk.nSurowce = 52000;
Slonsk.nZloto = 12000000; */
// Wstep do opowiesci
cout << "---------------------------------------------------" << endl;
cout << " ROZMOWA..." << endl;
Gracz.nZycie = 10;
Gracz.stfStan = STF_CHORY;
cout << "ROZMOWA... " << endl;
cout << "" << endl << endl;
// Wybór stronnictwa, decyduje o całej fabule i epilogu
string WyborStronnictwa;
cout << "[Za ktora strona chcesz sie opowiedziec? - DECYZJA NA CALA GRE!]" << endl;
cout << "Przyborow | Slonsk" << endl;
do {
cin >> WyborStronnictwa;
} while (WyborStronnictwa != "Przyborow" && WyborStronnictwa != "Slonsk");
if (WyborStronnictwa == "Przyborow") {
/* Gra po stronie Przyborowa */
Gracz.obObywatelstwo = OB_PRZYBOROW;
cout << "- Pojde z wami, do Przyborowa." << endl;
}
else {
/* Gra po stronie Słońska */
Gracz.obObywatelstwo = OB_SLONSK;
cout << "- Chodzmy do Slonska, zolnierze." << endl;
}
Dalej();
/* SCIEŻKA PRZYBOROWA PROLOG
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
*/
KolejnyAkt("PROLOG", 'p');
if (Gracz.obObywatelstwo == OB_PRZYBOROW)
{
Dalej();
}
// w tworzeniu
getch();
return 0;
}
Error jest uzasadniony. Nie masz enumów REP_* (masz za to RG_* ale one i tak nie będą widoczne w funkcji).
Może zastanów się czy nie byłoby... rozsądniejsze wyjęcie deklaracji enumów poza main(). Pomyśl też o zastosowaniu klas zamiast struktur.
dziękuję za pomoc.
[quote]ogólnie bajzel w tym kodzie jest[/quote]
wiem, muszę się wreszcie nauczyć rozkładać go na pojedyncze pliki .h i .cpp a nie wszytko w jednym...
Kiedy zaczynałem z C też podchodziłem do dzielenia kodu na pliki jak do jeża, ale potem przekonałem się, że nie ma w tym nic magicznego, ani trudnego. Zasada jest bardzo prosta: rozrzucasz kod na pliki .c/.cpp, tworzysz do nich pliki .h z deklaracjami, a w plikach źródłowych które korzystają z obiektów w innych plikach includujesz odpowiedni plik nagłówkowy (.h). To jest cała filozofia.
Przykładowo w Twoim kodzie zrobiłbym tak (zakładając, że nadal chcesz to robić na strukturach, a nie klasach):
- w pliku country.h umieściłbym strukturę przechowującą dane państwa oraz deklaracje funkcji na niej operujących, zaś w pliku coutry.cpp kod tych funkcji,
- analogicznie dla regionu stworzyłbym plik region.h oraz region.cpp,
- analogicznie dla gracza - player.h i player.cpp.
Nie wiem jak chcesz zorganizować akty (i co właściwie one robią), ale można pomyśleć o wydzieleniu także ich.
W ten sposób struktury i funkcje operujące na graczu (np. funkcja zwracająca const char* opisujący stan zdrowia gracza) będą zgrupowane w jednym miejscu, ale będzie można ich używać w kilku.
Budowanie np. krajów można umieścić w pliku country.cpp lub w oddzielnym, jednakże to aż się prosi o wczytywanie danych z zewnątrz. Hardkodowanie takich rzeczy jest zabawne (do pewnego momentu), ale uciążliwe w utrzymaniu i generuje mnóstwo redundantnego kodu. Pomyśl co będzie kiedy zdefiniujesz sobie np. 300 krajów, a w trakcie rozwoju postanowisz dodać jakiś nowy element do struktury... ponad 300 zmian w kodzie potrafi zniechęcić nawet najwytrwalszych (chociaż przy użyciu odpowiednich narzędzi można ten ból zmniejszyć).
ciekawe rady, jestem bardzo wdzięczny.
próbowałem takie pliki stworzyć jednak ciągle mam błędy z niewykrywaniem przez kompilator ich deklaracji. trzeba używac externu?
przepraszam że tak was nękam ale umieszczając w country.cpp danych do struktur musze je wziasc pod main'a, a includujac plik w glownym pliku spowoduje wystapienie dwoch main'ów!
Nie, nie, nie... nie.
Funkcja main() może być tylko jedna. Nie twórz jej innych plikach. Przykład:
Plik country.h:
struct country { ... };
int country_blah(struct country *cn);
const char *country_foo(struct country *cn, int bar);
Plik country.cpp:
#include "country.h"
int country_blah(struct country *cn) { ... }
const char *country_foo(struct country *cn, int bar) { ... }
Plik game.cpp:
#include "country.h"
int main(void)
{
struct country country_foobaria;
int blah;
// ...
blah = country_blah(&country_foobaria);
// ...
printf("Foo in %s is %s\n", country_foobaria.name, country_foo(&country_foobaria, 666));
// ...
}
Potem kompilujesz to tak (przykład dla g++, sprawdź w dokumentacji jak wywoływać Twój kompilator):
g++ -o game country.cpp game.cpp
Albo zgodnie ze sztuką:
g++ -o country.o -c country.cpp
g++ -o game.o -c game.cpp
g++ -o game country.o game.o
ale czemu do game.cpp nie można przypisać np. country.cpp?
jak wartości tam dodane będą uwzględnione w game?
von_ilnicki napisał(a)
ale czemu do game.cpp nie można przypisać np. country.cpp?
W jakim sensie "przypisać"?
von_ilnicki napisał(a)
jak wartości tam dodane będą uwzględnione w game?
Zmieniasz wartości w strukturach, które poprzez wskaźnik (lub referencję) przekazujesz do różnych funkcji. Jeśli nie wiesz co to są wskaźniki/referencje i/lub nie wiesz jak ich używać, to musisz o nich poczytać, bo bez tego w C i C++ można tworzyć tylko proste programy.
W skrócie, dane do funkcji przekazujesz poprzez wartość lub wskaźnik (w C++ możesz też uzyć referencji, które są takimi zubożonymi wskaźnikami). Kiedy przekazujesz przez wartość (np. strukturę) funkcja działa na jej kopii i wszelkie zmiany jakie w niej wprowadzi będą widoczne tylko w obrębie tej funkcji. Wskaźnik natomiast mówi funkcji "wykonaj obliczenia na obiekcie, który znajduje się pod tym adresem w pamięci", zatem funkcja działa bezpośrednio na obiekcie i wszelkie zmiany zachodzą od razu w nim. Po zakończeniu działania funkcji zmiany są też widoczne poza nią.
Przykład:
/* Przekazanie przez wartość */
void add_one_byval(int val)
{
val += 1;
/* w tym miejscu val ma wartość 2, ale po wyjściu z funkcji val jest niszczone wraz z zawartością */
}
/* Przekazanie przez wskaźnik */
void add_one_byptr(int *val)
{
*val += 1;
/* w tym miejscu val wskazuje na wartość 2; po wyjściu z funkcji val jest niszczone */
}
int main(void)
{
int foo;
foo = 1;
add_one_byval(foo);
/* w tym miejscu foo nie zmieniła wartości */
add_one_byptr(&foo);
/* w tym miejscu foo ma wartość 2 */
/* ... */
}
Tak samo robisz ze strukturami, np:
struct foo_s {
int val;
};
void add_one_byptr(struct foo_s *s)
{
s->val += 1;
}
int main(void)
{
struct foo_s foo;
foo.val = 1;
add_one_byptr(&foo);
/* w tym miejscu foo.val ma wartość 2 */
/* ... */
}
Poczytaj o wskaźnikach i referencjach. Z tymi pierwszymi trzeba postępować roztropnie, gdyż nieumiejętne użycie może prowadzić do trudnych do zlokalizowania błędów.