Beginners Vraag

Status
Niet open voor verdere reacties.

bierens

Gebruiker
Lid geworden
4 aug 2006
Berichten
191
Hallo,

Ik ben pas begonnen met C++ en ben bezig om via tutorials het programmeren onder de knie te krijgen, nu ben ik met het spelletje Pengo bezig, weet niet of iemand bekent is met deze tutorial. Maar...

Ik krijg een foutmelding, dit is wat ik doe:
Code:
include "Console.h" //Deze file staat in dezelfde map als mijn programmeer bestand

// teken Pengo
MoveCursor(myX, myY);
cout << PengoCharacter;
De FOUT:

[Linker error] undefined reference to `MoveCursor(unsigned short, unsigned short)'
[Linker error] undefined reference to `GetVirtualKey()'
[Linker error] undefined reference to `MoveCursor(unsigned short, unsigned short)'
[Linker error] undefined reference to `MoveCursor(unsigned short, unsigned short)'
ld returned 1 exit status
C:\Danny\Makefile.win [Build Error] [Pengo.exe] Error 1

Ik gebruik Dev-C++ om te programmeren

Alvast bedankt,

Bierens
 
Laatst bewerkt:
Deze error komt vaak voor omdat de lokatie van de headerfile waarin het "symbool" staat niet ge-include is.

Een hele mond vol, maar in jouw geval komt het neer op:

Je hebt een headerfile waarin de functie MoveCursor gedeclareerd staat. Om te kunnen linken (een onderdeel van het compileerproces) moet je de directory opgeven waarin deze headerfile staat.

Dat doe je op twee punten:
- in de "include" statements helemaal bovenaan waarin je zegt om welke file het gaat
- in de include directory die je aan je compiler meegeeft.

Concreet houdt het dus in dat je bovenaan nog include "voorbeeldheader.h" moet invullen, en in Dev-C++ (goeie keuze, ik gebruik 'm zelf ook :) ) aan moet geven waar die file dan staat.

Dit kan waarschijnlijk bij een menu item genaamd Linker. Nu zit ik op het moment op m'n werk, dus ik kan je even niet zeggen waar precies. Ik zal straks een edit doen om dat aan te passen.
 
Alvast bedankt voor je reactie, helaas snap ik er nog niet heel veel van.

Zoals ik begrijp moet ik dus een bestand/library ingeven zodat dev-c++ weet dat " staat voor iets inlezen uit dezelfde directory als het opgeslagen bestand staat?

Bedankt alvast
 
Laatst bewerkt:
Ik kon het toch niet laten:

Op http://www.geocities.com/uniqueness_template/

vond ik het volgende:

# Go to the "Options" menu and select "Compiler Options".
# In the "Directories" tab, put check in the "Add the directory below to be searched for include files:" option, and enter the location(s) of where you plan to save your files. TIP: Do not use directory names with spaces and make sure to separate multiple entries with semicolons. As an example, mine is set to: C:\PRG;C:\PRG\CSC161.

Ter verdere uitleg:

Als je een programma gaat schrijven, dan wordt het op den duur te groot om in 1 bestand alle code te gebruiken. In dat geval ga je je code splitsen in meerdere bestanden. Vaak wil je dan wel een funktie die in de ene file staat gebruiken in een andere file. Daarom moet je aangeven welke functies er in een bestand zitten.
In C++ gebeurd dit door alle declaraties van de functies in een los bestand te zetten: de header file.

De reden om dat te doen is dat je op deze manier iemand anders een library kunt geven zonder dat je meteen de code hoeft te geven: als die ander de headerfile heeft weet ie immers welke functies in de library zitten.

Om nu de functies zoals MoveCursor te kunnen gebruiken in jouw bestand zul je dus een include met de headerfile met daarin die functie bij je code moeten zetten. Net zoals je nu Console.h hebt staan.
Dev-c++ weet nu wel hoe het bestand heet waarin hij naar de functie MoveCursor moet zoeken, maar hij weet nog niet in welke directory het staat. In veel gevallen zul je namelijk niet alle libraries die je wilt gebruiken bij je project zetten. Om nou aan Dev-c++ uit te leggen waar hij die headerfile dan kan vinden stel je dat in zoals bovenaan deze post.

Bij compilatie wordt dan in die directories gezocht naar de headerfile en kan je programma volledig gecompileerd worden.
 
Helaas werkt ook dit niet.

Ik ben nu bij gereedschap naar compiler-opties gegaan,

Daar zie ik het volgende:

Mappen

Daarin staan verscheidene mappen van dev-c++ zelf, in binairies,libraries,c includes,c++ includes

Ik heb daar mijn map: c:\danny

in toegevoegd maar nog krijg ik dezelfde fout.

Linker error

In mijn Project-opties 'Linker menu' heb ik alleen staan: Console.a
En bij Bestanden - include mappen staat c:\danny en c:\dev-cc
 
Laatst bewerkt:
Nog even ter extra informatie:

Het gaat hier over de console API van dev-c++ , deze heb ik gedownload en in de map gezet.De volgende bestanden heb ik dus:

Console.h << Include bestand (header)
Console.a << Library bestand
 
Laatst bewerkt:
Nou zeg, jij weet ook wel leuke problemen te vinden... :)

Na even prutsen ben ik er toch uit:

Download de *broncode* van:
HTML:
http://www.ronkes.nl/programmeren/console%20api/bloodshed.asp#download

Zet die in een aparte directory en open het project wat daarbij staat.
Vervolgens compileer je de library.
Daarna kopieer je de library over de vorige bestanden heen. Console.a was na deze aktie bij mij ineens 10 Kb kleiner.

Vervolgens voeg je bij Project options het volgende in:
Bij het tabblad Directories vul je de directory waar je de library hebt gezet in bij Library directories en de directory waar je de header hebt gezet bij Include directories.

Daarna ga je naar het tabblad Parameters. Daar klik je op de knop Add Libray or Object, en selecteer je het Console.a bestand dat je zojuist gekopieerd hebt.

Dan zet je bovenaan in je broncode bestand nog: #include <Console.h>

Ziezo, bij mij werkt ie dan.
 
En dat werkt inderdaad, maar ik loop daarna bij het volgende onderdeel weer tegen problemen :(

Nu is het volgens mij echt een programmatie fout :)

14 C:\Programmeer\Main.cpp In file included from Main.cpp
22 C:\Programmeer\Player.cpp expected init-declarator before "Player"
22 C:\Programmeer\Player.cpp expected `,' or `;' before "Player"
C:\Programmeer\Makefile.win [Build Error] [Main.o] Error 1

Zal even de volledige code posten die ik tot nu heb hopelijk kun je er dan wat mee :)

Main.cpp
Code:
/******************************************************************************
	Bestand:   Main.cpp
	Project:   Pengo

	Copyright: (c) 2003 Joost Ronkes Agerbeek

	Auteur:    Joost Ronkes Agerbeek <joost@ronkes.nl>
	Datum:     11 januari 2003
******************************************************************************/

#include <iostream>
#include "Console.cpp"
#include <windows.h>
#include "Player.cpp"

using namespace std;

/******************************************************************************
	Constante variabelen
******************************************************************************/

/**
 * De toetsen voor de besturing van Pengo.
 */
const int PengoUp    = VK_UP;
const int PengoDown  = VK_DOWN;
const int PengoLeft  = VK_LEFT;
const int PengoRight = VK_RIGHT;
const int GameExit = VK_ESCAPE;

/**
 * De vertraging van de game loop in milliseconden.
 */
const int GameDelay = 150;

/**
 * Het ASCII-teken dat Pengo voorstelt.
 */
const char PengoCharacter = '*';

/******************************************************************************
	Globale functies
******************************************************************************/

/**
 * Het programma start hier.
 *
 * @return	altijd 0
 */
int main()
{
// maak speler aan
Player myPlayer = CreatePlayer();

// teken Pengo
MoveCursor(myPlayer.X, myPlayer.Y);
cout << PengoCharacter;

// laat speler Pengo besturen
int myKey;

do
{

// vraag huidige tijd op
DWORD myTime = timeGetTime();

// wacht tot vertraging om is
while (timeGetTime() < (myTime + GameDelay));

// wacht op een toets
int myKey = PeekVirtualKey();
	
// verwijder Pengo van scherm
MoveCursor(myPlayer.X, myPlayer.Y);
cout << " ";

// is er een toets ingedrukt?
if (PeekVirtualKey() != 0)
{
	// ja, verwijder toets uit buffer
	myKey = GetVirtualKey();
    
// welke toets is ingedrukt?
switch (myKey)
{
case PengoUp:
{
// stel richting in
myPlayer.Direction = 1;
} break;

case PengoDown:
{
// stel richting in
myPlayer.Direction = 2;
} break;

case PengoLeft:
{
// stel richting in
myPlayer.Direction = 3;
} break;

case PengoRight:
{
// stel richting in
myPlayer.Direction = 4;
} break;
}
}
// verwijder Pengo van scherm
MoveCursor(myPlayer.X, myPlayer.Y);
cout << " ";

// verplaats de speler
MovePlayer(myPlayer);

// teken Pengo
MoveCursor(myPlayer.X, myPlayer.Y);
cout << PengoCharacter;

} while (myKey != GameExit);

// wacht op enter
cout << endl;
system("pause");

return 0;
}

Player.h
Code:
/******************************************************************************
	Bestand:   Player.h
	Project:   Pengo

	Copyright: (c) 2003 Joost Ronkes Agerbeek

	Auteur:    Joost Ronkes Agerbeek <joost@ronkes.nl>
	Datum:     11 januari 2003
******************************************************************************/

#ifndef __PLAYER_H__
#define __PLAYER_H__

/******************************************************************************
	Structures
******************************************************************************/

/**
 * Een speler.
 */
struct Player
{
	/**
	 * De positie van de speler.
	 */
	int X, Y;
	
	/**
	 * De richting die de speler op loopt.
	 */
	int Direction;
};

/******************************************************************************
	Globale functies - definities
******************************************************************************/

/**
 * Maakt een nieuwe speler aan en initialiseert de gegevens van de speler.
 *
 * @return	een nieuwe speler
 */
Player CreatePlayer();
void MovePlayer(Player& player)
#endif

Player.cpp
Code:
/******************************************************************************
	Bestand:   Player.cpp
	Project:   Pengo

	Copyright: (c) 2003 Joost Ronkes Agerbeek

	Auteur:    Joost Ronkes Agerbeek <joost@ronkes.nl>
	Datum:     11 januari 2003
******************************************************************************/

#include "Player.h"

/******************************************************************************
	Globale functies
******************************************************************************/

/**
 * Maakt een nieuwe speler aan en initialiseert de gegevens van de speler.
 *
 * @return	een nieuwe speler
 */
Player CreatePlayer()
{
	// maak nieuwe speler
	Player myPlayer;

	// stel standaardwaarden in
	myPlayer.X = 40;
	myPlayer.Y = 12;
	myPlayer.Direction = 0;

	// geef speler terug
	return myPlayer;
}

/**
 * Verplaatst de speler één positie.
 *
 * @param	player	de speler die verplaatst moet worden
 */
void MovePlayer(Player& player)
{
	// in welke richting beweegt de speler?
	switch (player.Direction)
	{
	case 1:
		{
			// verplaats speler omhoog
			player.Y--;
		} break;
	case 2:
		{
			// verplaats speler omlaag
			player.Y++;
		} break;
	case 3:
		{
			// verplaats speler naar links
			player.X--;
		} break;
	case 4:
		{
			// verplaats speler naar rechts
			player.X++;
		} break;
	}
}
 
Laatst bewerkt:
De fout zit kennelijk in Player.cpp. Is dat een file die jij gemaakt hebt?
 
Uhm die heb ik gemaakt vanuit de tutorial ja :)

Maar bij het aanmaken van speler, gaat de Maker van de tutorial ineens van player.cpp naar player.h enzovoorts

Dus hoop ik wel dat ik het goed gedaan heb, maar ergens zit een foutje maar ik kan hem niet vinden heb ook op andere forums gekeken maar daar staat hij ook niet :)
 
Laatst bewerkt:
Wat mij opvalt namelijk is dat je een variabele aanmaakt van het type Player. Vervolgens geef je die terug via de return. Op het moment dat je de functie verlaat word het geheugen voor die variabele vrijgegeven. Het gevolg is dat de functie die het resultaat wil gaan gebruiken dus geheugen gaat aanspreken dat vrijgegeven is.

Dit gaat dus alleen werken als de waarde na aanroep van de functie direct gekopieerd wordt. Dan zou ik toch al gauw naar een constructor toe gaan.
 
Wow, dat klinkt ff te moeilijk :) Het staat zo in de tutorial, maar zou jij mij kunnen vertellen hoe ik dat aan kan passen dan? Volgens mij moet het echt 1 foutje zijn ofzo.

Groetjes en alvast bedankt,

Bierens
 
Laatst bewerkt:
Wat jij wil is een nieuwe Player aanmaken, toch?

C++ is een object georienteerde taal. Dat zegt op zich nog niet zoveel, maar het komt hier op neer:

Stel je voor dat je Player een echt "ding" is, bijvoorbeeld een stoel. Nu heeft een stoel een aantal eigenschappen: hoogte, breedte, materiaal en soort (ligstoel, keukenstoel etc.).

Als je in een niet-object georienteerde taal zit, dan zou je een stoel definieren als een struct. Een struct is een verzameling variabelen die bijelkaar gehouden worden door .. wel.. het struct. :)

Een stoel is dan:

struct {
int hoogte;
int breedte;
int materiaal; (leggen we vast als een nummer in een lijst)
int soort;
} stoel;

Hartstikke leuk, maar nou wil je eigenlijk ook functies met die stoel kunnen uitvoeren. Bijvoorbeeld "schuif aan". Nou zou je een functie kunnen schrijven waar je een stoel als variabele in doet, en waar een aangeschoven stoel als variabele uitkomt.

Maar... nu wil iemand anders ook zo'n stoel hebben. Hij maakt z'n eigen struct en z'n eigen functie.... die net niet bij jouw functie past. Hmm... probleem.

Het zou eigenlijk veel handiger zijn als je de functie erbij kunt zetten in dat struct. Dat is wat er gebeurt als je met classes gaat werken. Een class is het grotere broertje van een struct:

In een class maak je het ontwerp voor een stoel met alle eigenschappen en functies die je met die stoel kunt doen. Iedereen die nu een stoel nodig heeft pakt die class en maakt een variabele aan van het type stoel.

Er zitten 2 speciale functies in zo'n class: de constructor en de destructor. Deze vertellen de compiler dat als iemand een stoel aanmaakt, de compiler dat volgens de constructor moet doen. En als de variabele weer vrijgegeven wordt, gaat dat volgens de destructor.

In jouw geval kun je dus in de constructor vertellen hoe de variabelen X, Y en direction gevuld moeten worden. Dit gebeurd *altijd* als iemand een nieuwe Player aanmaakt.

Ik hoop dat ik het een beetje duidelijk heb kunnen maken: object georienteerd denken is echt een vak apart. Maar als je eenmaal doorhebt hoe het werkt zit het eigenlijk heel logisch in elkaar. Er zijn bergen met informatie beschikbaar over het onderwerp waarin het nog zeker zo goed uitgelegd wordt.

Mocht ik het nog niet duidelijk hebben gemaakt, dan heb je in ieder geval een term waarop je kunt gaan zoeken. :)
 
Bedankt voor je snelle reactie,

Ik begrijp inderdaad wel wat je typt, maar volgens mij komt dit later in de tutorial, en ik had graag gezien dat ik de tutorial kon blijven volgen :)

Ik zat misschien zelf te denken dat ik iets fout include, of dat ik misschien die Player CreatePlayer() nog ergens in een int ofzo moest zetten.

Weet dus eigenlijk niet precies wat ik moet doen, zou de class nog even willen laten zitten omdat dit later in de tutorial terug komt.

Groetjes Bierens

Ps. Dit is het stuk waar het in de tutorial fout gaat denk ik:

Player.cpp
Code:
/**
 * Verplaatst de speler één positie.
 *
 * @param	player	de speler die verplaatst moet worden
 */
void MovePlayer(Player& player)
{
	// in welke richting beweegt de speler?
	switch (player.Direction)
	{
	case 1:
		{
			// verplaats speler omhoog
			player.Y--;
		} break;
	case 2:
		{
			// verplaats speler omlaag
			player.Y++;
		} break;
	case 3:
		{
			// verplaats speler naar links
			player.X--;
		} break;
	case 4:
		{
			// verplaats speler naar rechts
			player.X++;
		} break;
	}
}
Vergeet niet de declaratie van de functie toe te voegen aan Player.h. <<<<<<< ????
 
Laatst bewerkt:
De tutorial volgen lijkt me heel verstandig. Ik ben zelf ook het type wat liever leert door stapje voor stapje een handleiding te volgen ipv er gewoon in te duiken.


Vergeet niet de declaratie van de functie toe te voegen aan Player.h. <<<<<<< ????

In Player.h vertel je welke functies je in Player.cpp hebt staan. Een declaratie is niks anders dan de naam en de parameters van die functie. Wat die functie daadwerkelijk doet, de definitie, beschrijf je dus in je .cpp file.

In dit geval is dit de declaratie voor MovePlayer:

void MovePlayer(Player& player);

Als je die in je Player.h toevoegt moet het goed gaan.
 
Deze had ik er al in staan maar ik denk dat het misschien met die

Player(Createplayer) te maken heeft << moet ik dat ook iets met void doen ofzo?

Want die moet ook in de player.h aangeroepen worden neem ik aan?
 
In de headerfile die je gepost hebt staat er geen ; achter de MovePlayer declaratie.

In een headerfile roep je in principe geen functies aan. Die is er alleen bedoeld om duidelijk te maken welke functies er in de bijbehorende cpp file zitten.
 
Ook dat is helaas niet het probleem,

Ik ga toch nog eens overnieuw beginnen met de tutorial.

Bedankt voor je hulp en ik laat het wel weten als ik er nog niet uit kom :)

Groetjes
 
Laatst bewerkt:
Ok, overnieuw gestart maar helaas zelfde problemen, bij onderdeel 2 het aanmaken van de speler, zou jij over de code kunnen kijken, of is dat te moeilijk?

Main.cpp
Code:
/******************************************************************************
	Bestand:   Main.cpp
	Project:   Pengo

	Copyright: (c) 2003 Joost Ronkes Agerbeek

	Auteur:    Joost Ronkes Agerbeek <joost@ronkes.nl>
	Datum:     11 januari 2003
******************************************************************************/

#include <iostream>
#include "Console.h"
#include "Player.cpp"

using namespace std;

/******************************************************************************
	Constante variabelen
******************************************************************************/

/**
 * De toetsen voor de besturing van Pengo.
 */
const int PengoUp    = VK_UP;
const int PengoDown  = VK_DOWN;
const int PengoLeft  = VK_LEFT;
const int PengoRight = VK_RIGHT;

/**
 * De toetsen voor de besturing van het spel.
 */
const int GameExit = VK_ESCAPE;

/**
 * Het ASCII-teken dat Pengo voorstelt.
 */
const char PengoCharacter = '*';

/**
 * De vertraging van de game loop in milliseconden.
 */
const int GameDelay = 100;

/******************************************************************************
	Globale functies
******************************************************************************/

/**
 * Het programma start hier.
 *
 * @return	altijd 0
 */
int main()
{

    // maak speler aan
    Player myPlayer = CreatePlayer();

    // houd richting van Pengo bij
    int myPlayer.Direction = 0; // HET GAAT NU OM DEZE REGEL....

	// houd positie van Pengo bij
	int myPlayer.X = 40;
	int myPlayer.Y = 12;

	// teken Pengo
	MoveCursor(myPlayer.X, myPlayer.Y);
	cout << PengoCharacter;

    // laat speler Pengo besturen
    int myKey;

do
{
    // vraag huidige tijd op
    DWORD myTime = timeGetTime();
    
    	
    // wacht tot vertraging om is
    while (timeGetTime() < (myTime + GameDelay));
    
	// wacht op een toets
	int myKey = PeekVirtualKey();

	// verwijder Pengo van scherm
	MoveCursor(myPlayer.X, myPlayer.Y);
	cout << "#";

// is er een toets ingedrukt?
if (PeekVirtualKey() != 0)
{
	// ja, verwijder toets uit buffer
	myKey = GetVirtualKey();

// welke toets is ingedrukt?
switch (myKey)
{
case PengoUp:
	{
		// stel richting in
		myPlayer.Direction = 1;
	} break;
case PengoDown:
	{
		// stel richting in
		myPlayer.Direction = 2;
	} break;
case PengoLeft:
	{
		// stel richting in
		myPlayer.Direction = 3;
	} break;
case PengoRight:
	{
		// stel richting in
		myPlayer.Direction = 4;
	} break;
 }
}
// in welke richting beweegt Pengo?
switch (myPlayer.Direction)
{
case 1:
	{
		// verplaats Pengo omhoog
		myPlayer.Y--;
	} break;
case 2:
	{
		// verplaats Pengo omlaag
		myPlayer.Y++;
	} break;
case 3:
	{
		// verplaats Pengo naar links
		myPlayer.X--;
	} break;
case 4:
	{
		// verplaats Pengo naar rechts
		myPlayer.X++;
	} break;
}

	// teken Pengo
	MoveCursor(myPlayer.X, myPlayer.Y);
	cout << PengoCharacter;

} while (myKey != GameExit);

	// wacht op enter
	cout << endl;
	system("pause");

	return 0;
}

Player.cpp
Code:
/******************************************************************************
	Bestand:   Player.cpp
	Project:   Pengo

	Copyright: (c) 2003 Joost Ronkes Agerbeek

	Auteur:    Joost Ronkes Agerbeek <joost@ronkes.nl>
	Datum:     11 januari 2003
******************************************************************************/

#include "Player.h"

/******************************************************************************
	Globale functies
******************************************************************************/

/**
 * Maakt een nieuwe speler aan en initialiseert de gegevens van de speler.
 *
 * @return	een nieuwe speler
 */
Player CreatePlayer()
{
	// maak nieuwe speler
	Player myPlayer;

	// stel standaardwaarden in
	myPlayer.X = 40;
	myPlayer.Y = 12;
	myPlayer.Direction = 0;

	// geef speler terug
	return myPlayer;
}

Player.h
Code:
/******************************************************************************
	Bestand:   Player.h
	Project:   Pengo

	Copyright: (c) 2003 Joost Ronkes Agerbeek

	Auteur:    Joost Ronkes Agerbeek <joost@ronkes.nl>
	Datum:     11 januari 2003
******************************************************************************/

#ifndef __PLAYER_H__
#define __PLAYER_H__

/******************************************************************************
	Structures
******************************************************************************/

/**
 * Een speler.
 */
struct Player
{
	/**
	 * De positie van de speler.
	 */
	int X, Y;
	
	/**
	 * De richting die de speler op loopt.
	 */
	int Direction;
};

/******************************************************************************
	Globale functies - definities
******************************************************************************/

/**
 * Maakt een nieuwe speler aan en initialiseert de gegevens van de speler.
 *
 * @return	een nieuwe speler
 */
Player CreatePlayer();

#endif

Dit zijn de foutmeldingen:

60 C:\Programmeer\Main.cpp expected primary-expression before "int"
60 C:\Programmeer\Main.cpp expected `;' before "int"
 
Laatst bewerkt:
Dat wil ik op zich best doen, maar dan zul je geduld moeten hebben. Die console.h is voor dev-c++ en ik heb hier thuis alleen maar linux bakken staan.

Maandag zit ik weer bij m'n chickie achter een xp bak.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan