How to create an array of arrays in C - arrays

Using plain c, if I have the following two arrays:
WCHAR depthUnits[2][10] = { _T("feet"), _T("metres") };
WCHAR speedUnits[3][10] = { _T("ft/min"), _T("m/min"), _T("m/s") };
How can I create an array called say allUnits and fill it with the above so that it will behave like so:
allUnits[0][0] = "feet";
allUnits[0][1] = "metres";
allUnits[1][0] = "ft/min";
allUnits[1][1] = "m/min";
allUnits[1][2] = "m/s";
So basically allUnits is an array and each element of that array is itself an array such that allUnits[0] references depthUnits and allUnits[1] references speedUnits.
Thanks.

Sounds like you are looking for an array of pointers to array of 10 char. Further you want the array to have 2 elements.
That would be like:
WCHAR (*allUnits[2])[10];
allUnits[0] = depthUnits;
allUnits[1] = speedUnits;
An example using char instead of WCHAR:
#include<stdio.h>
int main()
{
char depthUnits[2][10] = {"feet", "metres" };
char speedUnits[3][10] = {"ft/min", "m/min", "m/s" };
char (*allUnits[2])[10];
allUnits[0] = depthUnits;
allUnits[1] = speedUnits;
puts(allUnits[0][0]);
puts(allUnits[0][1]);
puts(allUnits[1][0]);
puts(allUnits[1][1]);
puts(allUnits[1][2]);
// Change feet -> Feet using depthUnits
depthUnits[0][0] = 'F';
// See that it also changed allUnits
puts(allUnits[0][0]);
return 0;
}
Output:
feet
metres
ft/min
m/min
m/s
Feet

WCHAR *allUnits[2][3];
/* ... */
allUnits[0][0] = depthUnits[0];
allUnits[0][1] = depthUnits[1];
allUnits[1][0] = speedUnits[0];
allUnits[1][1] = speedUnits[1];
allUnits[1][2] = speedUnits[2];

This uses array initialization, maybe that's what you wanted:
#include <stdio.h>
int main(void)
{
char* allUnits[][3] = {
{"feet", "meters"},
{"ft/min", "m/min", "m/sec"}
};
printf("0 0: %s\n", allUnits[0][0]);
printf("0 1: %s\n", allUnits[0][1]);
printf("1 0: %s\n", allUnits[1][0]);
printf("1 1: %s\n", allUnits[1][1]);
printf("1 2: %s\n", allUnits[1][2]);
}

You can initialize an array of arrays like you would any other array.
WCHAR* depthUnits[] = { _T("feet"), _T("metres") };
WCHAR* speedUnits[] = { _T("ft/min"), _T("m/min"), _T("m/s") };
WCHAR** allUnits[] = { depthUnits, speedUnits };

Related

Passing Array to function using double pointer

I was trying to get array updated through a function as in below code and this works fine.
char bookCategory[][MAX_CATEGORY_NAME_LENGTH] = {"Computer", "Electronics", "Electrical", "Civil", "Mechnnical", "Architecture"};
uint8_t getCategoryNumAndName(char* catName, uint8_t choice)
{
choice = choice - 0x30 - 1; /** Category starts from 1 on the screen */
if (choice >= (sizeof (bookCategory) / sizeof (bookCategory[0])))
{
//catName = NULL;
return (0xff);
}
else
{
strcpy(catName,bookCategory[choice]);
//catName = bookCategory[choice];
return(choice);
}
}
void addBooks(void)
{
// Some code here
char categoryName[30];
uint8_t catNumber;
catNumber = getCategoryNumAndName(categoryName, choice);
// Some code here
}
But I thought of making use of double pointer instead of using strcpy(). I tried below code, but I get incompatible pointer type error. How to call getCategoryNumAndName() in below code from addBooks()?
uint8_t getCategoryNumAndName(char** catName, uint8_t choice)
{
choice = choice - 0x30 - 1; /** Category starts from 1 on the screen */
if (choice >= (sizeof (bookCategory) / sizeof (bookCategory[0])))
{
*catName = NULL;
return (0xff);
}
else
{
//strcpy(catName,bookCategory[choice]);
*catName = bookCategory[choice];
return(choice);
}
}
void addBooks(void)
{
// Some code here
char categoryName[30];
uint8_t catNumber;
catNumber = getCategoryNumAndName(&categoryName, choice);
// Some code here
}
You can only pass pointer address to getCategoryNumAndName function not array address.
You can do as below.
char *categoryName = NULL;
catNumber = getCategoryNumAndName(&categoryName, choice);
make sure you assign the memory to categoryName in getCategoryNumAndName before dereferencing it .
To just force the code to work, you need to cast categoryName to a char**. But reading your code, it seems like you just want to move the pointer? You don't need a fixed size array for the category name. Just use a pointer:
char* categoryName;

Dynamically enumerate keys in libconfig

in libconfig - is it possible to dymanically enumerate keys?
As an example, in this example config file from their repo - if someone invented more days in the hours section, could the code dynamically enumerate them and print them out?
Looking at the docs, I see lots of code to get a specific string, or list out an array, but I can't find an example where it enumerates the keys of a config section.
Edit
Received some downvotes, so thought I'd have another crack at being more specific.
I'd like to use libconfig to track some state in my application, read in the last known state when the app starts, and write it out again when it exits. My app stores things in a tree (of depth 2) - so this could be niceley represented as an associative array in a libconfig compatible file as below. The point is that the list of Ids (1234/4567) can change. I could track them in another array, but if I could just enumerate the 'keys' in the ids array below - that would be neater.
so
ids = {
"1234" = [1,2,3]
"4567" = [9,10,11,23]
}
e.g (psuedocode)
foreach $key(config_get_keys_under(&configroot)){
config_get_String($key)
}
I can't see anything obvious in the header file.
You can use config_setting_get_elem function to get n-th element of the group, array or list, and then (if it's group) use config_setting_name to get it's name. But AFAIK you can't use digits in key names. So consider following config structure:
ids = (
{
key = "1234";
value = [1, 2, 3];
},
{
key = "4567";
value = [9, 10, 11, 23];
}
);
Then you can easily enumerate through all members of the ids getting the values you want using the following code:
#include <stdio.h>
#include <libconfig.h>
int main(int argc, char **argv) {
struct config_t cfg;
char *file = "config.cfg";
config_init(&cfg);
/* Load the file */
printf("loading [%s]...\n", file);
if (!config_read_file(&cfg, file)) {
printf("failed\n");
return 1;
}
config_setting_t *setting, *member, *array;
setting = config_lookup(&cfg, "ids");
if (setting == NULL) {
printf("no ids\n");
return 2;
}
int n = 0, k, v;
char const *str;
while (1) {
member = config_setting_get_elem(setting, n);
if (member == NULL) {
break;
}
printf("element %d\n", n);
if (config_setting_lookup_string(member, "key", &str)) {
printf(" key = %s\n", str);
}
array = config_setting_get_member(member, "value");
k = 0;
if (array) {
printf(" values = [ ");
while (1) {
if (config_setting_get_elem(array, k) == NULL) {
break;
}
v = config_setting_get_int_elem(array, k);
printf("%s%d", k == 0 ? "" : ", ", v);
++k;
}
printf(" ]\n");
}
++n;
}
printf("done\n");
/* Free the configuration */
config_destroy(&cfg);
return 0;
}

Postgresql C function that takes a FLOAT8[] and returns an INT[]?

Could someone please provide a template for a C function that would receive FLOAT8[] values and return INT[] values?
The examples that I have found use the same input numeric type as the output numeric type.
I have not seen any examples that show how to create a new INT[] and return it.
One way:
INT *my_function1(FLOAT8 *float8)
{
INT *zzz = malloc(sizeof(INT) * 10);
zzz[0] = 123;
zzz[1] = 234;
...
return(zzz);
}
Call the above like this:
{
INT *aaa = NULL;
FLOAT8 bbb[10];
...
aaa = my_function1(bbb);
printf("%d, %d\n", aaa[0], aaa[1]); /* Output: "123, 234"
...
if(aaa)
free(aaa);
}
Another way:
void my_function2(FLOAT8 *IN_float8, INT **OUT_int)
{
INT *yyy=malloc(sizeof(INT) * 10);
zzz[0] = 123;
zzz[1] = 234;
...
if(OUT_int)
*OUT_int = yyy;
else
{
free(yyy);
fprintf(stderr, "Oops! You gave me a NULL pointer for OUT_int.\n");
}
return;
}
Call the above like this:
{
INT *aaa = NULL;
FLOAT8 bbb[10];
...
my_function1(bbb, &aaa);
printf("%d, %d\n", aaa[0], aaa[1]); /* Output: "123, 234"
...
if(aaa)
free(aaa);
}

C: initializing struct with an array of strings

I'm trying to do the following, but the compiler is complaining about brackets, however, I can't find my way to an alternative.
struct cards {
char faces[13][6], suits[4][9];
}
typedef struct cards cards;
void init_struct(cards *s) {
s->suits = {"hearts","spades","clubs","diamonds"};
s->faces = {"ace","two","three","four","five",
"six","seven","eight","nine"
"ten","jack","queen","king"};
}
I realize that there are several possible duplicate threads out there, but none of them has led me on the track. I hope one of you can :) Thanks
#include <string.h>
typedef struct cards {
char faces[13][6], suits[4][9];
} cards;
cards base_card = {
{"ace","two","three","four","five",
"six","seven","eight","nine", //forgot "," at nine after
"ten","jack","queen","king"},
{"hearts","spades","clubs","diamonds"}
};
void init_struct(cards *s) {
memcpy(s, &base_card,sizeof(cards));
}
The direct initialization syntax can only be used for initialization, not assignment. You cannot do this, for example:
char p[2][5];
p = {"a", "b"}; //error
That's why it fails to compile. Try strcpy-ing string by string
strcpy(s->suits[0], "hearts");
strcpy(s->suits[1], "spades");
...etc
or, alternatively, initialize a temporary array and then copy it
char suits_tmp[4][9] = {"hearts","spades","clubs","diamonds"};
memcpy(s->suits, suits_tmp, 4*9);
#include <string.h>
#include <stdio.h>
struct cards {
const char** suits;
const char** faces;
};
typedef struct cards cards;
const char* suits[4] = {"hearts","spades","clubs","diamonds"};
const char* faces[13] = {"ace","two","three","four","five",
"six","seven","eight","nine"
"ten","jack","queen","king"};
int main()
{
cards deck;
deck.suits = suits;
deck.faces = faces;
printf(deck.suits[0]);
return 0;
}
This works as well. Uses no pointers.
Clarification
I know mine is the quick and dirty answer, but there is no strcpy or memcpy or a long list of assignments. If your plan is to use the standard deck of cards for your game, then it would be a constant set of values anyway. If your intent is to have different types of decks, then my answer may not be adequate. Yes, it doesn't have a init_struct function, but you could easily modify it for your intent (since I am not well versed in C and malloc.)
Use const char * within your struct (I assume there is no requirement to modify the actual content of the suit/face value) and initialise them individually:
struct cards {
const char *suits[4];
const char *faces[13];
};
typedef struct cards cards;
void init_struct(cards *s)
{
s->suits[0] = "hearts";
s->suits[1] = "spades";
s->suits[2] = "clubs";
s->suits[3] = "diamonds";
s->faces[0] = "ace";
s->faces[1] = "two";
s->faces[2] = "three";
s->faces[3] = "four";
s->faces[4] = "five";
s->faces[5] = "six";
s->faces[6] = "seven";
s->faces[7] = "eight";
s->faces[8] = "nine";
s->faces[9] = "ten";
s->faces[10] = "jack";
s->faces[11] = "queen";
s->faces[12] = "king";
}
Of course, if you just want a one-off set of cards, which is reasonable, then this will work:
struct
{
const char *suits[4];
const char *faces[13];
} cards =
{
{"hearts","spades","clubs","diamonds"},
{"ace","two","three","four","five",
"six","seven","eight","nine",
"ten","jack","queen","king"}
};

how to best achieve string to number mapping in a c program

I have a definite set of strings and its corresponding numbers:
kill -> 1
live -> 2
half_kill -> 3
dont_live -> 4
List is of 30 such strings and their number mapping.
If user enters "kill", I need to return 1 and if he enters "dont_live" I need to return 4.
How should I achieve this in c program? I am looking for an efficient solution because this operation needs to be done 100s of times.
should I put them in #define in my .h file?
Thanks in advance.
Sort your table, and use the standard library function bsearch to perform a binary search.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct entry {
char *str;
int n;
};
/* sorted according to str */
struct entry dict[] = {
"dont_live", 4,
"half_kill", 3,
"kill", 1,
"live", 2,
};
int compare(const void *s1, const void *s2)
{
const struct entry *e1 = s1;
const struct entry *e2 = s2;
return strcmp(e1->str, e2->str);
}
int
main (int argc, char *argv[])
{
struct entry *result, key = {argv[1]};
result = bsearch(&key, dict, sizeof(dict)/sizeof(dict[0]),
sizeof dict[0], compare);
if (result)
printf("%d\n", result->n);
return 0;
}
Here's what you get when you run the program.
$ ./a.out kill
1
$ ./a.out half_kill
3
$ ./a.out foo
<no output>
PS: I reused portions of sidyll's program. My answer should now be CC BY-SA compliant :p
A possible solution:
#include <stdio.h>
#include <string.h>
struct entry {
char *str;
int n;
};
struct entry dict[] = {
"kill", 1,
"live", 2,
"half_kill", 3,
"dont_live", 4,
0,0
};
int
number_for_key(char *key)
{
int i = 0;
char *name = dict[i].str;
while (name) {
if (strcmp(name, key) == 0)
return dict[i].n;
name = dict[++i].str;
}
return 0;
}
int
main (int argc, char *argv[])
{
printf("enter your keyword: ");
char s[100]; scanf("%s", s);
printf("the number is: %d\n", number_for_key(s));
return 0;
}
Here's one approach:
int get_index(char *s)
{
static const char mapping[] = "\1.kill\2.live\3.half_kill\4.dont_live";
char buf[sizeof mapping];
const char *p;
snprintf(buf, sizeof buf, ".%s", s);
p = strstr(mapping, buf);
return p ? p[-1] : 0;
}
The . mess is to work around kill being a substring of half_kill. Without that issue you could simply search for the string directly.
If it is a very short list of strings then a simple block of ifs will be more than sufficient
if (0 == strcmp(value, "kill")) {
return 1;
}
if (0 == strcmp(value, "live")) {
return 2;
}
...
If the number approach 10 I would begin to profile my application though and consider a map style structure.
if you have a fixed set of strimgs, you have two options: generate a perfect hashing function (check gperf or cmph) or create a trie so that you never have to check charcters more than once.
Compilers usually use perfect hashes to recognize a language keyword, in your case I would probably go with the trie, it should be the fastest way (but nothing beats direct measurement!)
Is it really a bottleneck? You should worry about efficiency only if the simple solution proves to be too slow.
Having said that, possible speed improvements are checking the lengths first:
If it's 4 characters then it could be "kill" or "live"
If it's 9 characters then it could be "half_kill" or "dont_live"
or checking the first character in a switch statement:
switch (string[0]) {
case 'k':
if (strcmp(string, "kill") == 0)
return 1;
return 0;
case 'l':
...
default:
return 0;
}
Use hashmap/ hashtable i think this would be the best solution.
Can you use an Enumunerator?
int main(void) {
enum outcome { kill=1, live, half_kill, dont_live };
printf("%i\n", kill); //1
printf("%i\n", dont_live); //4
printf("%i\n", half_kill); //3
printf("%i\n", live); //2
return 0;
}
Create a list of const values:
const int kill = 1;
const int live = 2;
const int half_kill = 3;
etc

Resources