Gå til innhold

Bone's Offisielle C++ hjelpetråd


Anbefalte innlegg

  • 3 uker senere...
Videoannonse
Annonse

Hei, jeg prøver å lære meg C++ og ble litt usikker da jeg kom til pekere.

 

Jeg har lagt til en liten kodesnutt under for å forklare problemet.

 

#include <iostream>
using namespace std;

int main()
{
   char *ptr, str[6] = "hello";

   ptr = str;

   cout << ptr; // Output: hello

   return 0;
}

 

Når jeg setter ptr = str, har jeg forstått det slik at ptr da vil peke på det første elementet i str. Utskriften av cout << ptr blir som skrevet "hello". Jeg fant ut at for å skrive ut adressen til str[0] kunne jeg bruke cout << &ptr. Når jeg skriver *ptr får jeg verdien til det første elementet i str, nemlig 'h'.

 

Det jeg lurer på er hvorfor den ikke skriver adressen til str[0] når jeg skriver cout << ptr, men heller skriver hele innholdet i str-tabellen?

 

Jeg håper dere kan hjelpe meg å forstå dette bedre.

Lenke til kommentar

Åkey, du får ta dette her med en klype salt. Er trøtt og sliten, så mulig det har gått litt fort et par steder her. Anyways, jeg vil tro det er pga. følgende:

 

str er en array (aka. tabell), og verdien av str er per definisjon derfor &str[0]. Dette er også verdien av ptr. Både ptr og str peker altså til en nullterminert string.

 

Vidre så jeg her at standardbiblioteket bl.a. definerer følgende funksjon:

ostream& operator<< (ostream& out, const char* s );

 

Jeg tipper at str og ptr (som jo er av typen char*), blir automatisk konvertert til const char*, og at denne funksjonen venter en nullterminert string (som den jo her får) som den skriver til standard output. Derfor skriver den ut strengen, og ikke minneadressen.

 

Standardbiblioteket definerer også denne funksjonen:

ostream& operator<< (void*& val );

&ptr er av typen char** (du tar adressen av en peker, så det er en peker til en peker), og jeg tipper at denne blir automatisk konvertert til void*&.

 

Det er altså to forskjellige funksjoner (selv om det kanskje ikke ser slik ut pga. operator overloading), og den ene skriver ut en nullterminert string, mens den andre (ihvertfall i dette tilfellet) skriver ut en minneadresse.

Lenke til kommentar

Kjøpte meg nettopp Accelerated C++ boken og kom fra Amazon idag. De forrige bøkene jeg har prøvd meg på har guidet meg gjennom bruk av kompiler og programmet jeg holdte på med, men ikke denne.

 

Jeg bruker Visual Studio 2008 og starter ett nytt C++ Empty Project, men når jeg skriver inn "Hello World" programmet og klikker F6 for "Build Solution" så kommer det bare "Build succeded" men ingen vindu med "Hello World". Jeg har 3 mapper i denne "solution" som heter Header Files, Resource Files, Source Files og jeg har prøvd å ha hello.cpp filen i alle av dem, uten noe annet resultat. Hva gjør jeg galt?

 

Teksten jeg bruker i filen er:

// a small C++ program

#include <iostream>

 

int main()

{

std::cout << "Hello, world!" << std::endl;

return 0;

}

Lenke til kommentar

F6 bare kompilerer.

F5 starter programmet i debug modus.

 

Merk at vinduet kommer til å lukke seg med en gang.

 

edit:

De få gangene jeg selv driver med console programmering, så har jeg alltid et terminalvindu klart i program-mappen og starter programmet derfra. Da er det enklere å gi det forskjellige parameter (ellers må en gå i project properties og endre Arguments som er litt slitsomt)

Endret av GeirGrusom
Lenke til kommentar

Hvordan har det seg at det lukker seg med en gang da? Husker jeg kom over den samme leksjonen i C Sharp og da var det en kommando jeg måtte legge til for å holde den oppe. Boken gir ihertfall uttrykk til at det skal være mulig å se vinduet med "Hello World" før det lukker seg.

Lenke til kommentar

Quicksort

 

Jeg leser boken C++ A Beginner's Guide av Herbert Schildt og kom over en kode som jeg hadde litt problemer med å forstå. Jeg har skrevet inn koden og den virker akkurat som den skal. Problemet er at jeg ikke forstår hvordan den virker.

Programmet sorterer en char array ved å bruke quicksort-algoritmen (velger medianen som utgangspunkt hver gang).

Har søkt litt på quicksort på internett og funnet ut noelunde hvordan quicksort virker i teorien, men når jeg ser på kodeeksempelet klarer jeg ikke helt å forstå hvordan man har tenkt i qs().

 

Altså problemet er å forstå hvordan de har overført det fra teori til kode...

Håper noen kan hjelpe meg med å forstå bedre..

Takker på forhånd. :)

 

#include <iostream>
#include <cstring>
using namespace std;

void quicksort(char *items, int len);

void qs(char *items, int left, int right);

int main()
{
   char str[] = "daebc";

   cout << "Original order: " << str << '\n';

   quicksort(str, strlen(str));

   cout << "\n\nSorted order: " << str << "\n";

   cin.get();

   return 0;
}

// Set up a call to the actual sorting function.
void quicksort(char *items, int len)
{
   qs(items, 0, len-1);
}

// A recursive version of Quicksort for sorting characters
void qs(char *items, int left, int right)
{

   int i, j;
   char x, y;

   i = left; j = right;
   x = items[(left + right) / 2];

   do
   {
       while((items[i] < x) && (i < right)) i++;
       while((x < items[j]) && (j > left)) j--;

       if (i <= j)
       {
           y = items[i];
           items[i] = items[j];
           items[j] = y;
           i++; j--;
       }
   } while (i <= j);

   if (left < j) qs(items, left, j);
   if (i < right) qs(items, i, right);


}

Lenke til kommentar
Quicksort

 

Jeg leser boken C++ A Beginner's Guide av Herbert Schildt og kom over en kode som jeg hadde litt problemer med å forstå. Jeg har skrevet inn koden og den virker akkurat som den skal. Problemet er at jeg ikke forstår hvordan den virker.

Programmet sorterer en char array ved å bruke quicksort-algoritmen (velger medianen som utgangspunkt hver gang).

Har søkt litt på quicksort på internett og funnet ut noelunde hvordan quicksort virker i teorien, men når jeg ser på kodeeksempelet klarer jeg ikke helt å forstå hvordan man har tenkt i qs().

 

Altså problemet er å forstå hvordan de har overført det fra teori til kode...

Håper noen kan hjelpe meg med å forstå bedre..

Takker på forhånd. :)

 

#include <iostream>
#include <cstring>
using namespace std;

void quicksort(char *items, int len);

void qs(char *items, int left, int right);

int main()
{
   char str[] = "daebc";

   cout << "Original order: " << str << '\n';

   quicksort(str, strlen(str));

   cout << "\n\nSorted order: " << str << "\n";

   cin.get();

   return 0;
}

// Set up a call to the actual sorting function.
void quicksort(char *items, int len)
{
   qs(items, 0, len-1);
}

// A recursive version of Quicksort for sorting characters
void qs(char *items, int left, int right)
{

   int i, j;
   char x, y;

   i = left; j = right;
   x = items[(left + right) / 2];

   do
   {
       while((items[i] < x) && (i < right)) i++;
       while((x < items[j]) && (j > left)) j--;

       if (i <= j)
       {
           y = items[i];
           items[i] = items[j];
           items[j] = y;
           i++; j--;
       }
   } while (i <= j);

   if (left < j) qs(items, left, j);
   if (i < right) qs(items, i, right);


}

Hver gang quicksort blir kalt så tar den et element, i koden din er det det midterste elementet (x = items[(left + right) / 2];), og så går den gjennom arrayen to ganger, en fra hver side til den finner et element som er mindre enn eller større enn x:

while((items[i] < x) && (i < right)) i++;
while((x < items[j]) && (j > left)) j--;

altså, i er nå plassen til det første elementet som er større enn x og j er plassen til det første elementet som er mindre enn x. Den neste koden:

if (i <= j)
	{
		y = items[i];
		items[i] = items[j];
		items[j] = y;
		i++; j--;
	}

bytter om på disse to elementene sånn at i nå inneholder et element som er mindre enn x og j et element som er større enn x og dermed er de tre elementene sortert. Og sånn fortsetter loopen til i og j møtes og alle elementene som er mindre enn x er på den venstre siden av x og de elementene som er større er på den høyre siden. Så kaller man quiksort rekursivt igjen for å sortere subarrayene på venstre og høyere-siden. Vet ikke om det ble helt bra forklart.. Du får spørre hvis det er mer du lurer på.

Lenke til kommentar

Tusen takk for utfyllende svar. Det har virkelig hjelpet meg til å forstå quicksort bedre.

Jeg skjønner ikke hvorfor forfatteren av denne koden har valgt å ta med (i < right) og (j > left) i while-løkkene da det iallefall kan virke som dette er overflødig siden jeg velger x lik medianen hver gang og da vil (items < x) og (x < items[j]) bli false når items og/eller items[j] er lik x.

En annen ting jeg oppdaget er at i do-while løkken kan man bare skrive while (i < j)...

Noen som kan tenke seg hvorfor koden er skrev slik..?

 

Uansett, atter en gang, takk for hjelpen... :)

Lenke til kommentar
Tusen takk for utfyllende svar. Det har virkelig hjelpet meg til å forstå quicksort bedre.

Jeg skjønner ikke hvorfor forfatteren av denne koden har valgt å ta med (i < right) og (j > left) i while-løkkene da det iallefall kan virke som dette er overflødig siden jeg velger x lik medianen hver gang og da vil (items < x) og (x < items[j]) bli false når items og/eller items[j] er lik x.

En annen ting jeg oppdaget er at i do-while løkken kan man bare skrive while (i < j)...

Noen som kan tenke seg hvorfor koden er skrev slik..?

 

Uansett, atter en gang, takk for hjelpen... :)

Nja, du må ha med i < right og j > left for at den ikke skal gå over grensen sin og begynne å sortere sub-arrayer som allerede er sortert og sånn. Skjønte ikke helt det siste spørsmålet men. Det er faktisk ganske lett å se hvordan quicksort funker med haskell-kode, da ser det slik ut:

qs []	 = []
qs (x:xs) =  qs left ++ [x] ++ qs right
	where left  = filter (<x) x
		  right = filter (>=x) xs

her ser man at quicksort på en tom liste er en tom liste, mens quicksort av en liste av minst et element og en resterende liste ((x:xs)) er en liste av quicksort på den venstre lista, sammenslått med element x, sammenslått med quicksort på den høyre lista, hvor den høyre og venstre lista er sortert til bare å ha elementer som er henholdsvis mindre og større enn x.

Endret av teflonpanne
Lenke til kommentar

Jeg pleier vanligvis å bruke mye klasser når jeg lages spill o.l. I det siste har jeg imidlertid fått problemer når prosjektene mine har blitt større. Mitt største problem er hvordan klasser kan få tilgang til variabler fra andre klasser. Dette er spesielt vanskelig når jeg har klasser som igjen er i klasser. Kollisjoner blir ofte knotete, særlig når disse skal gi feedback tilbake til spilleren som kræsjet.

 

Jeg pleier å ha en game-klasse på toppen som inneholder game-loopen og alle andre objekt-klasser. F.eks. kamera-klassen, omgivelser og en vector med flere player-klasser.

 

Hvordan pleier dere å strukturere spillene deres?

Lenke til kommentar

Jeg har bare kodet 2D-spill, men jeg synes det er greit å ha en objekt-klasse som er superklassen til alle objekter som kan vises på skjermen. Collision detection går da enten i denne klassen, eller evt. som en policy-klasse ( http://en.wikipedia.org/wiki/Policy-based_design) som f.eks. kan brukes med template parameters og arv. Eller så har jeg en egen collision-klasse med en friend-declaration i objekt-klassen. Jeg er enig i at det ofte blir knotete når f.eks. kollisjoner skal gi feedback. Noe som jeg har hatt god erfaring med er sigc++ som er et typesikkert callbacksystem.

 

Jeg fant ut av at oppsettet mitt stort sett er klin likt når jeg koder SDL, så jeg lagde et bibliotek for det. (http://zengen.sourceforge.net). Det enkleste tilfellet ser da ut slik som dette: http://zengen.svn.sourceforge.net/viewvc/z...cpp?view=markup

 

Greia her er jo at siden sigc++ er så fleksibelt, kan on_event være en metode istedenfor en vanlig funksjon, slik at main-game-loopen kan pakkes fint inn i en tilsynelatende isolert klasse. Litt snøvlete forklart, men hvis du ser litt på kildekoden ser du hvordan jeg pleier å gjøre det ihvertfall.

Lenke til kommentar

Object-klassen er superklassen til alt som har en surface (surfaces er en greie i SDL, vet ikke om du er kjent med SDL?). Den implementerer basic funksjoner som bl.a. returnerer høyden, bredden og surfacet. Screen og Sprite arver fra Object. Sprite-klassen er egentlig en superklasse for alt som er synlig på skjermen, og har en virtuell metode som heter blit_to(Object&). Sprites kan enten blittes direkte til skjermen eller til andre objekter, og det er derfor Screen og Sprite arver fra Object.

 

Videre er spillet delt i flere subsystems (i henhold til hva som er beskrevet i Programming Linux Games) som f.eks. Audio, Network, Input, Display. Display-subsystemet mitt fungerer slik at det inneholder en instans av Screen, og en list med Sprite*. Denne listen lages i main-game-loop, og etterhvert som hvert objekt blir vist, så poppes det fra denne listen. Listen inneholder altså objekter som enda ikke har blit blittet til skjermen.

 

Forøvrig enig i at sigc++-løsningen kanskje ikke er optimal. Kanskje den kan byttes ut med en policy-klasse istedenfor ellernoe...

 

Mulig det var litt krunglete forklart dette her, menneh..

Lenke til kommentar
  • 1 måned senere...

Hei! Er helt fersk i programmering, så jeg prøver meg foreløpig på enkle øvingsoppgaver. Men jeg sitter nå "fast" i en oppgave der en skal sjekke om et tall er primtall eller ikke.

 

Her er koden jeg har lagd;

 

#include <stdio.h>

 

int primtall(int tall);

 

int main(void)

{

int tall;

int i;

 

printf("\nTast inn et tall\n");

scanf("%d",&tall);

 

printf("\n%d\n",primtall(tall));

 

return 0;

}

 

primtall(int tall)

{

int i;

 

for( i=2; i <= tall-1; i++)

{

if( tall%i == 0)

{

return (0); /*ikke primtall*/

}

else

return (1); /*primtall*/

}

}

 

Problemet er at programmet i tillegg til de fleste primtall gir meg oddetall som også ikke er primtall, f.eks 9,15,21 osv. Er det hjelp å få her?

Lenke til kommentar

Problemet ligger i at du har en else blokk i if-en din. Uansett så vil den avsluttes på første iterasjon, og dette er egentlig bare en funksjon som sjekker om tallet er et partall eller ikke.

 

Her er et lite eksempel:

int IsPrime(int tall)
{
 if(!(tall & 1))
return 0; // Tallet er et partall, ikke noe poeng i å sjekke det.

 // Det er ikke noe poeng i å sjekke tall over halvparten
 int max = tall / 2;

 // Oddetall kan heller aldri divideres på partall, hopp over alle partall.
 for(int i = 3; i < max; i+=2)
if((tall % i) == 0)
  return 0; // Tallet lot seg dividere på i, det er ikke et primtall

 // Tallet er et primtall.
 return -1;
}

Lenke til kommentar
  • 1 måned senere...

Hei!

 

Driver og lærer C++ etter en bok.

 

*Her sto det egentlig noe mer som gjorde denne posten noe mer fornufig enn det den er*

 

//-------------------------------------------------------------------
//
// person.cpp
//
// Prøver getline() og ignore()
//
#include <string>
#include <iostream>
using namespace std;
const int linjelengde = 100;
int main()
{
 string navn;
 string adr;
 int  alder;
 string stilling;
 cout << "Navn : ";
 getline(cin, navn);
 cout << "Adresse : ";
 getline(cin, adr);
 cout << "Alder : ";
 cin >> alder;
 cin.ignore(linjelengde, '\n');
 cout << "Stilling : ";
 getline(cin, stilling);

 cout << navn << endl << adr << endl << alder << endl << stilling
<< endl;
 return 0;
} // main

 

De to gjenstående problemene mine nå er hva getline() gjør og hva ignore() gjør. Skjønte de ikke, spesielt ikke getline(). Skjønte ikke forklaringen i boka.

 

Edit: Feil i koden jeg posta, men har fiksa på det så jeg fjerna den

Edit2: La til riktig kode

Endret av Rockie
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...