|
If it's a simple piece of work you want to do for each item, just use a chain of if statements using strcmp() to compare.
If it's harder (which I assume it is since you've got 50 entries in your table), define a function pointer type:
typedef int (PFNTASK*)(
const char* szName,
);
int DoPla( const char* szName, );
int DoOct( const char* szName, ); Then define a structure:
typedef struct
{
const char* szName;
PFNTASK pfnTask;
} TaskEntry; Now define your array:
TaskEntry namesAndTasks[] =
{
{ "pla", DoPla },
{ "oct", DoOct }
}; Finally, search for the operation to perform:
for( int iTask = 0; iTask < 50; ++i )
{
if ( strcmp(
temp,
namesAndTasks[iTask].szName
) == 0 )
{
namesAndTasks.pfnTask( temp, );
break;
}
} Usually quite effective. I prefer it to a long switch statement, even when I have sequential integer codes to switch on.
Because the code size is smaller, this can sometimes run faster than a huge switch statement too.
--
Mike Dimmick
|
|
|
|
|
Mike Dimmick wrote:
Usually quite effective. I prefer it to a long switch statement, even when I have sequential integer codes to switch on.
Because the code size is smaller, this can sometimes run faster than a huge switch statement too.
Actually, most modern compilers (and this includes VC) translate switch statements on large numbers of integer variables to jump tables.
On C#, switches on strings are allowed, and above a certain threshold the compiler generates a Hashtable with jump locations and the strings as a key.
ORACLE One Real A$#h%le Called Lary Ellison
|
|
|
|
|
I'm sure they do. I meant from a code maintenance point of view: it's a lot easier to maintain (I think) a set of moderately simple functions than it is to maintain a 500-line function with a huge switch statement in it.
Of course, you can still code the dispatching mechanism like:
switch ( iValue )
{
case 0:
HandleCase0();
break;
case 1:
HandleCase1();
break;
default:
assert( !"Error in case statement!" );
break;
} but that gets very boring, very quickly. Unless there was some clear profiling indication that the table version was too slow for a given code path, I'd stick to that.
As for how common libraries implement it: in Win32 programming, you typically write a big switch statement. MFC's message maps are table-based (complicated somewhat by supporting ranges). ATL's BEGIN_MSG_MAP family of macros mask a honking great if /else if chain.
The hash table implementation is probably nicer if you have a fixed set and can calculate it all in advance, and either know that you can't get false-positives or check that there's a match before you jump. For general, intelligible coding, I use the array. The threshold is obviously because the hash table has an overhead in the hash function and the extra check in any case.
MFC has, IIRC, a small hash table for each class with a message map which contains the most recently used message map entries, so it doesn't have to search the whole table (and potentially the base class's table, and its base class, and so on down) every time a common message arrives.
My solution does require that all your operations will take the same parameters. This ain't necessarily so. One of my implementations was for a varargs function where you had command identifiers, and each command could take 0, 1 or 2 parameters. So I had to have a parameter count field as part of my jump table structure which indicated what you needed to cast the function pointer to. Again, MFC does something similar for its message maps.
--
Mike Dimmick
|
|
|
|
|
Mike Dimmick wrote:
but that gets very boring, very quickly. Unless there was some clear profiling indication that the table version was too slow for a given code path, I'd stick to that.
I agree. Actually, everytime I see a huge switch statement (as I'm an OOP die-hard) I start to ask what's wrong with the design, since this should be solved by a virtual method call. Not all switches should be virtual calls, but normally they indicate some design flaw in an OOP world.
ORACLE One Real A$#h%le Called Lary Ellison
|
|
|
|
|
Generally I'd agree, but in the case where you'd basically need an object for each 'arm' of the switch statement which you wouldn't use anywhere else, it's wasteful of programming time. The virtual method case is generally more maintainable, sure.
Of course you may well need some kind of factory method or object to create the objects, so you're either back to the switch statement again, or some other kind of creation table.
Languages with reflection can of course use the name of the class in order to create one; the advantage that MFC's Run-time Class Information has over the C++ language's standard RTTI is that you can (if your class uses DECLARE_DYNCREATE or DECLARE_SERIAL ) perform dynamic creation through the RUNTIME_CLASS macro.
--
Mike Dimmick
|
|
|
|
|
/* ATOF.C: This program shows how numbers stored
* as strings can be converted to numeric values
* using the atof, atoi, and atol functions.
*/
#include <stdlib.h>
#include <stdio.h>
void main( void )
{
char *s; double x; int i; long l;
s = " -2309.12E-15"; /* Test of atof */
x = atof( s );
printf( "atof test: ASCII string: %s\tfloat: %e\n", s, x );
s = "7.8912654773d210"; /* Test of atof */
x = atof( s );
printf( "atof test: ASCII string: %s\tfloat: %e\n", s, x );
s = " -9885 pigs"; /* Test of atoi */
i = atoi( s );
printf( "atoi test: ASCII string: %s\t\tinteger: %d\n", s, i );
s = "98854 dollars"; /* Test of atol */
l = atol( s );
printf( "atol test: ASCII string: %s\t\tlong: %ld\n", s, l );
}
Output
atof test: ASCII string: -2309.12E-15 float: -2.309120e-012
atof test: ASCII string: 7.8912654773d210 float: 7.891265e+210
atoi test: ASCII string: -9885 pigs integer: -9885
atol test: ASCII string: 98854 dollars long: 98854
Dr Abudawood
|
|
|
|
|
Hi,
I want to add a window to my application that will show a list of items.
For that I create a CFrameWand with a ClistCtrl view inside.
the problem is that the cunstructor of CFrameWnd is protected by default.
How can I pop up the window ?
Is there a method to do it without touching the specific constructor ?
Shay
|
|
|
|
|
I assume you are talking about a CFrameWnd derrived class of your own created by the class wizzard. You can either use dynamic creation (IMPLEMENT_DYANMIC ...) or make the constructor public yourself. I do the second all the time but in the past I have done some work with creating class instances using the GetRuntimeClass() stuff..
John
|
|
|
|
|
Yes, you are right, I amderiving my own class.
How do I use the "dynamic creation" ?
Or how do I use the GetRunTimeClass() ?
Thanks
|
|
|
|
|
How do I use the "dynamic creation" ?
Look in the documentation for CObject:
CRuntimeClass* pRuntimeClass = RUNTIME_CLASS( CMyClass );
CObject* pObject = pRuntimeClass->CreateObject();
ASSERT( pObject->IsKindOf( RUNTIME_CLASS( CMyClass ) ) );
However it is far easier to just make your constructor public...
John
|
|
|
|
|
Thank you,
I did converted it into public, but I said to myself it was fishy and not menat to be this way...
|
|
|
|
|
It is protected because MFC internals create it using the dynamic method and in most cases the user does not need to do this themselves.
John
|
|
|
|
|
You could use RTTI if you do not want to use MFC.
RUNTIME_CLASS is a macro written by Ms.
|
|
|
|
|
:(I want to find the relation between a font and the Unicode,
I want to know a font’s character set like to http://www.unicode.org/charts/, but I don’t’ know how I can find the character set like it?
|
|
|
|
|
If you're using Windows 2000 or XP, use the Character Map tool (typically in your start menu at Accessories > System Tools > Character Map). Check the Advanced View box.
This won't show you the code points which have no glyph (character image) assigned, but it will show you all the (basic) glyphs that are available in the font, and the code points to which they are assigned.
See here for a guide to Unicode terminology[^], including definitions of glyph, encoding and code point.
--
Mike Dimmick
|
|
|
|
|
I want to find a function that it can know which character can be displayed?
Different font have different character set, for example the font of Arial maybe have five character set and the font of PMingLiU maybe have ten character set. How I can know the number and name of a font’s character set?
|
|
|
|
|
GetFontUnicodeRanges , perhaps?
GetTextMetrics or GetOutlineTextMetrics might also be helpful, but I suspect for a TrueType font, GetTextMetrics will return DEFAULT_CHARSET in the tmCharSet field.
--
Mike Dimmick
|
|
|
|
|
Basically, UNICODE is a way the windows storing your character in the system .
UNICODE system applies a standard whereby each character in your program will be stored as 2 bytes no matter what character set it is in.
If you are using MBCS. It means that your program can selectively choose how many bytes need to be allocate for each character.
To know more about. Check out some cool articles in codeprojects.
|
|
|
|
|
I'm trying to learn how to implement a linked list. I'm having a fun time trying to get the following code to work. I didn't create a seperate header file for the top part (where the node class is defined) because I wanted to keep it simple at this point. I'm not sure where to add the main funtion or what header needs to be specified if any. I did a google search for the pop and push functions but didn't find a header. Also, where do I enter the information I want to add to my linked list database? I was hoping someone would help me out here, or at least point me in the right direction. Thanks much, Dave.
---------------------------------------------------------
//node class defined
class node {
private:
friend class llist; // We will have an llist class to manipulate
// nodes, and we want it to access node.
int information; // I'm assuming that this is a linked list
// of integers.
node *next; // Pointer to the next node.
node *previous; // Pointer to the previous node.
}
//----------------------------------------------------
//Ceate the llist class
class llist {
private:
node base; // We need a base node, from which other nodes will spring.
node *current; // A pointer to the current node.
public:
void push(int item);
int pop();
}
void llist::push(int item)
{
node *temp=current; // Temporary node
current->next=new node; // Create new node
current=current->next; // Assign current to new top node
current->information=item; // Assign the data
current->previous=temp; // Set previous pointer
}
int pop()
{
int temp;
temp=current->information;
if (current->previous == NULL) // Following a NULL pointer will lead to nothing but folly
return temp;
current=current->previous;
delete current->next;
return temp;
}
|
|
|
|
|
DaveE9th wrote:
I'm not sure where to add the main funtion
At the bottom.
DaveE9th wrote:
what header needs to be specified if any.
At this point, none are needed, although you'll probably be outputting some data so you'll eventually need stdio.h, or ostream (or wherever cout is kept).
DaveE9th wrote:
I did a google search for the pop and push functions but didn't find a header.
That's because the push() and pop() methods belong to your class.
DaveE9th wrote:
Also, where do I enter the information I want to add?
Input can come from various places, including a file, and the user typing it in.
|
|
|
|
|
Thanks Dave
"The man who reads nothing is better educated than the man who reads nothing but
newspapers."- Thomas Jefferson
|
|
|
|
|
push() and pop() are generally used when we talk about a stack and not just a list but I know STL uses push_back and push_front, pop_back, pop_front with all sequence containers..
John
|
|
|
|
|
I'm still stuck on getting this very interesting code to compile. I was hoping someone would type in the missing main function for me and let me know what else I need to do to get this going.
Thanks, Dave
VC++ 6.0
|
|
|
|
|
Thanks John, I've been reading up on vector containers in the STL as you mentioned...very fascinating.
Thanks, Dave
|
|
|
|
|
Is there anyway to verify a property page is created before I called RemovePage(), and is there anyway to insert a page (like between page 2 and 3)in the property pages? Thank you!
|
|
|
|