 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Dennis Schulz Guest
|
Posted: Sun Jan 16, 2005 11:21 am Post subject: how to access enum fields? |
|
|
Hi, I have the following problem:
I want to find out the number of the month from given string.
I defined 12 constants as a enum type num:
enum num{Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8,
Sep=9, Okt=10, Nov=11, Dec=12};
now I want to access the number of the month
This is working:
num n = Dec;
There is an error:
num n = static_cast<num>(MyString);
How can I convert it to a num type??
Thank you
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Patrick Leslie Polzer Guest
|
Posted: Mon Jan 17, 2005 12:34 am Post subject: Re: how to access enum fields? |
|
|
Dennis Schulz wrote:
| Quote: | enum num{Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8,
Sep=9, Okt=10, Nov=11, Dec=12};
[...]
There is an error:
num n = static_cast<num>(MyString);
How can I convert it to a num type??
Set up a conversion table. |
Leslie
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Larry Evans Guest
|
Posted: Mon Jan 17, 2005 12:36 am Post subject: Re: how to access enum fields? |
|
|
On 01/16/2005 04:21 AM, Dennis Schulz wrote:
[snip]
| Quote: | There is an error:
num n = static_cast<num>(MyString);
How can I convert it to a num type??
First convert MyString to a number, possibly using |
MyString.str() or something that returns a char* and
then use c's library function, atoi (I think that's right).
Alternately, convert the c* to a std::istrstream and extract
( i.e. something like a_istr>>a_int;) then do the
static_cast. I haven't tested it though.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Mon Jan 17, 2005 8:00 pm Post subject: Re: how to access enum fields? |
|
|
On 16 Jan 2005 06:21:44 -0500, Dennis Schulz <d.schulz81 (AT) gmx (DOT) net> wrote:
| Quote: | Hi, I have the following problem:
I want to find out the number of the month from given string.
I defined 12 constants as a enum type num:
enum num{Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8,
Sep=9, Okt=10, Nov=11, Dec=12};
now I want to access the number of the month
This is working:
num n = Dec;
There is an error:
num n = static_cast<num>(MyString);
How can I convert it to a num type??
|
Basically, you have to somehow map each month name to your enum. It could
be as simple as building an array of month names and then searching it
linearly:
char const* const month_names = { "Jan", "Feb", ..., "Dec", 0 };
int month_index(char const* month)
{
char const* const* p = month_names;
for(; *p; ++p)
if(!strcmp(month, *p))
break;
return *p ? p - month_names : -1;
}
(There are more powerful techniques and tools you can use for mapping a
string to an integer, like binary and ternary trees, hashing.)
Using the array and the function you can convert your enums to strings and
back:
char const* enum_to_str(num n)
{
return month_names[n - 1];
}
num str_to_enum(char const* month)
{
int const index = month_index(month);
return -1 != index ? static_cast<num>(index + 1) : throw
std::logic_error("bad month name");
}
| Quote: | num n = static_cast<num>(MyString);
|
You can static_cast<> syntax to convert a string to your enum only if your
string class has a conversion operator to your enum (that is,
MyString::operator num()), because enum's can't have constructors which
static_cast<> could use. Alternatively, you can define a class for
representing months with a constructor that takes a string, something
along the lines:
class month
{
private:
num m_;
public:
month(num m) : m_(m) {}
month(char const* m) : m_(str_to_enum(m)) {}
};
And then:
month m = static_cast<month>(MyString.c_str());
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Abhishek Pandey Guest
|
Posted: Mon Jan 17, 2005 8:09 pm Post subject: Re: how to access enum fields? |
|
|
"Dennis Schulz" <d.schulz81 (AT) gmx (DOT) net> wrote
| Quote: | Hi, I have the following problem:
I want to find out the number of the month from given string.
I defined 12 constants as a enum type num:
enum num{Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8,
Sep=9, Okt=10, Nov=11, Dec=12};
now I want to access the number of the month
This is working:
num n = Dec;
There is an error:
num n = static_cast<num>(MyString);
|
MyString is a character string e.g. "Feb" while Feb is a enum constant whose
value is 2.
You can not straightaway cast the string into integer in the way you are
trying to do.
You have to write some logic for conversion yourself.
Thanks
Abhishek
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jan 17, 2005 8:16 pm Post subject: Re: how to access enum fields? |
|
|
Dennis Schulz wrote:
| Quote: | Hi, I have the following problem:
I want to find out the number of the month from given string.
I defined 12 constants as a enum type num:
enum num{Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8,
Sep=9, Okt=10, Nov=11, Dec=12};
now I want to access the number of the month
This is working:
num n = Dec;
There is an error:
num n = static_cast<num>(MyString);
How can I convert it to a num type??
|
Use an std::map< std::string, num >. To initialize
the map, use something like the following:
| Quote: | typedef std::map< std::string, num
Map ;
struct Init
{
char const* name ;
enum value ;
operator Map::value_type() const
{
return Map::value_type( std::string( name ), value )
;
}
} ;
static Init const init[] =
{
{ "Jan", Jan },
{ "Feb", Feb },
// ...
} ;
Map const enumMap( init, init + 12 ) ;
|
Alternatively, if you want to allow abbreviations, full names,
caps and small letters, etc., you might want to write your own
comparator, and just use std::find on a C style array. Since
the table is unlikely to grow beyond twelve entries, the
performance using a linear search should not be a problem.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Bartlett Guest
|
Posted: Tue Jan 18, 2005 11:06 pm Post subject: Re: how to access enum fields? |
|
|
Dennis Schulz wrote:
| Quote: | Hi, I have the following problem:
I want to find out the number of the month from given string.
I defined 12 constants as a enum type num:
enum num{Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8,
Sep=9, Okt=10, Nov=11, Dec=12};
now I want to access the number of the month
This is working:
num n = Dec;
There is an error:
num n = static_cast<num>(MyString);
How can I convert it to a num type??
|
You can't directly. Enums are NOT strings, they are symbols, which are
thrown away after compilation. Similarly, if I have a string "A" and a
variable A I can't convert from one to the other.
Therefore, you need to set up a set of if statements to check the string
and convert to the number.
Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
brablc Guest
|
Posted: Wed Jan 19, 2005 11:49 pm Post subject: Translation table (Was: how to access enum fields?) |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: |
Use an std::map< std::string, num >. To initialize
the map, use something like the following:
...
|
This sounds like a good and general way to initialize a translation
table. So with a small change I get code stated bellow. But I have two
problems:
1) I have to specify number of elements in the the map constructor.
2) Access to the values via operator[] does not work when the map is
const.
template<class Value> struct MapInit
{
const char * key;
Value value ;
typedef typename
std::map< std::string, Value >::value_type value_type;
operator value_type() const {
return value_type( std::string( key ), value );
}
};
static MapInit<std::string> const initTradeType[] =
{
{ "N", "New" },
{ "C", "Cancel" }
} ;
std::map<std::string, std::string>
tradeTypeMap( initTradeType, initTradeType+2 ) ;
Best regards,
Ondrej
---
Family Homepage: http://brablc.com
Bookmark Server: http://sitebar.org (GPL)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Jan 20, 2005 6:14 pm Post subject: Re: Translation table (Was: how to access enum fields?) |
|
|
brablc wrote:
| Quote: | kanze (AT) gabi-soft (DOT) fr wrote:
Use an std::map< std::string, num >. To initialize
the map, use something like the following:
...
This sounds like a good and general way to initialize a
translation table. So with a small change I get code stated
bellow. But I have two problems:
1) I have to specify number of elements in the the map constructor.
|
Not really, see below.
| Quote: | 2) Access to the values via operator[] does not work when the
map is const.
|
So don't use the [] operator.
The real question is what do you do if you don't find the
entry. I usually wrap such classes in a higher level class,
whose [] operator returns a pointer to the element (and not a
copy), or a null pointer if the element isn't found; there are
also cases where not finding the element results in an assertion
failure.
| Quote: | template<class Value> struct MapInit
{
const char * key;
Value value ;
typedef typename
std::map< std::string, Value >::value_type value_type;
operator value_type() const {
return value_type( std::string( key ), value );
}
};
static MapInit<std::string> const initTradeType[] =
{
{ "N", "New" },
{ "C", "Cancel" }
} ;
|
Careful. There might be order of initialization issues here,
since the array is dynamically initialized. I tend to only use
PODs in my Init classes. In this case, for example, I would
declare MapInit to contain two char const*. (Of course, this
somewhat limits the use of a template for them. And typically,
the definition of the initialization table will be in the same
compilation unit as the map, which means that order is
guaranteed.)
| Quote: | static size_t iniTradeCount
= sizeof( IinitTradeType ) /sizeof( initTradeType[ 0 ] ) ;
|
is the classical, C-style solution. I usually use the
pseudo-standard global begin and end functions:
| Quote: | template< typename T, size_t N
T const*
begin( T const (&array)[ N ] )
{
return array ;
}
template< typename T, size_t N
T const*
end( T const (&array)[ N ] )
{
return array + N ;
}
std::map
tradeTypeMap( initTradeType, initTradeType+2 ) ;
std::map< std::string, std::string
tradeTypeMap( begin( initTradeType ),
end( initTradeType ) ) ;
|
With both this and the classical C-like solution, the compiler
does the counting, not you.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Thu Jan 20, 2005 8:08 pm Post subject: Linux Assembly Language? |
|
|
Jonathan Bartlett wrote:
Does that make sense? "Linux assembly language?"
I suppose you mean the assembly language of the Intel 80386 (or
possibly you assume a 486 or a Pentium), and Linux system calls.
Although I've heard that Linux ports are available for 680x0,
DEC Alpha, SPARCs, and others... hard to see how any true "assembly
language" could run on all of these platforms.
Then again, I'm not a Linux guru. Is there actually an assembly
language for Linux, different in some significant way from Intel
assembly language?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Bartlett Guest
|
Posted: Fri Jan 21, 2005 10:28 am Post subject: Re: Linux Assembly Language? |
|
|
| Quote: | Does that make sense? "Linux assembly language?"
|
The book is for people new to programming. Saying "assembly language
for 80386 and higher CPUs using Linux kernel system calls" would not
make sense. Since we use Linux on its most common architecture, and use
Linux-specific system calls, and use the AT&T syntax, then, yes, "Linux
assembly language" makes sense. I have enough trouble trying to
convince people that there are more processors in the world than those
that are Intel-compatible that I felt making the distinction on the
cover of the book would not be helpful. If you know enough about
computers and Linux to be running Linux on a different platform, you
probably have enough intelligence to guess what architecture I'm talking
about or to ask someone. If you don't, the distinction is just confusing.
Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ondrej Brablc Guest
|
Posted: Sat Jan 22, 2005 4:48 am Post subject: Re: Translation table (Was: how to access enum fields?) |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | brablc wrote:
This sounds like a good and general way to initialize a
translation table. So with a small change I get code stated
bellow. But I have two problems:
1) I have to specify number of elements in the the map constructor.
Not really, see below.
2) Access to the values via operator[] does not work when the
map is const.
So don't use the [] operator.
|
Thank you for your hints, I think I have an implementation that is good
enough (plese let me know on my email if the code is too long for this
group).
| Quote: | #include <string
#include
#include
#include
/* INTERFACE */
template< class Value> class TranslationMap
{
public:
typedef typename std::map< std::string, Value > valueMap;
struct Init
{
const char * key;
Value value;
typedef typename valueMap::value_type value_type;
operator value_type() const
{
return value_type( std::string( key ), value );
}
};
template< typename T, size_t N
TranslationMap(std::string aTableName, T const (&array)[ N
]):
mTableName(aTableName), mMap(array, array+N)
{
}
template< class InputIterator
TranslationMap(std::string aTableName,
InputIterator first, InputIterator last):
mTableName(aTableName), mMap(first, last)
{
}
const Value & operator[]( std::string key) const
throw(std::domain_error)
{
typedef typename valueMap::const_iterator const_iterator;
const_iterator found = mMap.find(key);
if (found == mMap.end())
{
throw std::domain_error( mTableName+": Unknown key
["+key+"]" );
}
return (*found).second;
}
private:
std::string mTableName;
valueMap mMap;
};
/* INITIALIZATION */
static TranslationMap
{
{ "Jan", 1 },
{ "Feb", 2 },
{ "Mrz", 3 },
{ "Apr", 4 },
{ "Mai", 5 },
{ "Jun", 6 },
{ "Jul", 7 },
{ "Aug", 8 },
{ "Sep", 9 },
{ "Okt", 10 },
{ "Nov", 11 },
{ "Dez", 12 },
};
static const TranslationMap<int> MONTHS( "MONTHS", initMonths );
/* USAGE */
int main()
{
try
{
std::cout << "Jan=" << MONTHS["Jan"] << std::endl;
std::cout << "Mar=" << MONTHS["Mar"] << std::endl;
}
catch ( std::exception & e)
{
std::cerr << "Exception has occured: " << e.what()
std::endl;
}
}
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jan 24, 2005 8:17 pm Post subject: Re: Translation table (Was: how to access enum fields?) |
|
|
Ondrej Brablc wrote:
| Quote: | Thank you for your hints, I think I have an implementation
that is good enough.
|
Seems pretty good to me.
In my own code, the map is a singleton. My own code was
written long before templates existed, and uses small lex/yacc
program to generate the code, including the tables. The template
is probably preferable, but then you'd need a function for
initializing the tables (called from the constructor, and
generated by the lex/yacc code). So the constructor would look
something like:
template< typename Value >
TranslationMap::TranslationMap()
{
extern void initializeTranslationMap( ValueMap& ) ;
initializeTranslationMap( mMap ) ;
}
Where, of course, initializeTranslationMap is the code generated
by lex/yacc. (Note that even if the actual object is const, it
doesn't become const until the constructor has terminated. Note
too that by passing it the mMap parameter, we've made it
dependent. And that I can't find any reasonable place to put
the extern declaration but in the function itself.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|