views:

78

answers:

5

I've got a list of number that I need to keep track of. The numbers are loosely related, but represent distinctly different items. I'd like to keep a list of the numbers but be able to refer to them by name so that I can call them and use them where needed easily. Kind of like an inventory listing, where the numbers all refer to a part ID and I'd like to call them idPart1, idPart2, idPart3 so their purpose is easily identifiable when they are used.

What would be the best way to do this?
1)Define a structure. Say, Inventory. A number of int members will be included, part1, part2 etc. To use, an instance of the structure will be created, values assigned to the members, and the numbers will be used by saying struct.member as needed.
2)Define an enumeration. Use part1, part2 as the enum literals. Store the actual values in a vector or list, each one at the index corresponding to the value of the number's name within the enum. Use the enum literals to retrieve the values, list[enumLit].
3)Something completely different

There's nothing else I need to do with the numbers - just look them up every once in a while. Since there's no processing, I kind of think a new class for them is overkill, but I'm willing to be convinced otherwise.

Any suggestions?

+1  A: 

You can use a map with a string as the key.

std::map<string,int> mymap;
mymap["part1"] = value1;
cout << mymap["part1"];
Mark Ransom
I don't love the idea of the user needing to know the exact string that serves as the key.
Rachel
@Rachel, your examples all show the user needing to know the string, as structure member names or enumeration tags. I don't understand the objection.
Mark Ransom
@Mark - I guess personal preference, but enum literals and structure members pop up with intellisense, leaving a whole lot less room for errors than entering a string name would. And the compiler catches them.
Rachel
@Rachel I'm confused about your requirements. Is the user looking these up at runtime? If that's the case they're not going to be interacting with any of your code entities (like enums or structs) so you have to have some way of representing the numbers external to the program.
Nick Meyer
My error. By user I meant another developer. This is going to be handed off, so I need others to easily find their way throught the code.
Rachel
+1  A: 

You could use the:

std::map<string, int> someMapName;

with the key as the string and the actual number as the int. That way you could do you could use

someMapName["idPart1"]

to grab the number.'

EDIT: If you are ok with Enumerations then option 2 would work perfectly with the std::map just instead of string, the key would be your enum type obviously.

Robb
I'd like to avoid the user needing to enter the string. Too much room for error usually.
Rachel
@Rachel doesn't having the user enter anything leave room for error? And is there really anything the user could enter that has less possibility for error than entering the numbers directly?
Nick Meyer
A: 

Based on your comments to the other answers, I'd say enums are the way to go, but I'd structure them a little differently.

namespace id {
    enum {
        part1 = 123,
        part2 = 456,
        part3 = 987,
        ...
    };
}

cout << id::part1;
Mark Ransom
A: 

Use a database.
Specifically, a table like the following:

+------------------+-------------------+
| Item Name        | Item Number       |
+------------------+-------------------+

Internally, this can be represented as:

std::map<std::string, // The item name
        unsigned int> // The number.

When you want the number, retrieve it using the name:

std::map<std::string, unsigned int> index_by_name;
//...
std::string part_name = "Part0123";
unsigned int part_number = 0;
part_number = index_by_name[name];

Seriously, use a database. Check out SQLite and MySQL.

Thomas Matthews
+2  A: 

Let me try to rephrase what you're trying to do here. You want developers who use your code to be able to refer to a pre-defined set of numeric values:

  • using intuitive names
  • that will be validated at compile time
  • and that the IDE will recognize for the sake of code completion.

If the values will not change at run-time, and they are integer values, you can use an enum as Mark Ransom showed.

If the values will not change at run-time, and they are non-integer values, you can use either #define or const variables:

#define PART1 1.3
#define PART2 "1233-456"

or

namespace PartNumbers
{
  const double Part1 = 1.3;
  const char* Part2 = "123-456"
}

If the values may change at run-time, you can use either of the two options you identified. Both of these options have the drawback of requiring an object to be instantiated which holds the current part number values. The other options are simpler to implement and don't require any run-time lookup. Everything is resolved at compile time.

All of these options require users of your code to recompile if they are to access new part types. Your first option may require existing code to be recompiled when new part types are added, even if the existing code doesn't access them; it's more prone to memory layout changes.

Darryl
They are set during run-time. I had boiled down my options to the two I mentioned, but both felt awkward. I was hoping to get either a neater way to do this or else confimation that there was no simpler way and that one of the options was acceptable.
Rachel