ok. I need a bit of help. I'm designing a console app that will act sort of as a database for storing some information. (using C++ and trying to use OOP as much as possible.)
What I have is over 900 recipies for spells used in a game. These recipies utilize many of the same items over and over again. The odd's of mistyping an item somewhere is far too great so I want to set it up so that each item has to be entered only once, and from that point on I can refer to that item from a list. There will be serveral lists, for different categories of items.
Here's what I'm wanting out of the list class.
From an outer object, when a menu choice is chosen to choose an item from the list, I want to call a function inside the list object. Let's call it list.Add();
The list should then provide it's own menu to the user, consisiting of all items that are currently in the list with numbers to easily select those items, then an added menu choice to add a new item to the list, and a choice to cancel. (oh, and a choice to edit an item in case I find I mistyped an item earlier.)
The first idea I had was to use an array or a string table to contain the strings for the items to choose from and return the index of the item chosen. However, if the user (me) adds a new item, i'd like it to automatically sort it into the list alphabetically. This would of course cause any previously used indexes to be invalid.
So I need to, instead, store the string and an ID integer for each item in the list, and then return that ID. This would make it so that the sorting of the list alphabetically would not invalidate the ID to String connections.
Then when someone makes a choice from the menu using a number (which *IS* the index in the array) it can get the ID from there and return that to the calling object.
Then I need another function later to call List.GetItem(ID) that would look up the ID and return the corrosponding string.
Now for the questions:
How is the best way to store that information in the object? A two dimentional array? an array of structs (e.g. item.ID and item.String)? should the array by dynamic?
How would I sort a new entry into the array alphabetically?
What format and method would I use best to save this list into a file so that the list is maintained between sessions? (I'm not gonna do all 900 recipies in one sitting.)
Obviously, I'm not looking to add all the items to all the lists ahead of time. I am trying to make this so that I add the items to each list as I come across those items while entering the top level recipe.
And when giving the menu for the user to choose from, would it be better to try to list the items in a single column or can I try to put them into three column's to shorten the lines of output? (average item would be like "Ink Additive of the Nameless" or "Invigorating Thickener" etc.. there are approximately 20 items of each category. However that number varies.)
Basically, can someone help walk me through creating said object?
Note: Walk me through does not neccesarily mean do it for me. If you do make the class for me, I'd appreciate explanations so that I can understand why you did what you did, so that I can use it in the future.
Edit: Oh yea, if it makes any difference, i'm using DevC++
And this is why I never get anything done. I was about to ask some more questions, but alas i'm being called away. When I return i'll try to ask and hopefully someone else will be able to help.
ok. From what i'm reading, it looks like the map might be what i want from the STL (i've not worked with templates, so I'm kinda new to these.)
It sorts by the key which must be unique. yet I want it to sort by the string, which in my case should be unique anyway. so I want to use map<str,int> or supply some sort of compare function for it to sort by. (will the default sorting 'a<b' work with strings?) I still have no idea what that allocator does or is supposed to do.
it also appears to be dynamic as any examples i've found on the documentation has never supplied an array size when creating the variable.
#include <iostream>
#include <map> // This is what the examples show. I would have guessed <stl>
class List
{
public:
void AddItem (string Item);
int SelectItem (int Choice);
private:
map<string,int> _Item;
};
void List::AddItem (string item)
{
int ID = _Item.size() + 1;
_Item[item] = ID;
}
int List::SelectItem (int Choice)
{
map<string,int> it = _Item.begin();
it+= Choice;
return it.second;
}
ok.. i guess the lack of replies means i'm on the wrong track..
I'll go back to figguring out a class that does all of the above.. probably using a struct for item members.
If it's still relevant:
I think std::map is a good solution for you:
-) yes, it is dynamic, but this is fine, isn't it?
-) yes, std::string has a reasonable default sorting behaviour: string("a")<string("b")
-) Don't wrap a class around map. As far as I understand your task, map is all you need. "Dictionary": AddItem -> map::insert; SelectItem -> map::find
-) You should think about not using int as the "payload" of your map, but a class, which really represents you data.
Let me see if you still read this thread...
Yea, I'm still keeping an eye on this thread.. I havn't done the other yet..
Dynamic is fine, and in fact favorable
Glad to hear i can use the standard compare on the string.
and map::find won't quite do, as i won't be searching for key or value, but rather position.
The menu would provide the list in alphabetical order. This, however, is not neccessarily the same order they were added to the list. This is why I have to use some sort of ID.
e.g. If I were using just the index and in a previous recipe i used the item listed at index 12, which means i stored the number 12 in a variable in the outer object, then on the next recipe i added a new item to the list that sorted into position 10.. now my previous recipe is pointing to the wrong list item. It is now pointed to what used to be at index 11 which just got moved up to index 12.
So, what I want to do, instead, is when a new item is added to the list, it's given an ID that is unique to it. (basically list size + 1). When i provide the list to the user to select one, and he (or I) hit say number 12.. it'll go to index 12 and return that ID to be stored in the outer object.
Then later, when i'm finally ready to write the txt files with the recipe's, it can send the ID to the list and get the string to print at that point. This would save space in Ram (900+ recipies.. wow) and would give me a chance to make sure all ingredients were typed in correctly and not mispelled.
1 Quill of the Coercer (all recipies has 1 quill. this will be one list)
1 Extending Thickener (all recipies has 1 thickener. this will be another list)
1 Luclin's Ink Additive (all recipies has 1 additive. this will be another list)
2 Ink of Pain (all recipies will have at least 1 ink. this will be another list)
1 Ink of the Cat
1 Ink of the Rhino
1 Runic Papyrus (all recipies has 1 parchment. this will be another list)
the array of objects for containing the spell recipe info would look like this
struct ingredient
{
int ID;
int qty;
};
struct character
{
int charclass;
int charlevel;
}
struct recipe
{
char name[50];
int trivial;
character chars[6]; // actually this should be dynamic. will be 1 for most cases, but can be up to 14.
int quill; // These can just use Int cause there will never be more than 1 of each.
int thickener;
int additive;
int parchment;
ingredient misc; // rarely, some spells have a single miscellaneaous ingredient.
ingredient inks[6]; // could be dynamic. should never be more than 4 though.
};