Compare User input string to MACRO name - c

I am trying to make a look up table. Here is the pretext:
Suppose, following is the defines list of certain macros.
#define ENTITY1 0x10001001
#define ENTITY2 0x10001002
.
.
.
The ENTITY_ is the User readable string value of the otherwise unsigned long integer type value and there can be any number of macros (say greater than 200, or even 500).
Now, there is a list which keeps track of which entity exists in which file number. Something like this:
0x10001001 1
0x10001002 2
0x10001003 3
.
.
.
The use of the long unsigned integers for each ENTITY is necessary because of proprietary conventions.
The first list is already present, and the second list needs to be generated through a program by using the macro strings in #defines of the first list as the user enters the record.
Since the number of such entries is very large, hard coding each value is a burdensome task. Also, if the first list is updated, the second list will not update appropriately if additional switch cases are not coded.
When the user makes an entry, he tells that the entry is to be made in ENTITY3 through a string variable, the system should look up if a macro exists by the name ENTITY3. If yes, then open the file with number 3 and do the necessary processing, otherwise, display warning that such an entry does not exist.
So, how do I compare the string variable entered by the user with a macro name without using SWITCH CASE?
I am using C programming. GNU C Library.
Edit: Here is the scenario.
The different entities named ENTITYn (n can be any number) can exist in different files which have a certain integer number 1,2,3...
But, the proprietary environment has built up these entities such that they are recognized using certain unsigned long integers like 0x01001001 etc. For each entity, the macros have been defined in some header files corresponding to those entities by the name ENTITY1 ENTITY2...
Now when a certain manager wants to change something, or enter certain data to a particular entity, he would address is by the name ENTITYn, and the program would look up in a lookup table for a corresponding entry. If a match is found, it would use the unsigned long integer code for that entity for subsequent processing internal to the proprietary system, access another lookup table which looks for which file number has this entry and opens that file location for processing.
I need to populate this second table with the unsigned long ints of the Entities and their corresponding locations (let all of them be in a single file 1 for now). I want to circumvent the condition, that the one making that LUT has to know the corresponding entity unsigned long integer codes. The program uses the input string i.e. ENTITY1 and directly maps it.
But now I am beginning to think that hardcoding a LUT would be a better option. :)

Macro names don't exist in a C program. The preprocessor has replaced every instance of the macro name by its substitution value. If I understand your problem correctly, you'll probably need some kind of lookup table, like:
#define ENTITY1 0x10001001
#define ENTITY2 0x10001002
#define STR(x) #x
struct lookup { char *name; unsigned value; } ;
struct lookup mylut[] = {
{ STR(ENTITY1), ENTITY1 }
, { STR(ENTITY2), ENTITY2 }
};
The preprocessor will expand that to:
struct lookup { char *name; unsigned value; } ;
struct lookup mylut[] = {
{ "ENTITY1", 0x10001001 }
, { "ENTITY2", 0x10001002 }
};
, which you can use to look up the string literals.

Macros are preprocessor features, they're not visible to the C compiler. So you cannot directly reference the "values" of macros from code.
It seem you need two look-up tables, if I get this correctly:
One table mapping a string such as ENTITY1 to to a unique unsigned integer, such as 0x10001001.
One table mapping an unsigned integer such as 0x10001001 to a "file number" which looks like a (small) unsigned integer such as 1.
Both of these tables can be generated by processing the source code you seem to have. I would recommend gathering the ENTITYn strings into something like this:
struct entity_info
{
const char *name;
unsigned int key;
};
Then have your pre-processing code build a sorted array of these:
const struct entity_info entities[] = {
{ "ENTITY1", 0x10001001 },
{ "ENTITY2", 0x10001002 },
/* and so on */
};
Now you can implement an efficient function like this:
unsigned int get_entity_key(const char *entity_name);
It could perhaps use binary-search, internally.
Then you need to do the second step, obviously. I'm not sure of the exact details of these values (how and when they can change); if the "file number" for a given entity is constant, it could of course be added directly into the entity_info structure.

So, how do I compare the string variable entered by the user with a macro name?
You can't. Macros exist only at compile-time (technically, only at preprocess-time, which happens before compile-time).
I'm not going to suggest a solution until I'm sure I understand your scenario correctly (see my comment above).

Related

How to implement a form with optional input fields in C?

I'm working on a console program that allows to search in an array of a structure named Person
For simplicity I'm now assuming that all of the attributes are integers.
typedef struct Person {
int name;
int city;
int email;
} Person;
so the comparing function would look like this:
int comparing(int x, int y) {
return x == y;
}
I'm trying to make a searching function that would allow the user to use comparing(int x, int y) and the user can search using one or more criteria. Meaning they can search by just name and email for example.
If you want to have "checkboxes" that the user can check by moving the cursor on the screen with the arrow keys and then press the ENTER key to activate them, then you cannot do this with the C standard library, but you probably can do it with a platform-specific API. For example, if you are on the Linux platform, you can use ncurses. However, you might be better off creating a proper graphical application, i.e. not a console applicaton.
If you want to keep it a simple text console application using only the features of the C standard library, then you can have a text menu in which the user can specify that he wants to toggle a checkbox, and then it asks the user which checkbox number he wants to toggle. After every change of the checkboxes, the program reprints all checkboxes to show the user the new state of the checkboxes.
In the comments section, you specifically asked for code to show you how the loop of the search should look like. Therefore, I have written such a loop for you.
This loop requires that a variable of type struct Person with the name lf (which stands for "looking for") is created and filled with all search criteria. Only the fields that are actually being searched for have to be set. The remaining fields can stay uninitialized. Also, three variables of type bool must be created with the names should_match_name, should_match_city and should_match_email. These three variables must be set to specify whether to search for the corresponding field, and if set to true, the corresponding field must also be set in the lf variable. Note that you must #include <stdbool.h> to enable support for the bool variable type.
The loop could then look like this:
for ( int i = 0; i < number_of_valid_elements_in_array; i++ )
{
if (
( !should_match_name || lf.name == array[i].name ) &&
( !should_match_city || lf.city == array[i].city ) &&
( !should_match_email || lf.email == array[i].email )
)
{
printf(
"Matching person found:\nName: %d\nCity: %d\nE-Mail: %d\n\n",
array[i].name, array[i].city, array[i].email
);
}
}
Note that more sophisticated search algorithms (for example those used in database engines) do not search all elements in order to find a match, but they rather search using indexes. This makes the search significantly faster. These indexes would have to be created in advance, though. But as long as you have less than a million elements, it will probably not matter.

Is an initialised 2d array fine for mapping consecutive integers to strings in C?

I have to map consecutive integer codes from 1 to 100 to strings in C. Normally, for a mapping of number to string, I would have something like this:
#define code1 1
#define code2 2
.
.
#define code100 100
struct map
{
int code;
char *msg;
}objs[100];
I would then loop over the objs and if the number matches, I would use the corresponding string of the obj array. Since I know that the numbers to be mapped are consecutive, I can just do this:
const char *arr[100] = { "abc", "def", ....... "100th msg"};
I can then forget the looping and just print arr[code]. Is this a bad approach? The only disadvantage I see is that when somebody else adds a code in the middle, they have to be careful about it. The advantage is obviously that I don't need to loop over the struct array.
Using a direct indexed array is a commonly used approach that works fine if the data never (rarely) changes, and there are not too many gaps, because you spend a record for every gap. At some point the management or the storage cost of the gaps may become an issue.
If you need to cope with more dynamic compile-time updates to the data then the next best thing is a sorted array. If you can guarantee that your entries are always in order but perhaps there are gaps, or new entries added to the end, then you can binary chop your ordered array to quickly find the entry you want. You may want to do a start-up pass that checks the array is correctly ordered, but you only have to do that once.
If you need to worry about runtime updates, then you seriously need to consider higher-level container abstractions such as mapping trees or hashmaps.
Suppose the array has error messages. Then a common approach is to define constants fo each error and print the message associated with it, for example:
#define ERR_NONE 0
#define ERR_NOMEM 1
#define ERR_BADNUM 2
// etc
and define the array as:
const char *msgs[] = {
"No error",
"Out of memory",
"Bad number",
// etc
};
and have a function to print the message, for example:
void printmsg(int code)
{
printf("%s\n",msgs[code]);
}
which can be called as
printmsg(ERR_NOMEM);
For modularity, the #defines can be in e.g. errors.h, together with the prototype of printmsg, and the array can be in errors.c.
The only problem with your approach is that the codes can never change. You can't add intermediate codes without changing the entire code. But it should work. Also the first code should be zero or you'll have to either pad the array or shift the codes when accessing.
Essentially what you have is an immutable hash table.
#define BASE_CODE 5
#define CODE_BLUE 5
#define CODE_GREEN 6
const char *responses[] = {'blue', 'green'};
printf("%s\n", responses[code - BASE_CODE]);
If you want to be able to change the codes (add, remove, insert codes in the middle of the sequence, verify if a code was properly referenced), then you should stick with the first approach, but add a hash function so you don't need to loop sequentially over the array.

Inserting integer array with postgresql in C (libpq)

I'm trying to post an integer array into my postgresql database. I'm aware that I could format everything as a string and then send that string as one SQL command. However, I believe the PQexecParams function should also bring some help. However, I'm kind of lost as how to use it.
//we need to convert the number into network byte order
int val1 = 131;
int val2 = 2342;
int val3[5] = { 0, 7, 15, 31, 63 };
//set the values to use
const char *values[3] = { (char *) &val1, (char *) &val2, (char *) val3 };
//calculate the lengths of each of the values
int lengths[3] = { sizeof(val1), sizeof(val2), sizeof(val3) * 5 };
//state which parameters are binary
int binary[3] = { 1, 1, 1 };
PGresult *res = PQexecParams(conn, "INSERT INTO family VALUES($1::int4, $2::int4, $3::INTEGER[])", 3, //number of parameters
NULL, //ignore the Oid field
values, //values to substitute $1 and $2
lengths, //the lengths, in bytes, of each of the parameter values
binary, //whether the values are binary or not
0); //we want the result in text format
Yes this is copied from some tutorial.
However this returns :
ERROR: invalid array flags
Using a conventional method does work:
PQexec(conn, "INSERT INTO family VALUES (2432, 31, '{0,1,2,3,4,5}')");
Inserts data just fine, and I can read it out fine as well.
Any help would be greatly appreciated! :)
libpq's PQexecParams can accept values in text or binary form.
For text values, you must sprintf the integer into a buffer that you put in your char** values array. This is usually how it's done. You can use text format with query parameters, there is no particular reason to fall back to interpolating the parameters into the SQL string yourself.
If you want to use binary mode transfers, you must instead ensure the integer is the correct size for the target field, is in network byte order, and that you have specified the type OID. Use htonl (for uint32_t) or htons (for uint16_t) for that. It's fine to cast away signedness since you're just re-ordering the bytes.
So:
You cannot ignore the OID field if you're planning to use binary transfer
Use htonl, don't brew your own byte-order conversion
Your values array construction is wrong. You're putting char**s into an array of char* and casting away the wrong type. You want &val1[0] or (equivalent in most/all real-world C implementations, but not technically the same per the spec) just val1, instead of (char*)&val1
You cannot assume that the on-wire format of integer[] is the same as C's int32_t[]. You must pass the type OID INT4ARRAYOID (see include/catalog/pg_type.h or select oid from pg_type where typname = '_int4' - the internal type name of an array is _ in front of its base type) and must construct a PostgreSQL array value compatible with the typreceive function in pg_type for that type (which is array_recv) if you intend to send in binary mode. In particular, binary-format arrays have a header. You cannot just leave out the header.
In other words, the code is broken in multiple exciting ways and cannot possibly work as written.
Really, there is rarely any benefit in sending integers in binary mode. Sending in text-mode is often actually faster because it's often more compact on the wire (small values). If you're going to use binary mode, you will need to understand how C represents integers, how network vs host byte order works, etc.
Especially when working with arrays, text format is easier.
libpq could make this a lot easier than it presently does by offering good array construct / deconstruct functions for both text and binary arrays. Patches are, as always, welcome. Right now, 3rd party libraries like libpqtypes largely fill this role.

What is a way to represent complex numbers in C?

Without using the complex.h header file, suppose I want to create my own header file where I will define a variable argument function,
taking value 0 if I did not insert any value from the keyboard,
becoming a real number if I input only one value,
and a complex number if I input two values.
How can such a complex number be implemented? I have been thinking about the "i" symbol for the imaginary part. How can it appear? Is there any nice way to write a complex number?
Also I need to define addition in the complex field. How can that be done?
You should use a structure to represent it:
struct complex{
int real;
int imaginary;
};
now you can create an instance:
struct complex num;
and set its fields:
num.real = 3; //real part is now set to 3
num.imaginary = 5; //imaginary part is now set to 5
Why not create a struct with two fields for the Re and Im parts?
The i-notation is only a representation.
Then you can write functions that take two variables of the strcut type you created and return the added numbers as the same struct type.

Creating a File of Random Size [1...500] KB

Foreword: I have simplified the problem into its key functionalities, so if it sounds weird it is because this is a small aspect of the whole program.
Problem:
I want to create something like 100 text files: I'll loop and use my loop counter to name the files.
Then, I want to populate each file with random strings. I use my String struck defined below for this. I want to fill the file up from [1KB up to 500KB].
struct String // And yes I am using my own String library.
{
char *c;
int length;
int maxLength;
}
Lets assume I have the file opened (probably at the moment I create it, so it is empty). Now I would check something like this.
int range = Random.Range(0,500);
I would get a number that would predetermine the file size. So if range == 100 then the file would be populated with 100KB of "data".
I would first have my string created.
// Maybe making this 100 chars would help?
String *s1 = makeString("abcdefghijklmnopqrstuvwxyz");
How would I figure out how many times I have to write my String s1 into the file to make it the size of range? Preferably before writing to the file, I wouldn't want to write first then check, then write again.
And How would I get a random integer value in C? I used to the Random.Range in C#.
To keep it simple, it would best if you can make your string size the common denominator of 1KB (1024 bytes). So you don't have to take care fraction.
After that you can do as #naitoon mentioned above (range*1024)/s1->length. If each of the character of your string is 1 byte long.
As for random integer, you can call the standard library rand() which returns integer between 0 to RAND_MAX, which is at least 32767.
Also, in order to keep the random number with your range(0~500), you can do a modular of the return value.
range = rand() % 500;

Resources