Okei, eli koitan täs pistää vanhaa peliä uuteen kuosiin. Ongelma on nyt seuraava:
Olen tehnyt pelin logon tiedostoon fTittle.cpp ja sille headerin fTittle.h. Kyseisessä tiedostossa on funktio fTittle() (joo, en oo hyvä nimeämään...). Nyt kun sitten kutsun fTittle() funktiota, saan virheilmoituksen "cout undecleared (first use in function)". Käytän Dev-C++.
Ainiin, ja koodi:
fTittle.h/.cpp
//Tämä tiedosto sisältää pää ruudun sisällön ja funktiot. Sitä käytetään kun peli käynnistetään. //Tulostetaan logo, jonka jälkeen kysytään haluaako pelaaja pelata vai sammuttaa void fTittle() { cout << " NN NN UU UU KK KK EEEEE SSSSSS II MM MM UU UU"<< endl << " NNNN NN UU UU KK KK EE SS II MMMM MMMM UU UU"<< endl << " NN NN NN UU UU KKKK EEEEE SSSSSS II MM MM MM MM UU UU"<< endl << " NN NNNN UU UU KK KK EE SS II MM MM MM MM UU UU "<< endl << " NN NN UUUU KK KK EEEEE SSSSSS II MM MMM MM UUUU "<< endl << " __________________ " << endl << " |__ _ _ __|" << endl << " | | | | | | " << endl << " | | | | | | " << endl << " | | | | | | " << endl << " __| |_| |_| |__ " << endl << " |__________________|" << endl; }
ja sitten main.ccp
#include <cstdlib> #include <iostream> #include "ftittle.cpp" using namespace std; int main() { fTittle(); //kutsustaan funktiota fTittle() joka piirtää logon system("PAUSE"); return EXIT_SUCCESS; }
Kuten varmaa näette, koitan ny eka ratkaista mitä hel*****ä kone nyt herjaa ennen kuin teen itse käyttöliittymän. Oma tyylini on "tee toiminto->testaa->korjaa->tee seuraava toiminto". Täs tapaukses tää "logo" toiminto ei nyt toimi.
P.S: Ennen kuin unohdan, tän olis tarkoitus toimii tuolla DOS ympäristössä, eli konsolissa tai jotain sinne. Sori huono selostus, ohjelmointi onnistuu muttei termit.
*edit*
Ja koiton jo lisätä #include <iostream> fTittle.h/.cpp, siirtää sen main:tä fTittle:leen, jne. Herja tulee vaikka mikä olis.
Jos nyt oikein ymmärsin, niin tuota namespacea pitää kutsua myös tuolla toisessa tiedostossa.
Otat std:n käyttöön myöhemmin kuin sitä tarvitaan.
Eli joko siirrät sen tuonne ftittle.cpp-tiedoston alkuun tai sitten cout:n eteen kirjoitat std::cout << "tekstiä"; ... jolloinka et tarvitse std-nimiavaruutta, mutta joudut aina kirjoittamaan alkuun tuon std::-pätkän.
Viisaammat osaavat varmasti paremmin neuvoa.
edit. pahus, MIB ehti ensin!
Protip: toisia projektiin kuuluvia .c/.cpp tiedostoja ei #includetata vaan kääntäjälle annetaan ne parametreinä (ilmeisesti) tai antamalla IDE:n hoitaa se (jos sellaista käyttää).
Jeps, testasin tuota mitä sanoin ja hyvin toimii ;)
Kokeilin MIB:in neuvoa.
Kiitti! Nyt pelittää! </huono sanaleikki>
Itse en ole tottunut tuohon namespace, koska kun aikoinani opettelin c++ siitä ei puhuttu mitään. Kai siihen oppii tätä projektia tehdessä :)
@temu92: Kuinkas tuo toimii? Luin kans et toisia .ccp tiedostoja ei kuulu #include, mutta en kyl keksiny miten ne muuten saa toimimaan main funkiossa.
Lue C++-oppaasta asian teoriapuoli ja tutustu koodivinkkeihin 1901 ja 1770.
Hmm... mistähän tällä kertaa kiikastaa? namespace on mukana mutta silti sama virhe. Tällä kertaa tiedostona on fGame.cpp/.h (teen ton .h tiedoston aina varmuuden varalta ku ei koskaa tiedä mitä herjaa).
täs on tän hetken main.ccp
//NukeSimu III, aplha 0.1 #include <cstdlib> //ei muista enää... ei tainnut olla tarvetta mutta antaa olla vielä. Testaan myöhemmin. #include <iostream> // perus sisääntulo/ulostulo #include <conio.h> //ruudun tyhjennystä varten #include "fTittle.cpp" //päävalikko #include "fGame.cpp" //itse peli using namespace std; int main() { int vMode = 0; vMode = fTittle(); //kutsustaan funktiota fTittle() joka piirtää logon ja asettaa pelin tilan if (vMode == 1) { system("cls"); // tyhjentää ruudun fGame(); } else { system("cls"); // tyhjentää ruudun cout << "loser..." << endl; } system("PAUSE"); return EXIT_SUCCESS; }
ja sitte tämä fGame.ccp, jossa fGame() sijaitsee. Koodia on lisää mutta laitan tän ensimmäisen kohdan esille. Lopussa on viellä tuo int fSide() jossa valitaan osapuoli. Se palauttaa arvon 1,2 tai 0 joka tulkitaan virheeksi. En viitsi laittaa sitä, koska se on käytännössä vain isoläjä ASCII kuvaa.
//tämä on nyt se varsinainen "peli", jossa aluksi valitaan puoli (IHAN UUS! Ennen piti pelata //vain USA:lla... :D //kuitenkin, meillä on tuo fgame(), jossa varsinaiset tapahtumat ovat ja sitte fSide() jossa //valitaan ollaako jenkki vai neukku. using namespace std; void fGame() //varsinainen peli { int vStatus = 0; cout << "In main mode" << endl; vStatus = fSide(); if (vStatus == 1 || vStatus == 2) { cout << "This section of the game is still under work. Please be patient." << endl; } else { cout << "There was a somekind of error there. Dunno what you did, but it was something " << endl << "that you weren't supposed to do. Jerkass." << endl; } //return 1; } //fGame päättyy
jos ihmettelette miks fGame() on erillisessä teidostossa, tarkoitus on vielä tehdä fOption() ja fLoad(), jotka taas vievät oman osansa teidostosta. Hajauttamalla tietyt "yläfunktiot" (no, oikeesti alifunktiot) pysyy tuo main() selkeämpänä kun siellä ei ole useaa funktiota yhdessä rytäkässä. Plus vielä luokat jotka on vielä suunnittelun alla.
Et näköjään ymmärrä tuosta monen tiedoston jutusta yhtikäs mitään. Mikset lukenut linkittämiäni neuvoja, tai mikset ottanut niistä opiksesi?
Koska en ymmärtänyt antamiasi linkkejä ja edellinen neuvo ei toimi. Lisään tuon namespace, mutta virhe on sama. Nyt vain eri tiedosto.
Virhe taitaa olla rivillä
vMode = fTittle();
fTittle() on void-tyyppinen, joten se ei palauta mitään. Nyt kuitenkin yrität sijoittaa tyhjää int-muuttujaan.
Ei ole, ikävä kyllä. Koodi on muuttunut :) fTittle() on tätä nykyää int, joka palauttaa int arvon. En ole vielä tehnyt ns. "backup" komentoa, joka antaa virhe ilmoituksen jos sieltä tulee jotain muuta kuin mitä pyydetään. Eli peli kysyy käyttäjältä haluaako hän pelata vai ei.
(ASCII logo jätetty pois tilan säästämiseksi)
int fTittle() { int vValinta = 1; //alustetaan vValinta muuttuja ja annetaan sille oletusarvoksi 1, joka aloittaa pelin // Tähän tulee alun logo cout << "Welcome to NukeSimu III. Please enter your choice: " << endl //Pyydetään pelaaja tekemään valinta <<"1: Beging new game " << endl <<"2: Quit" << endl; cin >> vValinta; return vValinta; //palautetaan pelaajan valinta } //fTittle() päättyy
mutta huomasimpa tämän: myöhemmin tulee ilmoitus kohdassa
vStatus = fSide();
virhe: fSide() undecleared
ja jotain fSide() used prior declared
Jos joku osaisi suomeksi selittää, mitä tällä "declare" tarkoitetaan ja MINNE sen on tarkoitus mennä, olisin erittäin tyytyväinen :D
*edit*
Kappas, sain cout virheen pois kun lisäsin rivit
int fTittle();
void fGame();
int fSide();
tuon using namespace std; jälkeen. Nyt tulee vain ilmoitus fSide() undecleared. Osaako kukaan auttaa?
EDIT: olitkin laittanut jo uutta koodia... no anyway, toivottavasti tämä auttaa
ymmärtämään metabolixin koodivinkkejä...
EDIT2: tuo virhe johtuu siitä, että et ole määrittänyt funktiota
int fSide(); missään. Eli laitettu sisältöä tyyliin:
int fSide() { int x = 1; return x; }
Sää teet väärin... pitäis olla #include "xxx.h"
eikä #include "xxx.cpp"
esim.
xxx.cpp
#include "xxx.h" void moi() { std::cout<<"moi!!"<<std::endl; }
xxx.h
#ifndef _XXX_H #define _XXX_H 1 #include <iostream> extern void moi(); #endif
main.cpp
#include "xxx.h" int main() { moi(); std::cin.get(); return 0; }
anteeksi nyt tyhmyyteni, mutta en nyt ymmärtänyt täysin. Eli <iostream> tulee toisen , esim. fGame.h sisään? Tuleeko sinne myös "using namespace std; "? Ja sitte nuo #ifndef _XXX_H ja #define _XXX_H 1. Tiedän, että suurin osa porukasta osaa lukea tuon kuin joisivat vettä, mutta itse koodasin viimeksi 5 vuotta sitten ja nyt yritän taas kehittyä (kertasin kyllä perusteet, et ihan nollasta en lähtenyt). Kieli vaan on menny eteenpäin.
EDIT: Katso Metabolixin ohje alempaa... :D
//Tarkistetaan onko määritetty (#define...) _XXX_H #ifndef _XXX_H //jos ei ole, niin määritetään se. Tämä estää sen, ettei samaa tiedostoa //vahingossa sisällytetä montaa kertaa samaan projektiin. #define _XXX_H 1 //Koodia.... //lopetetaan ehto #endif
Mande kirjoitti:
anteeksi nyt tyhmyyteni, mutta en nyt ymmärtänyt täysin. Eli <iostream> tulee toisen , esim. fGame.h sisään?
Header tiedosto (.h/.hpp) on nimensä mukaisesti otsikkotiedosto eli sinne voi ja yleensä laitetaankin itse varsinaisen koodin #include rivit ja tärkeiden muuttujien ja funktioiden esittely, ehkä struct rakenteet, luokat (niiden funktiot kannattaa taas pistää omaan .cpp tiedostoonsa). Periaatteessa perussääntönä voitaisiin pitää, että header tiedosto on esittelyä kun varsinainen kooditiedosto on sitten valmis käyttämään esim. juuri iostreamin esittelemiä asioita. Sitten ei tarvitse muuta kuin pistää #include "xxx.h" joka kooditiedoston alkuun.
Mande kirjoitti:
Ja sitte nuo #ifndef _XXX_H ja #define _XXX_H 1..
Tuo #ifndef .. #endif systeemi estää tiedoston lisäyksen kahteen kertaan. Rivi tarkistaa onko jo tiedostossa käyty kertaalleen ja jos ei niin määritellään _XXX_H ilmaisemaan että nyt ollaan käyty. Juurikin siksi esimerkiksi ei haittaa vaikka rivin #include <iostream> laittaisikin useammin kuin kerran koska se ei käännösvaiheessa ole koskaan useampaan kertaan sisällytetty samaan koodinpätkään.
Disclaimer: en ole vastuussa jos jokin meni väärin :P Itsellä toimii silti koodit näillä keinoilla.
vehkis91 selitti pari kohtaa väärin.
#include <iostream>
kuuluu kaikkiin niihin tiedostoihin, joissa sitä tarvitaan, siis kaikkiin, joissa esiintyy std::cin tai std::cout. Jos et jostain erikoisesta syystä tarvitse sitä .h-tiedostossa, laita se vain .cpp-tiedostoihin ja vain, jos sitä tarvitaan.
using namespace std;
kuuluu niihin tiedostoihin, joissa tarvittaisiin muuten std::-etuliitettä mutta et halua sitä käyttää. Jos tämän rivin sijoittaminen oikeaan paikkaan tuottaa ongelmia, ota se kokonaan pois ja käytä std::-etuliitettä, kunnes olet viisastunut riittävästi, jotta ymmärrät oppaasta, mitä rivi tekee ja milloin sitä on järkevää käyttää vai onko koskaan.
Kaipaamasi suomennokset:
declare, esitellä, ja declaration, esittely;
define, määritellä, ja definition, määrittely.
Lisätietoa näiden merkityksistä on oppaassa, jonka jo linkitin. Et ilmeisesti yrittänyt juurikaan lukea sitä, nimittäin myös nämä käännökset esiintyvät siinä.
*edit*
Okei, eli fiksattu versio
*edit*
En tiedä tarkalleen ymmärsinkö oikein, mutta ainakin virheet vähenee.
eli täl hetkel:
fGame.cpp
//tämä on nyt se varsinainen "peli", jossa aluksi valitaan puoli (IHAN UUS! Ennen piti pelata //vain USA:lla... :D //kuitenkin, meillä on tuo fgame(), jossa varsinaiset tapahtumat ovat ja sitte fSide() jossa //valitaan ollaako jenkki vai neukku. #include <iostream> // perus sisääntulo/ulostulo int fGame() //varsinainen peli { int vStatus = 0; std::cout << "In main mode" << std::endl; vStatus = fSide(); if (vStatus == 1 || vStatus == 2) { std::cout << "This section of the game is still under work. Please be patient." << std::endl; } else { std::cout << "There was a somekind of error there. Dunno what you did, but it was something " << std::endl << "that you weren't supposed to do. Jerkass." << std::endl; } return 1; } int fSide() { int vSelection; //USAn lippu: Joan Stark, http://www.geocities.com/soho/7373/july4.htm#vertflag std::cout << "============;===========;() " << std::endl //vasara ja sirppi From: Dave Bird---St Hippo of Augustine http://punkabbestia.com/punkabbestia/ascii-art/docs/ascii-art_de_collection/s/sickle%2Bhammer.html << " # # # #:::::: |\\', \\." << std::endl << " # # # #:::::: .' \\\\| \\'." << std::endl << " # # # #:::::: __| |~ \\ :" << std::endl << " # # # #:::::: /\\ \\_. \\ /\\ : |" << std::endl << " # # # # # # # \\ \\| \\ \\/ \\ / /" << std::endl << " # # # # # # # \\/ \\ \\/\\ '._.' /" << std::endl << " # # # # # # # /\\ \\ '.___.'" << std::endl << " # # # # # # # / /\\ \\" << std::endl << " # # # # # # # / / \\ \\" << std::endl << " # # # # # # # / / \\ \\" << std::endl << " \\/ \\/" << std::endl; std::cout << " 1:USA 2:USSR " << std::endl; std::cin >> vSelection; if (vSelection == 1 || vSelection == 2) { return vSelection; } else { return 0; } } //fSide päättyy
fGame.h
#ifndef _fGame_h #define _fGame_h extern int fGame(); extern int fSide(); #endif
main.ccp
//NukeSimu III, aplha 0.1 #include <cstdlib> //ei muista enää... ei tainnut olla tarvetta mutta antaa olla vielä. Testaan myöhemmin. #include <iostream> // perus sisääntulo/ulostulo #include <conio.h> //ruudun tyhjennystä varten #include "fTittle.h" //Valikko #include "fGame.h" //itse peli int fGame(); int fSide(); int main() { int vMode = 0; vMode = fTittle(); //kutsustaan funktiota fTittle() joka piirtää logon ja asettaa pelin tilan if (vMode == 1) { system("cls"); // tyhjentää ruudun fGame(); } else { system("cls"); // tyhjentää ruudun std::cout << "loser..." << std::endl; } system("PAUSE"); return EXIT_SUCCESS; }
ja Dev-C++ ilmoittaa että funktio fSide() on esittelemätön. Kuinka korjata?
Ja P.S: Kiitos Metabolixelle kun jaksaa vastailla tällaisen tollon kysymyksiin :) ja teille muillekkin :)
Lue vielä edellisen viestini kappale iostream-otsikon sijoittelusta.
Ai p*****e, nyt huomasin. Oli jäänyt tuo #include "fGame.h" pois fGame.cpp tiedostosta. Nyt alkoi taas toimia.
Kiitos paljon kun jaksoit auttaa. Uskoisin et kyl se tästä eteenpäin (toivottavasti) osaa itse etsiä virheet ja korjata. Kiitti viel kerran.
Aihe on jo aika vanha, joten et voi enää vastata siihen.