what function will convert a char to its number value
-
I am trying t create a switch statment that sitches on names in an array but I can only come up with a the loop below. Is there a function that will return the numeric value of a char?
char Names[50] for(int i=0; i<50; i++){ int temp = (int)Names[i]; if(temp = **the number value of 'pla'**) then do some stuff if(temp = **the number value of 'oct'0**) then do some more stuff }
StevenIf it's a simple piece of work you want to do for each item, just use a chain of
if
statements usingstrcmp()
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[] =
{
// Fill in 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 -
If it's a simple piece of work you want to do for each item, just use a chain of
if
statements usingstrcmp()
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[] =
{
// Fill in 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 DimmickMike 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 know I am asking why you are doing something rather than just answering your question so I apologize. First, there is a way to get the numeric value of a char. Just cast the char as an int and there you go. Second, there is no numeric value of a string so you can't do what you are asking. In your sample code, you show: char Names[50] for(int i=0; i<50; i++) { int temp = (int)Names[i]; // reinitialization error? if(temp = the number value of 'pla') then do some stuff; if(temp = the number value of 'oct'0) then do some more stuff; } Where is your switch statement? Are you simulating the switch with the if statements? In the sample shown, you have a single name which can be up to 50 chars long. You are merely comparing 1 letter from that same name at a time. If you need 50 names, you'll need to define a 2 dimensional array like char Names[50][30]; If you absolutely have to use a switch statement (like a school project) you can create a struct which contains a key value and when you populate the struct you can increment the key. struct NameStruct { char Names[50][30]; int key; }; Then you can use the NameStruct.key value in your switch statement and access the names with NameStruct.Names[key] If your end goal is to be able to loop through an array of strings and take a different action for each string you could try: char Names[50][MAX_NAME_LENGTH]; int x; for (x = 0; x < MAX_NAME_LENGTH; x++) { if(!strcmp(Names[x], "Text to compare")) DoSomething(); if(!strcmp(Names[x], "Other text to compare")) DoSomethingElse(); ........ if(!strcmp(Names[x], "Last text to compare")) DoSomethingEtirelyDifferent(); }
for (x = 0; x < MAX_NAME_LENGTH; x++) Should be for (x = 0; x < 50; x++) and you should use the 'if else' construct to avoid unneeded calls to strcmp(). INTP
-
I know I am asking why you are doing something rather than just answering your question so I apologize. First, there is a way to get the numeric value of a char. Just cast the char as an int and there you go. Second, there is no numeric value of a string so you can't do what you are asking. In your sample code, you show: char Names[50] for(int i=0; i<50; i++) { int temp = (int)Names[i]; // reinitialization error? if(temp = the number value of 'pla') then do some stuff; if(temp = the number value of 'oct'0) then do some more stuff; } Where is your switch statement? Are you simulating the switch with the if statements? In the sample shown, you have a single name which can be up to 50 chars long. You are merely comparing 1 letter from that same name at a time. If you need 50 names, you'll need to define a 2 dimensional array like char Names[50][30]; If you absolutely have to use a switch statement (like a school project) you can create a struct which contains a key value and when you populate the struct you can increment the key. struct NameStruct { char Names[50][30]; int key; }; Then you can use the NameStruct.key value in your switch statement and access the names with NameStruct.Names[key] If your end goal is to be able to loop through an array of strings and take a different action for each string you could try: char Names[50][MAX_NAME_LENGTH]; int x; for (x = 0; x < MAX_NAME_LENGTH; x++) { if(!strcmp(Names[x], "Text to compare")) DoSomething(); if(!strcmp(Names[x], "Other text to compare")) DoSomethingElse(); ........ if(!strcmp(Names[x], "Last text to compare")) DoSomethingEtirelyDifferent(); }
Believe me I don't have to do this for a school project. I have created a tool that display flight simulator data in real time. Long story short: (this is just another feature of the program) The flight simulator writes to a file and I use the getline() function to get the names of signals that the sim wrote and put them in
TSimHeader_arr[0].Name[i]
which is an array in a struct. anyways I think the function(char)strdup(name.c_str())
isn't putting them in the char array correctly. Because when I read them bach out they are strange characters. I don't know how to do this. Does anyone??? stevenvoid setInitialValues(){ sSignal.SimWriteFlag=1; sSignal.DisplayReadFlag=0; sHeader.SimStatus=setSimStatus(); string name,unit,min,max,value; for(int i=0; iTSimHeader_arr[0].Name[i] = (char)strdup(name.c_str()); TSimHeader_arr[0].Unit[i] = (char)strdup(unit.c_str()); TSimHeader_arr[0].Min[i] = atof(min.c_str()); TSimHeader_arr[0].Max[i] = atof(max.c_str()); TSimSignal_arr[0].Value[i] = atof(value.c_str()); // printf("%s",TSimHeader_arr[0].Name[sig_count]); sig_count ++; } TSimHeader_arr[0].SignalCount = sig_count; writeRfmData(); createRandNum(); }
-
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;// ...etc...
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 greatif
/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 -
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;// ...etc...
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 greatif
/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 DimmickMike 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
-
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
orDECLARE_SERIAL
) perform dynamic creation through theRUNTIME_CLASS
macro. -- Mike Dimmick -
for (x = 0; x < MAX_NAME_LENGTH; x++) Should be for (x = 0; x < 50; x++) and you should use the 'if else' construct to avoid unneeded calls to strcmp(). INTP
John R. Shaw wrote: for (x = 0; x < MAX_NAME_LENGTH; x++) Should be for (x = 0; x < 50; x++) and you should use the 'if else' construct to avoid unneeded calls to strcmp(). :omg: You are correct of course. Thank you! I'm going to live forever or die trying!
-
I am trying t create a switch statment that sitches on names in an array but I can only come up with a the loop below. Is there a function that will return the numeric value of a char?
char Names[50] for(int i=0; i<50; i++){ int temp = (int)Names[i]; if(temp = **the number value of 'pla'**) then do some stuff if(temp = **the number value of 'oct'0**) then do some more stuff }
Steven/* ATOF.C: This program shows how numbers stored * as strings can be converted to numeric values * using the atof, atoi, and atol functions. */ #include #include 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
-
Believe me I don't have to do this for a school project. I have created a tool that display flight simulator data in real time. Long story short: (this is just another feature of the program) The flight simulator writes to a file and I use the getline() function to get the names of signals that the sim wrote and put them in
TSimHeader_arr[0].Name[i]
which is an array in a struct. anyways I think the function(char)strdup(name.c_str())
isn't putting them in the char array correctly. Because when I read them bach out they are strange characters. I don't know how to do this. Does anyone??? stevenvoid setInitialValues(){ sSignal.SimWriteFlag=1; sSignal.DisplayReadFlag=0; sHeader.SimStatus=setSimStatus(); string name,unit,min,max,value; for(int i=0; iTSimHeader_arr[0].Name[i] = (char)strdup(name.c_str()); TSimHeader_arr[0].Unit[i] = (char)strdup(unit.c_str()); TSimHeader_arr[0].Min[i] = atof(min.c_str()); TSimHeader_arr[0].Max[i] = atof(max.c_str()); TSimSignal_arr[0].Value[i] = atof(value.c_str()); // printf("%s",TSimHeader_arr[0].Name[sig_count]); sig_count ++; } TSimHeader_arr[0].SignalCount = sig_count; writeRfmData(); createRandNum(); }
Prototype: char *_strdup( const char *strSource ); Bad: (char)strdup(name.c_str()); // this is incorrect usage Good: strdup(name.c_str()); // normal usage Ok: (char*)strdup(name.c_str()); // this is redundant INTP