how to associate enum with array of string - arrays

If  I have array string for courses name like
courseName = {"java","math","physics"}
and enum have constant variables with code for courses like
CSC = 320
How to associate them in C language ?

You need some way to map the enumeration to the array index.
A simple array of structures with a "from" and "to" member solve it:
struct
{
int course; // Course enumeration value
unsigned name; // Name array index
} course_to_name_map[] = {
{ JAVA_101, 0 },
// etc...
};
To find the name loop over the mapping array to find the course, and then use the corresponding index to get the name:
char *get_course_name(int course)
{
static const size_t map_element_count = sizeof course_to_name_map / sizeof course_to_name_map[0];
for (unsigned i = 0; i < map_element_count; ++i)
{
if (course_to_name_map[i].course == course)
{
return course_names[course_to_name_map[i].name];
}
}
// Course was not found
return NULL;
}
Note that this is only one possible solution. It's simple but not very effective.

why not:
enum KEY {
KEY_JAVA = 320,
KEY_MATH = 123,
KEY_PHYSICS = 17,
};
char *course_to_name[] = {
[KEY_JAVA] = "java",
[KEY_MATH] = "math",
{KEY_PHYSIC] = "physics",
};
// usage:
course_to_name[KEY_JAVA];
It works quite well as long as courses codes are relatively small.

Related

make my struct instance 'translate' certain numbers into certain strings

I want to use enums and structs (without using object oriented) to make my program 'translate' the following integers into the specified strings:
1 = "small"
2 = "medium"
3 = "large"
I want something like this: (the known part will be an integer, that has to be translated into the matching string)
size.num = 3;
printf("%s", size.size);
and the output would be large.
I tried to do it with two structs:
struct Size {
int num;
char* type;
}size_map[] = {
{ 1, "small" },
{ 2, "medium" },
{ 3, "large" },
};
struct outfit {
char* ...;
char** ....;
struct Size size;
}T_shirt;
T_shirt.size.num = 3;
so when I have only a size in number, I can iterate over the size_map to find the matching size (in words) I need.
But is there a simple way to make it automatically 'know' that without the use of size_map? (an enum would be also a problem- I will have to use it the opposite way..)
Why not use simple switch as below?
char *sizeInWord = NULL;
switch(size) {
case 1:
sizInWord = "small";
break;
case 2:
sizInWord = "medium";
break;
case 3:
sizInWord = "large";
break;
default:
sizInWord = "InvalidSize";
break;
}

ColdFusion, BigDecimal cannot be used as an array

I am trying to perform a few simple tasks with an array of structures that I have and feel like I'm almost done with my solution but am having some last minute trouble. I am trying to accomplish the following tasks:
Create a struct with the following values; id, name, int arr[].
I am using a FOR loop to iterate over an array of values like ID, name, sub id.
For each item in my list, I am trying to make the decision if I've seen the struct before and if its in my agencies Array.
If its not there, add the current struct to an array. If its already present in the array then add the current sub id to the int arr[] entry of the struct.
When I run my code below I keep getting the error, "BigDecimal cannot be used as an array" and I don't understand what's happening. I am new to CFSCRIPT so perhaps I'm either not getting the arr[] values out of the struct or not defining my struct correct so the third value is of Array type.
remote array function getCurrAgenciesList(String Acct_Id) returnformat="JSON"
{
include "qry_getCurrentAssignedRepoAgenciesAll.cfm";
//define arr to hold values...
var agenciesArr = [];
var recordLength = getCurrentAssignedRepoAgencies.RecordCount;
for(agency in getCurrentAssignedRepoAgencies)
{
currentStruct = {id=agency.repoID, name=agency.repoName, relatedColl=agency.collatSub};
var structArrIndex = arrayOfStructsFind(agenciesArr, "id", agency.repoID);
if(structArrIndex eq 0)
{
//add new struct to agenciesArr
ArrayAppend(agenciesArr,currentStruct,"true");
}
else
{
//find current struct in array using index from before...
var collFromStr = agenciesArr[structArrIndex]['relatedColl'];
//add current collatsub to array, append.
var updatedStruct = ArrayAppend(collFromStr,agency.collatSub);
//reassign updated arr[] struct value back in array.
agenciesArr[structArrIndex]['relatedColl'] = collFromStr;
}
}
//return...
return agenciesArr;
}
function arrayOfStructsFind(Array, SearchKey, Value)
{
var result = 0;
var i = 1;
var key = "";
for (i=1;i lte arrayLen(array);i=i+1)
{
for (key in array[i])
{
if(array[i][key]==Value and key == SearchKey)
{
result = i;
return result;
}
}
}
return result;
}
Any help would be greatly appreciated, as I feel I'm stuck on this one last thing or there's something I am missing. Any feedback is welcome.
UPDATE the error happens at line 27,
var updatedStruct = ArrayAppend(collFromStr,agency.collatsub);
UPDATE 3:39PM
I believe the issue is not related to the above line but this line:
var collFromStr = agenciesArr[structArrOmdex]['relatedColl'];
I am asking for an array to be returned from the struct from key, relatedColl. I am thinking only an integer is return so when the next Array Append operation is performed the code explodes. So, how does one create an array inside a struct in Cold Fusion\CFSCRIPT????
I have solved my problem by making the following changes:
Re-defined the struct definition to have an array type as the third element.
After doing this it looks like the search needed to be modified so I switched the ordering of my key, value if statement.
I also gathered a great amount of information from this link. It is wonderful.
Final Code:
remote array function getCurrAgenciesList(String Acct_Id) returnformat="JSON"
{
include "qry_getCurrentAssignedRepoAgenciesAll.cfm";
//define arr to hold values...
var agenciesArr = [];
var recordLength = getCurrentAssignedRepoAgencies.RecordCount;
for(agency in getCurrentAssignedRepoAgencies)
{
arr = [agency.collatSub];
currentStruct = {id=agency.repoID, name=agency.repoName, relatedColl=arr};
var structArrIndex = arrayOfStructsFind(agenciesArr, "id", agency.repoID);
if(structArrIndex eq 0)
{
//add new struct to agenciesArr
ArrayAppend(agenciesArr,currentStruct,"true");
}
else
{
//find current struct in array using index from before...
var collFromStr = agenciesArr[structArrIndex]['relatedColl'];
//add current collatsub to array, append.
ArrayAppend(collFromStr,agency.collatSub,"true");
//reassign updated arr[] struct value back in array.
agenciesArr[structArrIndex]['relatedColl'] = collFromStr;
}
}
//return...
return agenciesArr;
}
function arrayOfStructsFind(Array, SearchKey, Value)
{
var result = 0;
var i = 1;
var key = "";
for (i=1;i lte arrayLen(array);i=i+1)
{
for (key in array[i])
{
if(key == SearchKey and array[i][key]==Value)
{
result = i;
return result;
}
}
}
return result;
}

How do I create an Array of Objects in C?

I'm new to C, coming from a language like javascript the amount of types, keywords etc. in the language are painfully confusing.
In javascript I can create an array of objects like so.
arrayOfObjectsInsideJavascript = [
{ s:"ejf09j290fj390j2f09", f=0 },
{ s:"dj320992209920209dj", f=0 }
]
From what I've read it seems that I'll need to be using typedefand orstructs.
I've tried:
typedef struct[] = {
{ s:"ejf09j290fj390j2f09", f=0 },
{ s:"dj320992209920209dj", f=0 }
}
struct[] = {
{ s:"ejf09j290fj390j2f09", f=0 },
{ s:"dj320992209920209dj", f=0 }
}
typedef struct {
char[] s = "ejf09j290fj390j2f09";
int f = 0;
} objectLikeClassThingy;
What's the best way to create the object I need?
like this ?
struct {
const char *s;
double f;
} obj[] = {
{ .s = "ejf09j290fj390j2f09", .f = 0 },
{ .s = "dj320992209920209dj", .f = 0 }
};
Where JavaScript has dynamic "properties", C has static "tags". A struct type is defined as a sequence of tags, which each have a type.
For the type inside your example array
arrayOfObjectsInsideJavascript = [
{ s:"ejf09j290fj390j2f09", f=0 },
{ s:"dj320992209920209dj", f=0 }
]
your last solution started off almost correctly:
struct element {
char s[256];
int f;
};
You have two options for the type of s:
If you want to store the string inside the object, you use some array type, such as char s[256]. 256 is the length of the array, so when you use zero-terminated strings, the maximum allowed string length is 255 (which is 256, minus one for the '\0' character).
If you want to store the string outside the object, you use some pointer type. Since you want to use string literals, you should declare the tag as const char *s. Changing a string literal causes undefined behaviour, so it's best to prevent yourself from doing so.
For this answer, I'll use the first option in the examples.
If you want to define one struct, you could now write something like
struct element {
char s[256];
int f;
} one_object = {
.s = "ejf09j290fj390j2f09",
.f = 0,
};
or
struct element {
char s[256];
int f;
};
/* ... later, in a scope where `struct element` is visible ... */
struct element one_object = {
.s = "ejf09j290fj390j2f09",
.f = 0,
};
or, with a typedef,
typedef struct {
char s[256];
int f;
} your_element_type;
/* ... later, in a scope where `your_element_type` is visible ... */
your_element_type one_object = {
.s = "ejf09j290fj390j2f09",
.f = 0,
};
Note that this doesn't necessarily work with older compilers that don't support the C99 standard. In the older days, you'd have to initialise fields in order:
your_element_type one_object = { "ejf09j290fj390j2f09", 0 };
Also note that, if you're never going to refer to the type name struct element again, you don't have to name it:
struct {
char s[256];
int f;
} one_object = {
.s = "ejf09j290fj390j2f09",
.f = 0,
};
Arrays are initialised similarly (you've actually already initialised an array, namely s, with a string):
struct element {
char s[256];
int f;
} so_many_objects[] = {
{ .s = "ejf09j290fj390j2f09", .f = 0 },
{ .s = "dj320992209920209dj", .f = 0 },
};
or
struct element {
char s[256];
int f;
};
/* ... later, in a scope where `struct element` is visible ... */
struct element so_many_objects[] = {
{ .s = "ejf09j290fj390j2f09", .f = 0 },
{ .s = "dj320992209920209dj", .f = 0 },
};
or, with a typedef again,
typedef struct {
char s[256];
int f;
} your_element_type;
/* ... later, in a scope where `your_element_type` is visible ... */
your_element_type so_many_objects[] = {
{ .s = "ejf09j290fj390j2f09", .f = 0 },
{ .s = "dj320992209920209dj", .f = 0 },
};
By the way, note that we are using an incomplete type for so_many_objects; this is only possible because the compiler can see how big the array should be. In these examples, the compiler would treat your code as if you'd have written struct element so_many_objects[2]. If you think you'll have to extend the array with more objects, you'd better specify how many elements the array has (at maximum), or learn about dynamic allocation.

Syntax for assigning to a struct in a struct

I have a struct Entity that is made up of Limbs and an enum, Limbs is also a struct with two items e.g.
typedef enum{ALIVE, DEAD} state;
typedef struct Limb{
int is_connected;
int is_wounded;
} Limb;
typedef struct Entity{
Limb limb_1;
Limb limb_2;
state is_alive;
} Entity;
Now lets say I have a function that's designed to assign entity particular values, what is the proper syntax to use here? My current guess is this:
void assign_entity(Entity *entity){
*entity = {
.limb_1 = { 1, 0 },
.limb_2 = { 1, 0 },
.is_alive = ALIVE
};
}
But I get an error (expected expression) when I use this syntax, what am I doing wrong here? What is the proper syntax for assigning to a struct inside a struct.
You're trying to use a compound literal but omitting the proper syntax.
It should be:
void assign_entity(Entity *entity){
*entity = ((Entity) {
.limb_1 = { 1, 0 },
.limb_2 = { 1, 0 },
.is_alive = ALIVE
});
}
Note that this requires C99 (or a suitably extended compiler, of course).
Probably too verbose for someone the code below:
void assign_entity(Entity *entity)
{
entity->limp_1.is_connected = 1;
entity->limp_1.is_wounded= 0;
entity->limp_2.is_connected = 1;
entity->limp_2.is_wounded= 0;
entity->is_alive = ALIVE;
}
If you have already allocated memory at the address pointed to by entity and all you're trying to do is "assign particular values", then you would do it as follows:
void assign_entity(Entity *entity)
{
entity->limb_1 = ( 1, 0 );
entity->limb_2 = ( 1, 0 );
entity->is_alive = ALIVE;
}
Or, if you want to roll it all up into one line:
void assign_entity(Entity *entity)
{
*entity = ((1, 0), (1, 0), ALIVE);
}
Designated initializer syntax can only be used in an initialization.
One way to do what you want would be:
Entity const new = {
.limb_1 = { 1, 0 },
.limb_2 = { 1, 0 },
.is_alive = ALIVE
};
*entity = new;

How do you convert values to enumeration constants in c?

Earlier I was fixing a lexer for my parser; now I have to create a validater for it. My idea was to convert the enumeration constants to strings by using the following preprocessor macro: #define MACRO_STRINGIFY(x) #x.
Then I made a function to compare various token values lactually, I made three, but they are all the same with a few minor changes):
unsigned int compare_keyword( enum script_keywords keyword, char *token ) {
char *temporary = MACRO_STRINGIFY( keyword );
unsigned int i = 0;
for (; i < (strlen( "KEYWORD_" ) + 1); i++) {
++temporary;
}
// 0 on match, 1 on no match
return strcmp( temporary, token ) ? 1 : 0;
}
Now, this function works absolutely fine... when keyword is the enumeration constant:
void test() {
printf( "\nIF is " );
// Finish the sentence based on the return value
compare_keyword( KEYWORD_IF, "IF" ) ? printf( "not a keyword.\n" ) : printf( "a keyword.\n" );
}
test(); //--> Outputs 'IF is a keyword' like expected.
On the other hand, the function does not work as intended if I pass a value like 1 (the value which the symbolic enumeration constant KEYWORD_IF resolves to.):
// Same as last time with one edit:
void test() {
/* See above code with following change on line 4 */
compare_keyword( 1, "IF" ) /* etc... */
/* Rest of code from previous test */
}
test(); //--> Outputs 'IF is not a keyword' even if KEYWORD_IF resolves to the value 1.
The point I'm getting across here is that the preproccessor is very literal, and I would much prefer using a for loop to loop through the constants efficiently without bloating the code size (which is what would happen if I end up using enumeration constants). Therefore, the question is how can I convert plain integer values to their symbolic names without using switch…case… or if…else…?
Edit: Enumeration Details:
enum script_keywords {
KEYWORD_IF = 1,
KEYWORD_THEN = 2,
KEYWORD_ELSEIF = 3,
KEYWORD_ELSE = 4,
KEYWORD_ENDIF = 5,
KEYWORD_FOR = 6,
KEYWORD_TO = 7,
KEYWORD_STEP = 8,
KEYWORD_EXITFOR = 9,
KEYWORD_NEXT = 10,
KEYWORD_LOOP = 11,
KEYWORD_WHILE = 12,
KEYWORD_EXITLOOP = 13,
KEYWORD_ENDLOOP = 14,
KEYWORD_DO = 15,
KEYWORD_EXITDO = 16,
KEYWORD_UNTIL = 17,
KEYWORD_ON = 18,
KEYWORD_GOTO = 19,
KEYWORD_CALL = 20,
KEYWORD_LET = 21,
KEYWORD_DIM = 22,
KEYWORD_AS = 23
};
The Macro "MACRO_STRINGIFY" is evaluated at compile time by the preprocessor. It will return the actual name of the argument, so
MACRO_STRINGIFY(keyword) -> "keyword"
MACRO_STRINGIFY(KEYWORD_IF) -> "KEYWORD_IF"
MACRO_STRINGIFY(1) -> "1"
Apparently this will not lead to any solution.
Instead one could use a compile-time generated key-value mapping to implement such functionality:
struct map
{
int key;
const char* value;
};
struct map mappings[] =
{
{ KEYWORD_IF, "IF" },
{ KEYWORD_ELSE, "ELSE" }
};
and then simply iterate those mapping entries at runtime to find out what you need:
static int is_keyword(const char* str)
{
int i;
const int count = sizeof(mappings) / sizeof(mappings[0]);
for(i = 0; i < count; i++)
{
struct map* m = &mappings[i];
if(strcmp(str, m->value) == 0)
{
return 1;
}
}
return 0;
}
void test()
{
const char* str = "IF";
const char* what;
if(is_keyword(str))
{
what = "a keyword";
}
else
{
what = "not a keyword";
}
printf("%s is %s.\n", str, what);
}
This is about as minimal as it may get. The executable binary does not normally include names of enumeration values as known from e.g. Java.
To extend this even further, you could do some preprocessor voodoo to generate the mapping array (semi-) automatically. But as I am not a big friend of preprocessor voodoo I will skip that ;)

Resources