idiomatic C for an int to const string map - c

How can I express in C a map like this one?
{
{1, "One"},
{1000, "One thousand"},
{1000000, "One million"}
}
The key is an int and can be a big int, the value is a constant string and it is known at compile time.
The map will contain some 20 or 30 elements.
I would write this function:
const char* numbers( const int i )
{
switch( i ) {
case 1: return "One";
case 1000: return "One thousand";
case 1000000: return "One million";
default: return "";
}
}
is there any better (more idiomatic) way of doing it?

Using a switch is entirely idiomatic C, there's a separate style consideration (that would apply in pretty much any language) whether you want to separate the key/value data out of the program logic.
You could use an array of const struct { int key; const char *value; };, but then you'll start worrying about whether you should use a linear search, binary search, perfect hash, etc. With a switch, the compiler takes it out of your hands.
If you have some kind of associative container (tree or hashmap) that you use for other things in this project then you could use that, but it's not really worth writing one for a 30-item collection.

Just like you did:
typedef struct {
long long key;
char *val;
} Item;
const Item mydict[] = {
{1, "One"},
{1000, "One thousand"},
{1000000, "One million"}
};
I leave as an exercise the body of numbers() function.
The alternate solution suggested by Steve Jessop is perfectly valid as well.

If all is statically known, I would go with something like this:
char strings[][] = {"One", "One thousand", "One million", /* whatever */};
int map[] = {1, 1000, 1000000};
const char *numbers(const int i)
{
position = search(map, i);// if the array is too small, just linear search
// if it is big, you can binary search
// if there is a relation use a formula
// although a formula is not extendable.
// In this case, it is log(i) in base 1000.
return strings[position];
}
This method can be extended for non-static data. You just have to make sure you correctly fill the strings array and keep the map sorted.
Note: Obviously, you should add sufficient error-checking etc. For example in the case where search couldn't find i.

This could be one solution.
Basically create sorted array of key-value pairs and then just use bsearch-function (performs binary search) to quickly find the correct value. It might make sense to implement your own binary search to make searching more convinient.
#include <stdlib.h>
#include <stdio.h>
typedef struct mapping
{
int key;
char* value;
} Mapping;
int mappingCompare(const void* a, const void* b)
{
const Mapping* first = (const Mapping*)a;
const Mapping* second = (const Mapping*)b;
return second->key - first->key;
}
int main()
{
Mapping map[3];
Mapping search;
Mapping* result;
map[0].key = 1;
map[0].value = "One";
map[1].key = 1000;
map[1].value = "One thousand";
map[2].key = 1000000;
map[2].value = "One million";
//qsort is only needed if the map is not already in order
qsort(map, 3, sizeof(Mapping), mappingCompare);
search.key = 1000;
result = (Mapping*)bsearch(&search, map, 3, sizeof(Mapping), mappingCompare);
printf("value for key 1000 is %s\n", result->value);
}

Related

Comparing Char* to Enum variable in C

So I'm trying to utilize Enumerated types in C for the first time. So I have an Enumerated "variable?" declared and I also have a struct which has a variable of the Enumerated type(among other things). Finally I have a static array for which there is an element containing each of the enum "types?" in the same order they were declared. I am hoping to use the enum type to act as an index for the array.
So my problem is that I need to somehow relate a char* variable to the enumerated type. If I KNOW that the Char* variable is one of the enum types, is there some way to assert that without having to look at each char to determine which specific enum"option" it is?
Example:
enum example = {abc,def}
struct _strExample {
enum example letters;
....
};
typedef struct _strExample strEx;
static strEx Table[2] = {
{abc,...}
{def,...}
};
//Given char* "abc" , want either example.abc or 0 ( correct index of table)
So given the char* "abc"(does not need to be char*), is there a simple way to get either the correct enum "type?"(abc or def)or the correct index of the table? I know that I could check all the individual chars in the char* and manually determine which enumerated "type?" it is, but I am going to be working with a very large set of enumerated variables and this kind of thing is exactly what I was trying to avoid. any help or advice you guys could give on enumerated types and/or my design would be most appreciated.
Use a an array of strings where the index into the array is the enum value. If the strings are all short, or all about the same length, storing the string in the array makes sense. Otherwise, use a char* pointer.
typedef enum enum_t { plugh, plover, xyzzy, y0 } enum_t;
const char *etable = { "plugh", "plover", "xyxxy", "y0", NULL };
With that, you can convert with a simple search like:
enum_t find_enum(char *sval)
{
enum_t result=plugh; /* value corresponding to etable[0] */
int i=0;
for (i=0; etable[i]!=NULL; ++i, ++result)
if (0==strcmp(sval, etable[i])) return result;
return -1;
}
The enum-to-string converstion is simply etable[e-plugh]. Those allow for a different definition of enum_t where the first meaningful value may not be 0, but the values are sequentially assigned thereafter.
No, you can't lookup any scalar value from a character array. You have to iterate over a set of strings to compare and find the relation to the enum member.
You can use an array of structs
typedef struct { int value; const char * name; } lookup_t;
lookup_t lookup[] = {
{ 1, "One"},
{ 0, NULL} // end tag, alternatively use the _countof(lookup) to get the number of elements
};
and compare your char* with the name member. Then you use the value on match.
Use if :
char *ex = "abc";
strEx strex;
if(!(strcmp("abc",ex))) {
strex.letters = abc;
}
else {
strex.letters = def;
}

How to implement an enum with specific values for its members?

I could be going about this all wrong, and it could be that an enum does is not a good way to solve this problem, but I am really not sure where to go with it otherwise.
Basically, I have non-sequential codes that correspond to certain strings. For example,
9 = "Enter"
10 = "Right"
15 = "Left"
17 = "Down"
And so on. I currently have this implemented with a large set of definitions:
#define ENTER_INDEX 0
#define RIGHT_INDEX 1
That is used to index into a char* array:
char* array[] = { "Enter", "Right" };
And when I receive information regarding which code was received, I then print the strings with a huge switch-case.
Any ideas on how to do this more efficiently? Is an enum a good approach?
Sure, you can use an enum, but that won't help you associate the names with the numerical values.
The problem is that you can't declare an enum and a string "in parallel" from the same source code characters, without using trickery such as X macros. Even then you probably won't solve the requirement for different casing which your code shows. Which you might want to avoid, because obfuscation.
The enum would be just:
typedef enum {
ID_ENTER = 9,
ID_RIGHT = 10,
ID_LEFT = 15,
ID_DOWN = 17
} Id;
I would then use C99's fantastic support for explicit indexes in array initializers to declare an array of strings indexed by an Id:
static const char *id_names[] = {
[ID_ENTER] = "Enter",
[ID_RIGHT] = "Right",
/* add more */
};
Note that the above is independent of the order, since each element initializer has an explicit index. This makes it very robust.
You can of course use a macro to cut down on the repetition, but that will make an all-caps string array:
#define DECL_ID(i) [ID_ ## i] = #i
static const char *id_names2[] = {
DECL_ID(ENTER), DECL_ID(RIGHT), /* add more */
};
To implement an enum with specific values for its members can be done by
enum options_en
{
Enter=9,
Right=10,
Left=15,
Down=17,
Default=0;
} ;
then you can declare a variable which can take only values defined in the enumerated type
options_en opt_val = Default;
For exploring more information about your question , refer this link, Found it very useful and is relevent to your question
http://www.cprogramming.com/tutorial/enum.html
A dictionary or hash table can be used. In c++ stl libraries I don't recall the name of the collection but in short y. use dictionaries/hashtables with generics.
So in your case you fill up the dictionary with key value pairs and when your later use the collection you can get a value using your key.
So it gets rid of switch statements and enums and will allow you to map any two types. Here is pseudo code
Value = dictionary[key]
So if key is 0 then the value will be set to Enter based on your example.
In short lookup examples for c++ and dictionary as I am answering from mobile phone and could not direct you to the exact collection name.
You can also create a map during initialization:
#include<stdio.h>
typedef struct { int code; const char *str; } key_info;
key_info keys[] = {
{9, "Enter"}, {10, "Right"}, {15, "Left"}, {-1, NULL}
};
#define MAX_KEY_CODE 15
size_t keymap[MAX_KEY_CODE + 1];
int main ( ) {
size_t i;
for (i = 0; keys[i].str; i++) {
keymap[keys[i].code] = i;
}
printf("%s\n", keys[keymap[10]].str);
return 0;
}
A huge switch is not a bad solution. The question is why do you need an extra array of names. Why don't you return directly string literals from the switch?
char *name(int code) {
switch (code) {
case 9: return("Enter");
case 10: return("Right");
case 15: return("Left");
...
}
}

mutidimension array with muti dimension data types in c

I have to implement a strange data structure. There is a queue, which contains memory allocations(it may be a queue or array but no-Linked list or anything that use malloc() in the code).
and we have to use this body:-
Struct //we don't have to use pointer in structure in achieving the task
{
int frequency;
unsigned char symbol;
short int left,right;
}
Here you can see that we have alphabets like a,b,c,d and e at the first index and their corresponding frequency on second index and the other two index are not useful for the moment but we have to allocate memory for them right now.
For now only thing which is useful for us is just the second index (which is the frequency of alphabets). What i have to do in this question is two add the two minimum frequency (i have to to put that it at a place so that increasing order must be maintained) for example: You can see below we add first two nodes frequency: So for the first index we obtained result of "a+b",Lets say "z"(a+b=z) and for second index(3+3=6) and the other two index are "0" and"0" , so not useful for us. and we have to now adjust this obtained memory such that it maintains increasing order of frequency
Now question is :
(1) Any ideas how to implement this type of data structure ? (without using pointer,malloc() , linked lists etc.) (but can use queue/stack), Moreover we can use memcpy() for shifts.
(2) How to achieve sorting in this type of case (but it's secondary thing , first how to implement it ?) (I am sorry i am tagging this question at the topics which could make the solution of this question, sorry for this)
And please do not hesitate me to ask if you don't understand anything in this question.
Is this structure primarily being used for searching or for storing? Are you going to be constantly adding and removing elements, or is it going to stay fairly static?
Assuming I understand the problem (which is not guaranteed), it sounds like the simplest approach would be to use a regular array of your struct type1:
struct afreq {
int freq;
unsigned char sym; // why unsigned? why not just plain char?
short int left,right;
};
...
struct afreq data[N]; // where N is large enough for as many elements
// as you need
size_t dataSize;
Use the qsort library function to order your array as necessary. You'll have to write a comparison function to pass to qsort:
int cmpAfreq( const void *lhs, const void *rhs )
{
const struct afreq *l = lhs;
const struct afreq *r = rhs;
if ( l->freq < r->freq ) return -1;
if ( l->freq > r->freq ) return 1;
return 0;
}
So, assuming you start out with something like the following:
struct afreq data[N] = { {3, 'a', 0, 0 }, {3, 'b', 0, 0}, {4, 'c', 0, 0 },
{6, 'd', 0, 0 }, {9, 'e', 0, 0} };
size_t dataSize = 5;
you could add a new element like so:
struct afreq newItem;
newItem.freq = data[i].freq + data[j].freq;
newItem.sym = 'z';
newItem.left = newItem.right = 0;
if ( dataSize < N )
{
data[dataSize++] = newItem;
qsort( data, dataSize, sizeof data[0], cmpAfreq );
}
else
{
// data array is full, can't add another element
}
To remove an element from the array, you could overwrite the element to be removed with the last element, reduce the counter by 1, and re-sort the array:
data[i] = data[dataSize--];
qsort( data, dataSize, sizeof data[0], cmpAfreq );
This is by no means efficient; having to fully re-sort the array every time you add or remove data will be expensive (especially since qsort's performance is poor on already-mostly-sorted arrays). But this is probably the most straightforward implementation I can think of.
1. Actually, it sounds like the simplest approach would be to use a language like C++ or Java or Python or just about anything else that provides a map or similar container, keyed on your sym member
I think that you might as well declare an array of 26 of your structs, because it appears that you can only have one entry for each letter, no more
struct counting_thing //we don't have to use pointer in structure in achieving the task
{
int freq;
unsigned char sym;
short int left,right;
}
struct counting_thing ordered_things[25]; // one entry for each letter [a-z]
Then, you simply need a sorting algorithm that operates on an array of nodes and uses the freq element of each node as the basis of comparision.

Word count in C, learning more CS

After about 5 years of programming in dynamic languages such as Python and JS I am starting to feel I'm missing out of what happens under the hood. Languages such as these are really great because they let you focus on what you have to do leveraging the trouble of working with pointers, memory allocation and many searching, sorting, inserting algorithms. Even though I never regret using these languages as I really feel they are ridiculously powerful I feel that, in order to become a better programmer, I need to take a step back and understand what happens under the hood!
I decided to do this by writing a simple word counter: The app gets all the params and outputs all the unique words, each one with a counter: "Hello world Hello" would return "Hello: 2", "world: 1" (not taking in consideration the actual output structure). This program is the Python equivalent of:
import sys
from collections import defaultdict
def main():
results = defaultdict(int)
for word in sys.argv[1:]:
results[word] += 1
print results
Writing it in C is a bit different, I feel like I'm getting something utterly wrong with pointers, arrays of pointers and all that stuff! I want to get better, Help me get better!!
#include <stdio.h>
#include <stdlib.h>
// This is what a key-value pair: <int, string>
typedef struct {
int counter;
unsigned char* word;
} hashmap;
// Checks if inside the array of results, hashmap->word is equals to word paramter
hashmap* get_word_from_results(hashmap* results[], int count, const char* word) {
int i;
hashmap* result;
for (i = 0; i < count; i++) {
result = results[i];
if (result->word == (unsigned char *)word)
return result;
}
return NULL;
}
int main(int argc, const char *argv[])
{
hashmap* results;
int results_counter = 0;
int i;
const char* word;
for (i = 1; i < argc; i++) {
word = argv[i];
hashmap* result = get_word_from_results(&results, results_counter, word);
// If result is NULL, means word is not inserted yet, let's create a new hashmap and insert it inside the array
if (result == NULL) {
hashmap h;
h.counter = 1;
h.word = (unsigned char *)word;
results = realloc(NULL, (results_counter + 1) * sizeof(hashmap) );
// NOTE: potential memory leak? would h be deallocated?
results[results_counter] = h;
results_counter++;
printf("NEW\n");
} else {
// The word already exists in the hashmap array, let's increase it by 1
result->counter++;
printf("INCREMENTED\n");
}
}
return 0;
}
Can anyone give me some advice? what am I doing wrong here? Are my pointers okay? also I think I spotted a memory leak (see comments), would anyone like to submit their version??
Thanks!! you guys are so cool!!
Daniel
The major pointer issue in your program is that when hashmap* results is passed to realloc for the first time, its value is uninitialized. This is undefined behavior. You should initialize the pointer to NULL, like this:
hashmap* results = NULL;
The other problem is comparing strings: you need to use strcmp rather than ==. Remember that strcmp returns zero when strings are equal.
There are also memory leaks at the end of your program. You should free results, along with the words that are stored inside its elements.
Of course the thing that you call hashmap behaves precisely like a dynamic array. Programming a hash table in C presents a different level of challenge, however, so I would encourage you to make your current approach work.

Value lookup table in C by strings?

If I have a set of small string values, and I want to fetch a numeric value to represent them, what's the best way to do this via a lookup table?
If I were only needing to do a straight look up, I know the optimal solution would just be a series of if statements:
if (strcmp(str, "foo") == 0)
tmp = FOO;
else if (strcmp(str, "bar") == 0)
tmp = BAR;
But, I ask this because these small string values represent an attribute in a small project I'm writing in C, and the attributes can be read-only or read-write (no write-only for now, maybe never).
So what I currently do just to make sure things work is have a lookup function comprised of an if-then clause like above to look up which values are read-only, and a second functions that looks up which values are read-write. But this is large and ugly to me.
I'm thinking, have three functions instead. One function is the lookup function, and it returns an int value that is the numeric form of the string. But this lookup function can also take a flag that determines whether it fetches a read-only value, or a read-write value. If a write operation is done on a value that is really read-only, the function will return -EINVAL (or something equivalent).
The other two functions, now still the read and write, just call this lookup function, passing in a string of the value, and the flag that determines whether they're for reading or writing.
Thing is, I don't know how this is modeled in C (if it can be modeled), and searching Google is tiresome with all the content farms ripping this place off (and giving me C++/C# answers instead).
So this is how I think it'll look:
int lookup_func(const char *name, const char *flag) {
int tmpval = 0;
/* code to do the lookup. */
if (tmpval == 0)
return -EINVAL;
else
return tmpval;
}
int get_readonly_bit(const char *name) {
return lookup_func(name, "ro");
}
int get_readwrite_bit(const char *name) {
return lookup_func(name, "rw")
}
Thoughts? The idea is to reduce code size by not repeating the if-then branches for these two functions, which differ slightly in overall design, and simply let some kind of a lookup function figure out what function this value serves.
Do you not consider just putting a table in? A hash table is also fine if there are lots of properties.
int lookup(const char *name)
{
typedef struct item_t { const char *name; int writable; int value; } item_t;
item_t table[] = {
{ "foo", 0, FOO },
{ "bar", 1, BAR },
{ NULL, 0, 0 }
};
for (item_t *p = table; p->name != NULL; ++p) {
if (strcmp(p->name, prop_name) == 0) {
return p->value;
}
}
return -EINVAL;
}

Resources