I have a problem right now where I'm trying to essentially bind a string to a value. What would be the easiest way to associate these values in C? I essentially want a Python like tuple that I can add to a list.
That's what C structures are for. For example, the following structure is a tuple which binds a string (up to twenty characters long) to an integer value:
typedef struct {
char strVal[21];
int intVal;
} tTuple;
Variables of type tTuple (or pointers to them if they're dynamically allocated) can be passed around, added to lists, and manipulated in any way that makes sense to your situation.
Using a structure similar to the one above, the following complete program shows this in action. It could probably do with some more sanity checks(a) but should be fine for just showing how to do a tuple (which is what the question was asking about):
#include <stdio.h>
#include <string.h>
static struct { char strVal[21]; int intVal; } tuple[10];
static int tupleCount = 0;
static void listTuples(void) {
printf("==========\nTuple count is %d\n", tupleCount);
for (int i = 0; i < tupleCount; ++i)
printf(" [%s] -> %d\n", tuple[i].strVal, tuple[i].intVal);
puts("==========");
}
static void addTuple(char *str, int val) {
printf("Adding '%s', mapped to %d\n", str, val);
strcpy(tuple[tupleCount].strVal, str);
tuple[tupleCount++].intVal = val;
}
static void deleteTuple(char *str) {
int index = 0;
while (index < tupleCount) {
if (strcmp(str, tuple[index].strVal) == 0) break;
++index;
}
if (index == tupleCount) return;
printf("Deleting '%s', mapped to %d\n", str, tuple[index].intVal);
if (index != tupleCount - 1) {
strcpy(tuple[index].strVal, tuple[tupleCount - 1].strVal);
tuple[index].intVal = tuple[tupleCount - 1].intVal;
}
--tupleCount;
}
int main(void) {
listTuples();
addTuple("aardvark", 31);
addTuple("buffalo", 41);
addTuple("camel", 59);
addTuple("dingo", 27);
listTuples();
deleteTuple("buffalo");
listTuples();
return 0;
}
The output of that program is:
==========
Tuple count is 0
==========
Adding 'aardvark', mapped to 31
Adding 'buffalo', mapped to 41
Adding 'camel', mapped to 59
Adding 'dingo', mapped to 27
==========
Tuple count is 4
[aardvark] -> 31
[buffalo] -> 41
[camel] -> 59
[dingo] -> 27
==========
Deleting 'buffalo', mapped to 41
==========
Tuple count is 3
[aardvark] -> 31
[dingo] -> 27
[camel] -> 59
==========
(a) Such as checking the string length and array count for overflow, or disallowing duplicate keys (if desired).
An alternate way to associate values of different types is to create parallel arrays. One array for each typed element, associated by having the same index.
char *strVal[5];
int intVal[5];
So strVal[0] is associated with intVal[0], and so on.
This way of representing a tuple can be applied even in a language without a struct or record type.
Related
I'm using the LXLE 14.04 distribution of Linux. I want to write a C program to read commands, interpret and perform them. I'd like the program to be efficient, and I do not want to use a linked list. The commands are operations on sets. Each set can contain any of the values from 0 through 127 inclusive. I decided to represent a set as an array of characters, containing 128 bits. If bit at position pos is turned on then the number pos is in the set and if the bit at position pos is turned off then the number pos is not present in the set. For example, if the bit at position 4 is 1, then the number 4 is present in the set, if the bit at position 11 is 1 then the number 11 is present in the set.
The program should read commands and interpret them in a certain way. There are a few commands: read_set, print_set, union_set, intersect_set, sub_set and halt.
For example, the command read_set A,1,2,14,-1 in the terminal will cause the reading of values of the list into the specified set in the command. In this case the specified set in the command is A. The end of the list is represented by -1. So after writing this command, the set A will contain the elements 1,2,14.
This is what I have so far. Below is the file set.h
#include <stdio.h>
typedef struct
{
char array[16]; /*Takes 128 bits of storage*/
}set;
extern set A , B , C , D , E , F;
This is the file main.c
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
set sets[6];
/*Below I want to initialize sets so that set[0] = A set[1] = B etc*/
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
void read_set(set s,char all_command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
typedef struct
{
char *command;
void (*func)(set,char*);
} entry;
entry chart[] = { {"read_set",&read_set} };
void (*getFunc(char *comm) ) (set,char*)
{
int i;
for(i=0; i<2; i++)
{
if( strcmp(chart[i].command,comm) == 0)
return chart[i].func;
}
return NULL;
}
int main()
{
#define PER_CMD 256
char all_comm[PER_CMD];
void (*ptr_one)(set,char*) = NULL;
char* comm; char* letter;
while( (strcmp(all_comm,"halt") != 0 ) & (all_comm != NULL))
{
printf("Please enter a command");
gets(all_comm);
comm = strtok(all_comm,", ");
ptr_one = getFunc(comm);
letter = strtok(NULL,",");
ptr_one(sets[*letter-'A'],all_comm);
all_comm[0] = '\0';
letter[0] = '\0';
}
return 0;
}
I defined a command structure called chart that has a command name and function pointer for each command. Then I have created an array of these
structures which can be matched within a loop.
In the main function, I've created a pointer called ptr_one. ptr_one holds the value of the proper function depending on the command entered by the user.
The problem is, that since user decides which set to use,I need to represent the sets as some variable, so that different sets can be sent to the function ptr_one. I thought about
creating an array in main.c like so
set sets[6];
sets[0] = A;
sets[1] = B;
sets[2] = C;
sets[3] = D;
sets[4] = E;
sets[5] = F;
And then call the function ptr_one in the main function like this ptr_one(sets[*letter-'A'] , all_command).
That way, I convert my character into a set.
The problem is that while writing the above code I got the following compile error:
error: expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
I also tried the following in the file main.c
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
But I got this compile error expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
I know similar questions have been asked, by they don't seem to help in my
specific case. I tired this set sets[6] = { {A.array},{B.array},{C.array},{D.array},{E.array},{F.array} } too but it did not compile.
What's my mistake and how can I initialize sets so that it holds the sets A though F?
I am trying to convert some binary code into assembly, but as part of the task, I'm not sure how to get the last 5 elements(of 8) in the array into a new array. As you can see I've managed to created an array for the opCode(the first 3 elements), but am not sure how to get the operand into a new array or edit the initial one.
All help is appreciated.
void convert_to_assembly(char bin[])
{
int i;
printf("The binary code before spiliting is: ");
char binary[9] = {'1','0','1','1','1','1','1','0'};
for(i=0;i<=7;i++)
{
printf("%c",binary[i]);
}
printf("\n");
char opCode[4];
strncpy(opCode,binary,3);
printf("opcode: ");
for(i=0;i<3;i++)
{
printf("%c",opCode[i]);
}
printf("\n");
}
Output
The binary code before splitting is: 10111110
opcode : 101
operand: ???????
This worked for me if I understood you correctly (based on #WhozCraig):
void convert_to_assembly(char bin[])
{
int i;
printf("The binary code before spiliting is: ");
char binary[9] = "10111110\0";
printf("%s\n",binary);
char opcode[4];
char operand[6];
strncpy(opcode,binary,3);
opcode[3]='\0';
strncpy(operand,binary+3,6);
printf("opcode: %s\n",opcode);
printf("operand: %s\n",operand);
}
strncpy will copy 6 chars starting at binary+3 to operand, which will copy the next six elements starting from the fourth one.
Since the binary string contains all the information, we can treat the opcode and operand as an overlay view using union without creating new arrays nor writing code to tear apart the data:
#include <stdio.h>
#include <string.h>
union word {
char binary[8];
struct operation {
char opcode[3];
char operand[5];
} opvar;
};
void convert_to_assembly(char *bin) {
union word op;
(void) strncpy(op.binary, bin, sizeof(op.binary));
printf("before splitting: %.8s\n", op.binary);
printf("opcode: %.3s\n", op.opvar.opcode);
printf("operand: %.5s\n", op.opvar.operand);
}
int main() {
convert_to_assembly("10111110");
return 0;
}
OUTPUT
> ./a.out
before splitting: 10111110
opcode: 101
operand: 11110
>
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;
}
I need to compare the contents of an element of a struct to another.
struct total_owners
{
int ADT2; //id number
char arkyk[7]; //license plate number
};
typedef struct total_owners owners;
struct total_offenses
{
char arkyk2[7];
int serious; //seriousness of offense (0 or 1)
};
typedef struct total_offenses offenses;
struct total_drivers
{
int ADT;
int ADO; //license number
};
typedef struct total_drivers drivers;
what I want to compare is arkyk2 in total_offenses with arkyk in total_owners. they are both of the format XXX1234 ( three letters and 4 numbers)
this is the function I am working on
void sumpoints(offenses* b,owners* a, drivers* c, int amountowners , int amountoffenses ,int amountdrivers)
{
int totals[amountdrivers][3],i,j,h;
for (i=0;i<amountdrivers;i++)
{
totals[i][0] = c[i].ADT;
totals[i][1] = c[i].ADO;
totals[i][2] = 0;
}
for (h=0;h<amountdrivers;h++)
{
for (i=0;i<amountowners;i++)
{
for(j=0;j<amountoffenses;j++)
{
if (a[i].arkyk == b[j].arkyk2) // this is wrong (definitely)
{
if (c[h].ADT == a[i].ADT2)
{
totals[h][2] = totals[h][2]+1;
}
}
}
}
}
for (i=0;i<amountdrivers;i++)
{
printf("Total offenses per driver:\n");
printf(" ADT %d \t ADO %d \t total %d\n", totals[i][0] , totals[i][1] , totals[i][2]);
}
}
the end result should be a totals array with the id number in the first column , the license number in the second and the amount of offenses in the last.
To do string comparison, you would change
if ( a[i].arkyk == b[j].arkyk2 )
to
if( strncmp( a[i].arkyk, b[j].arkyk2, 7 ) == 0)
As was pointed out by #notlikethat, using plain strcmp may run into trouble since you have a 7 element array to store 7 characters, so there is no space for a terminating '\0'. By specifying that the comparison should stop after 7 characters, you avoid this issue.
In C: Create a function called compare that takes the two different structures as parameters and returns a bool. Inside the function just do a string comparison with strcmp or strncmp
In C++:
Go nuts with operator overloading, it might look better, and will give you the same performance.
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