Vinnaren i pepparkakshustävlingen!
2016-06-22, 19:40
  #1
Medlem
Hej jag läser för tillfället en grundläggande spelprogrammeringskurs i C++, för att lära mig mer om spelprogrammering samt friska upp mina riktigt rostiga c++ kunskaper (läst några grundläggande kurser för några år sedan).

Håller just nu på med den första uppgiften och i den får vi inte använda std::string eller liknande utan ska träna på att använda char-pekare och liknande.
I uppgiften ska namn på olika saker genereras genom att kombinera 1 del från 3 olika arrayer dynamiskt. För att sedan dynamiskt alkolera en char-pekare och retunera denna från funktionen.
Jag har löst den delen utav uppgiften på följande sätt. Vilket fungerar (även om det säkert inte är optimal kod).

Kod:
char* generateThingName()
{
	const char*  part1[] = { "Divine ", "Broken ", "Godfull ", "Powerfull ", "Spiked ", "Shiny " };
	const char*  part2[] = { "Blade ", "Axe ", "Knife ", "Bow ", "Club ", "Spear " };
	const char*  part3[] = { "of Doom ", "of the Wind ", "of the Fire ", "of the Dark ", "of the Light ", "of the trigh ", "of the Lies " };
	char buf[100];
	strcpy(buf, part1[rand() % (sizeof(part1) / sizeof(char*))]);
	strcat(buf, part2[rand() % (sizeof(part2) / sizeof(char*))]);
	strcat(buf, part3[rand() % (sizeof(part3) / sizeof(char*))]);
	char* name = new char[strlen(buf) + 1];
	strcpy(name, buf);
	return name;
}

Däremot så vill jag döpa flera olika typer av objekt där part1, part2 och part3 kan variera mellan olika saker. Jag försöker då skapa en fristående funktion som tar de tre olika part1, part2 och part3 som parametrar. Det är här mitt problem kommer in. Jag har försökt flera olika möjligheter men det närmaste jag har kommit just nu är nedanstående kod. Men den fungerar inte helt som den ska eftersom storleken på delarna inte räknas ut som de ska.
Någon som kan hjälpa mig? vilket är det rätta sättet att skicka part1, part2 och part3 som funktionen och sedan dynamiskt avgöra storleken och slumpa fram en del?
Kod:
char* generateThingName(const char* part1[], const char* part2[], const char* part3[])
{
	char buf[100];
	strcpy(buf, part1[rand() % (sizeof(part1) / sizeof(char*))]);
	strcat(buf, part2[rand() % (sizeof(part2) / sizeof(char*))]);
	strcat(buf, part3[rand() % (sizeof(part3) / sizeof(char*))]);
	char* name = new char[strlen(buf) + 1];
	strcpy(name, buf);
	return name;
}

int main()
{
	srand(time(0));
	const char*  part1[] = { "Divine ", "Broken ", "Godfull ", "Powerfull ", "Spiked ", "Shiny " };
	const char*  part2[] = { "Blade ", "Axe ", "Knife ", "Bow ", "Club ", "Spear " };
	const char*  part3[] = { "of Doom ", "of the Wind ", "of the Fire ", "of the Dark ", "of the Light ", "of the trigh ", "of the Lies " };
	char* name = generateThingName(part1, part2, part3);
	return 0;
}


Blev lite luddigt beskrivet men hoppas att någon van C-programmerare kan hjälpa mig.

MVH
Citera
2016-06-22, 20:23
  #2
Medlem
enowens avatar
Citat:
Ursprungligen postat av Admare
Hej jag läser för tillfället en grundläggande spelprogrammeringskurs i C++, för att lära mig mer om spelprogrammering samt friska upp mina riktigt rostiga c++ kunskaper (läst några grundläggande kurser för några år sedan).

Håller just nu på med den första uppgiften och i den får vi inte använda std::string eller liknande utan ska träna på att använda char-pekare och liknande.
I uppgiften ska namn på olika saker genereras genom att kombinera 1 del från 3 olika arrayer dynamiskt. För att sedan dynamiskt alkolera en char-pekare och retunera denna från funktionen.
Jag har löst den delen utav uppgiften på följande sätt. Vilket fungerar (även om det säkert inte är optimal kod).

Kod:
char* generateThingName()
{
	const char*  part1[] = { "Divine ", "Broken ", "Godfull ", "Powerfull ", "Spiked ", "Shiny " };
	const char*  part2[] = { "Blade ", "Axe ", "Knife ", "Bow ", "Club ", "Spear " };
	const char*  part3[] = { "of Doom ", "of the Wind ", "of the Fire ", "of the Dark ", "of the Light ", "of the trigh ", "of the Lies " };
	char buf[100];
	strcpy(buf, part1[rand() % (sizeof(part1) / sizeof(char*))]);
	strcat(buf, part2[rand() % (sizeof(part2) / sizeof(char*))]);
	strcat(buf, part3[rand() % (sizeof(part3) / sizeof(char*))]);
	char* name = new char[strlen(buf) + 1];
	strcpy(name, buf);
	return name;
}

Däremot så vill jag döpa flera olika typer av objekt där part1, part2 och part3 kan variera mellan olika saker. Jag försöker då skapa en fristående funktion som tar de tre olika part1, part2 och part3 som parametrar. Det är här mitt problem kommer in. Jag har försökt flera olika möjligheter men det närmaste jag har kommit just nu är nedanstående kod. Men den fungerar inte helt som den ska eftersom storleken på delarna inte räknas ut som de ska.
Någon som kan hjälpa mig? vilket är det rätta sättet att skicka part1, part2 och part3 som funktionen och sedan dynamiskt avgöra storleken och slumpa fram en del?
Kod:
char* generateThingName(const char* part1[], const char* part2[], const char* part3[])
{
	char buf[100];
	strcpy(buf, part1[rand() % (sizeof(part1) / sizeof(char*))]);
	strcat(buf, part2[rand() % (sizeof(part2) / sizeof(char*))]);
	strcat(buf, part3[rand() % (sizeof(part3) / sizeof(char*))]);
	char* name = new char[strlen(buf) + 1];
	strcpy(name, buf);
	return name;
}

int main()
{
	srand(time(0));
	const char*  part1[] = { "Divine ", "Broken ", "Godfull ", "Powerfull ", "Spiked ", "Shiny " };
	const char*  part2[] = { "Blade ", "Axe ", "Knife ", "Bow ", "Club ", "Spear " };
	const char*  part3[] = { "of Doom ", "of the Wind ", "of the Fire ", "of the Dark ", "of the Light ", "of the trigh ", "of the Lies " };
	char* name = generateThingName(part1, part2, part3);
	return 0;
}


Blev lite luddigt beskrivet men hoppas att någon van C-programmerare kan hjälpa mig.

MVH

Sorry men jag fattar inte vad det är du vill göra. Du får skriva ner uppgiften här istället, för koden som du har skrivit har en blandning mellan traditionell C och C++11 och makes no sense.
Citera
2016-06-22, 20:33
  #3
Medlem
Den delen utav uppgiften som ovanstående kod gäller är definierad så här
"Vapnets namn ska skapas på ett speciellt sätt. Namnet ska bestå av tre delar: 1. Ett adjektiv, t.ex. "Divine ","Ultimate ","Dodgy " eller "Spiked " (hitta på själv!) 2. En vapentyp, t.ex. "Blade ","Club " eller "Axe " (hitta på själv!) 3. En 'subtitel', t.ex. "of Doom", "of the Wind" eller "of the Phoenix" (hitta på själv!) Namnet bildas sedan genom att man tar en slumpad sträng från första listan, en slumpad sträng från andra listan, och till sist en slumpad sträng från tredje listan. Om man t.ex. tar den första strängen från varje lista så får man "Divine Blade of Doom". Strängen som ska hålla vapnets namn ska vara en char-pekare allokeras med operatorn 'new', så att den bara tar upp precis så mycket minne som behövs."

Sen kommer man också skapa en rustning/skydd och namnge på samma sätt (varav jag vill skapa den generella generateName funktionen.

Själva uppgiften är mycket längre och består utav flera delar, men det är just detta jag har problem med. Om det behövs kan jag posta hela uppgiften även om jag inte tycker det är relevant. Läraren har bestämt att vi måste träna på att använda char-pekare och därför inte får använda std::String.

Det är möjligt att min kod är helt fel ute, men exempel 1 ovan fungerar i alla fall som väntat. Jag har inte mycket erfarenhet av C-programmering och det var ett tag sen jag läste någon kurs eller använde C++ och jag är inte van att använda char-pekare istället för t.ex. std::string. Sen är jag också van att arbeta objektorienterat vilket vi inte får göra i denna uppgift.
Citera
2016-06-22, 23:27
  #4
Medlem
enowens avatar
Citat:
Ursprungligen postat av Admare
Den delen utav uppgiften som ovanstående kod gäller är definierad så här
"Vapnets namn ska skapas på ett speciellt sätt. Namnet ska bestå av tre delar: 1. Ett adjektiv, t.ex. "Divine ","Ultimate ","Dodgy " eller "Spiked " (hitta på själv!) 2. En vapentyp, t.ex. "Blade ","Club " eller "Axe " (hitta på själv!) 3. En 'subtitel', t.ex. "of Doom", "of the Wind" eller "of the Phoenix" (hitta på själv!) Namnet bildas sedan genom att man tar en slumpad sträng från första listan, en slumpad sträng från andra listan, och till sist en slumpad sträng från tredje listan. Om man t.ex. tar den första strängen från varje lista så får man "Divine Blade of Doom". Strängen som ska hålla vapnets namn ska vara en char-pekare allokeras med operatorn 'new', så att den bara tar upp precis så mycket minne som behövs."

Sen kommer man också skapa en rustning/skydd och namnge på samma sätt (varav jag vill skapa den generella generateName funktionen.

Själva uppgiften är mycket längre och består utav flera delar, men det är just detta jag har problem med. Om det behövs kan jag posta hela uppgiften även om jag inte tycker det är relevant. Läraren har bestämt att vi måste träna på att använda char-pekare och därför inte får använda std::String.

Det är möjligt att min kod är helt fel ute, men exempel 1 ovan fungerar i alla fall som väntat. Jag har inte mycket erfarenhet av C-programmering och det var ett tag sen jag läste någon kurs eller använde C++ och jag är inte van att använda char-pekare istället för t.ex. std::string. Sen är jag också van att arbeta objektorienterat vilket vi inte får göra i denna uppgift.

ok läste lite snabbt och slängde ihop detta lite snabbt, se om det är det du är ute efter

Kod:
#include <iostream>
#include <cstring>
#include <ctime>

template <size_t cast_sizesize_t type_sizesize_t title_size>
const 
charGenerateNewName(const charcast[], const chartype[], const chartitle[])
{
    
// Get some random names
    
const charrandom_cast{cast[std::rand()%cast_size]};
    const 
charrandom_type{type[std::rand()%type_size]};
    const 
charrandom_title{title[std::rand()%title_size]};

    
// Calculate size, spaces and null terminator
    
size_t size_of_all{strlen(random_cast) + strlen(random_type) + strlen(random_title) + 3};

    
// Allocate some mem and create a new char array
    
charname{new char[size_of_all]{}};

    
// Copy
    
std::strcat(namerandom_cast);
    
std::strcat(name" ");
    
std::strcat(namerandom_type);
    
std::strcat(name" ");
    
std::strcat(namerandom_title);

    return 
name;
}

int main()
{
    
std::srand(std::time(0));
    const 
chararr_cast[]{"Devine""Ultimate""Spiked"};
    const 
chararr_type[]{"Blade""Club""Axe"};
    const 
chararr_title[]{"of doom""of kebab"};

    
// new name, send size of each array as template parameter
    
const charnewname{GenerateNewName<332>(arr_castarr_typearr_title)};

    
// Print newname
    
std::cerr << newname << std::endl;

    
// Deallocate
    
delete[] newname;



Kompilera med -std=c++11 flaggan.
__________________
Senast redigerad av enowen 2016-06-22 kl. 23:39.
Citera
2016-06-22, 23:46
  #5
Medlem
Tack så mycket enowen, det verkar vara precis vad jag var ute efter. Ser mycket bättre ut än min kod också. Nu ska jag bara sätta mig och försöka förstå allting i din kod och se vad du gjorde annorlunda mot mig, så jag lär mig något också.

Tack än en gång.
Citera
2016-06-23, 00:05
  #6
Medlem
enowens avatar
Citat:
Ursprungligen postat av Admare
Tack så mycket enowen, det verkar vara precis vad jag var ute efter. Ser mycket bättre ut än min kod också. Nu ska jag bara sätta mig och försöka förstå allting i din kod och se vad du gjorde annorlunda mot mig, så jag lär mig något också.

Tack än en gång.

Inga problem, bara att fråga om någonting verkar oklart. Jag använde vissa saker här från c++11 standarden som inte fanns innan.

Bland annat: https://en.wikipedia.org/wiki/C%2B%2...initialization
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback