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.
Related
Can anyone provide me with a help about how can I map containers?
For example if I a have text file, which I import, and as the code reads trough the file it needs to map the lines which start with the same value (for example 1).
So how can I check if that line exists and if it does then import it the table, if not make a new record. And so on ...
If code sample or anything else is needed, please ask!
If you use a TextIO to read a file record per record, you'll get a container for each line.
A container is a structure you can refer as a super array. It will allow you to store anything at each position of this array (string, int, object, etc...) regardless what's store in the rest of the container.
There are two ways get and set data in it. There are functions (https://msdn.microsoft.com/en-us/library/aa570072.aspx) or you can use brackets:
ItemId itemId;
Qty qty;
Price price;
Container c;
//Add two elements in the container
c = ["1001", 10];
//Add a third element at the end
c += [1.5];
//Get the elements
[itemId, qty, price] = c;
So, it's a really versatile tool and it comes with a price. You can't manipulate it as a map or other collection classes.
Finally, the TexIO.read() method will get a container at each line, so you need to deal with it at each time. If you have a record identifier, a key and then data, it could be something like:
Container c;
TextIO file;
Map map = new Map(Types::Integer, Types::Container);
int identifier, key;
[...]
c = file.read();
while (c)
{
[identifier, key] = c;
if (identifier == 1 && !map.exists(key))
{
map.insert(key, c);
}
c = file.read();
}
I'm working on a hardware virtual analog synthesizer using C, and I'm trying to come up with an efficient data structure to manage the dynamic assignment of synthesizer voices in response to incoming MIDI messages.
I have a structure type which holds the data for a single synthesizer voice (pitch, low frequency oscillator, ADSR settings, etc.) and I have a "NoteOn" callback function which is executed when a MIDI "Note On" message is decoded. This function needs to take an "idle" voice from an "idle" pool, modify some settings in the structure, and assign it to a "playing" pool that the main synth engine works with to generate audio samples. Then, when a "Note Off" message is received, the voice with a note value corresponding to the one in the "Note Off" message needs to be selected from the "playing" pool, have its data structure modified again, and eventually returned to the "idle" pool (depending on envelope/ADSR settings.)
I tried an implementation using linked lists for both pools, but my implementation seemed rather cumbersome and slow. I'd like this process to be as quick as possible, to maintain playing responsiveness. Any suggestions?
If a linked list is too slow, the usual answer is to implement a hash table. There many, many possible variations of the data structure and algorithm. I'll just describe open, "single"-hashing, because that's the variation I'm most familiar with.
So with an open hash table, the table is just an array ("closed" hashing has an array, too, but each element is a linked list). We want the array to be, at most, about half-full for performance reasons. And at maximum-capacity, the filled table will actually have one empty slot still, because this simplifies the algorithm.
We also need a hash function which accepts the type of the key values, and returns integers. It's very difficult to predict how the hash function will behave with respect to clustered keys and overall performance. So just make sure it's an isolated function that can easily be changed later. It can be as simple as shifting-around all the bytes and adding them together.
int hash (char *key, int key_length, int table_size)
{
int ret, i;
for (i=0, ret=0; i < key_length; i++)
{
ret += key[i] << i;
}
return abs(ret) % table_size;
}
The table-lookup function uses the hash function to decide where to start looking in the array. If the key isn't found there (determined by doing a memcmp() on the actual search key and the key stored at that position in the table), it looks at each successive key, wrapping from the end of the array back to the beginning, and declares failure if it finds an empty table element.
#define RETURN_TABLE_I_IF_EQUAL_KEY_OR_EMPTY \
if (memcmp(table + i, &key, sizeof key) == 0 || (key_type)table[i] == 0) \
return table + i;
key_value_pair *hash_lookup(key_value_pair *table, int table_size, key_type key)
{
int h, i;
h = hash(&key, sizeof key, table_size);
i = h;
RETURN_TABLE_I_IF_EQUAL_KEY_OR_EMPTY
for ( ; i < table_size; i++)
RETURN_TABLE_I_IF_EQUAL_KEY_OR_EMPTY
for (i=0; i < h; i++)
RETURN_TABLE_I_IF_EQUAL_KEY_OR_EMPTY
return NULL;
}
We'll need one more function in front of this to handle a few quirks. It can return a NULL pointer which indicates that not only has the key not been found, but the table itself is overfull. An overfull table, which really means "completely full", but we decided earlier that a "full" table should really have one empty element. This means that both for loops should not run to completion; when it finds an empty table position, that's a failure. With an overfull table, it has to scan the entire table before discovering that the key is not present, thus losing much of the performance advtantage from using a hash at all.
The lookup function can also return a valid pointer to an empty slot. This is also a failure to find the value, but not an error. If adding the key/value pair for the first time, this will be slot to store it.
Or it could return a pointer to the desired table element. And this will be faster than a linear search, be it an array or linked list.
Deleting a key from the table requires us to fill-in the vacated position in the sequence. There are a couple of options.
If you're not worried about the table running out of space (it's set really large, and the lifetime and usage can be controlled), you can overwrite the entry with a deleted special key, distinct from an empty key.
Or, if you want to reclaim the space, too, you'll need to lookup the key, and then scan the rest of the "chain" (sequence of keys up to the next empty slot (including wrap-around)) and move the last key with a matching hash into the key-to-delete's position. Then write-over this moved key/value's position with the empty key. .... oops! This process must be repeated for the this last matching key until we're actually clearing the very last key in the chain. (I need to go fix this in my implementation right now!....)
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).
I am trying to make a game similar to chess. I want the user to type in what position of the piece they want to move is, then were they want to move it... ( on an 8x8 grid - A1 through to H8)
I cant workout a simple way to find a variable from what the user has typed in. The code I currently have is:
void main() {
printf("Enter Piece to Move: ");
scanf("%s",&move);
printf("\n\nWhere would you like to move %s?:",move);
scanf("%s",&to);
[...]
What i also have is a variable list of all the location of pieces. What I would like to happen is, if the user was to enter A1 for the piece to move. I want the value of variable named A1 to be used. This is so I can have the current position of the piece and also what is in the place...
Hope this makes scene and someone can help :)
Take a look at the concept of arrays. If you have a 2-dimensional array, you just need to convert the letter 'A' to a number and use it as in index in the array.
You cannot refer to a variable if you dynamically obtain its name. There's just no way to do it in C, unlike, say, PHP.
You should do the mapping manually
int a[8][8];
char c1, c2;
scanf("%c%c", &c1, &c2);
a[c1-'a'][c2-'1'] = ???; //this is your variable
The above is almost a pseudocode. I mean, you should take care of bad inputs and many other things, but you should get the idea.
That is impossible in C. When your program is running the names of the variables don't exist anymore, they only exist in your code.
Instead you should be using something called an array. It would take far too long to explain here, I think you should read a book on C.
you should use 2 "holders" of your data, a board representation AND pieces positions like
enum {WKING=1,BKING,WPAWN,BPAWN,WQUEEN,BQUEEN,WBISHOP,BBISHOP,WKNIGHT,BKNIGHT,WROOK,BROOK};
int board[8*8];
/* positions: */
int wking,wqueen[9],wbishop[10],wknight[10],wrook[10],wpawn[8];
int sking,squeen[9],sbishop[10],sknight[10],srook[10],spawn[8];
...
setposFromTo(int piece,int from,int to) {
switch(piece) { case WKING: "set board AND position here" break; ... }}
This question brings me back to my college days, but since I haven't coded since those days (more than 20 years ago) I am a bit rusty.
Basically I have an array of 256 elements. there might be 1 element on the array, 14 or 256. This array contains the usernames of people requesting data from the system. I am trying to count the duplicates on the list so I can give the priority to the user with most requests. So, if I have a list such as:
{john, john, paul, james, john, david, charles, charles, paul, john}
I would choose John because it appeared 4 times.
I can iterate the array and copy the elements to another and start counting but it gets complicated after a while. As I said, I am very rusty.
I am sure there is an easy way to do this. Any ideas? Code would be very helpful here.
Thank you!
EDIT:
The buffer is declared as:
static WCHAR userbuffer[150][128];
There could be up to 150 users and each username is up to 128 chars long.
1 - sort your array.
2 - set maxcount = 0;
3 - iterate array and count until visitNEXT username.
4 - if count > maxcount then set maxcount to count and save name as a candidate.
5 - after loop finished, pickup the candidate.
Here's how I would solve it:
First, define a structure to hold user names and frequency counts and make an array of them with the same number of elements as your userbuffer array (150 in your example).
struct user {
WCHAR name[128];
int count;
} users[150];
Now, loop through userbuffer and for each entry, check and see if you have an entry in users that has the same name. If you find a match, increment the count for that entry in users. If you don't find a match, copy the user's name from userbuffer into a blank entry in users and set that user's count to 1.
After you have processed the entire userbuffer array, you can use the count values from your users array to see who has the most requests. You can either iterate through it manually to find the max or use qsort.
It's not the most efficient algorithm, but it's direct and doesn't do anything too clever or fancy.
Edit:
To qsort the users array, you will need to define a simple function that qsort can use to sort by. For this example, something like this should work:
static int compare_users(const void *p1, const void *p2) {
struct user *u1 = (struct user*)p1;
struct user *u2 = (struct user*)p2;
if (u1->count > u2->count)
return 1;
if (u1->count < u2->count)
return -1;
return 0;
}
Now, you can pass this function to qsort like:
qsort(users, 150, sizeof(struct user), compare_users);
What did you mean with "there might be 1 element on the array, 14 or 256". Are 14 and 256 element numbers?
If you can change the array definition I think the best way will be to define
a structure with two fields, username and numberOfRequests. When a user requests, if usernames exists in the list the numberOfRequest will be increased. If it is the first time the user is requesting username should be added to list and numberOfRequests would be 1.
If you can not change the array definition, one is to sort the array with quick sort or another algorithm. It will be easy to count the number of request after that.
However, maybe there is a library with this functionality, but I doubt that you can find something in Standard Library!
Using std::map as proposed by AraK, you can stock your names without duplicates, and associate your names to a value.
A quick example :
std::map<string, long> names;
names["john"]++;
names["david"]++;
You can then search which key has the biggest value.