It seems like you're making a rod for your own back. If you're writing in C, then so be it. But in C++, use std::string for strings unless you have specific reasons to use something else.
C++ also has standard containers, amongst which is a double linked list, std::list, and a single linked list, std::forward_list. C++ programmers no longer write linked lists, dictionaries and so on, they're standard components.
Also, use const where appropriate. It'll stop you hurting yourself.
Anyway, back to your code.
You should remember that classes in C++ are the mechanism for creating user defined types. These user defined types should work just like built in types. To make your user defined types work like built in types, there are some members that are needed and are generated if you don't define them. They are:
* default constructor
* copy constructor
* assignment operator
* destructor
C++11 adds:
* move constructor
* move operator
These make your code work as you'd expect:
1 2 3 4 5 6 7 8
|
{
MobileApp app("Words for Friends", "A crossword puzzle game", {"puzzle", "multiplayer", "crossword"});
MobileApp d1(app);
MobileApp d2;
MobileApp d3;
d3 = d2 = d1;
std::vector<MobileApp> v { app, d1, d2, d3 };
}
|
Line 2: make a MobileApp, app, from inputs.
Line 3: make a MobileApp, d1, from app.
Line 4: make an empty MobileApp, d2.
Line 5: make an empty MobileApp, d3.
Line 6: assign the content of d1 to d2 and d3.
Line 7: make a vector v that is initialised with: app, d1, d2, d3
Line 8: cleanup app, d1, d2, d3, v
To make that happen, MobileApp should look like:
1 2 3 4 5 6 7 8 9 10
|
class MobileApp
{
public:
MobileApp();
MobileApp(const std::string& name, const std::string& desc,
std::initializer_list<string> l);
MobileApp(const MobileApp& n);
MobileApp& operator=(const MobileApp& n);
~MobileApp();
//...
|
The code is the same was what you have, but organised such that MobileApp is a user defined type and can be used interchangeably with built in types.
Now, your copy function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
struct key
{
key(const char* s) : keyword(strdup(s)), next(nullptr) {}
~key() { free(keyword); }
key* clone() const { return new key(keyword); }
char* keyword;
key* next;
};
void copylist(key&* head, const key* c)
{
if (c)
{
copylist(head, c->next);
head->next = c->clone();
}
}
void clearlist(key&* head)
{
if (head)
{
clearlist(head);
delete head->next;
}
}
int MobileApp::copyApp(MobileApp & c)
{
free(appName);
free(appDescription);
clearlist(head);
appName = strdup(c.appName);
appDescription = strdup(c.appDescription);
numKeywords = c.numKeywords;
copylist(head, c.head);
}
|
To rewrite your class in a standard way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
class MobileApp
{
public:
MobileApp(
const std::string& appName,
const std::string& appDescription,
std::initializer_list<std::string> keywords);
MobileApp() = default;
~MobileApp() = default;
MobileApp(const MobileApp& n) = default;
MobileApp& operator=(const MobileApp& n) = default;
private:
std::string appName;
std::string appDescription;
std::forward_list<std::string> keywords;
};
MobileApp::MobileApp(
const std::string& appName,
const std::string& appDescription,
std::initializer_list<std::string> keywords) :
appName(appName),
appDescription(appDescription),
keywords(keywords)
{
}
|
That's much simpler than messing around with pointers, right?