user8026040
user8026040

Reputation:

How to create a value-key table of values from struct in C?

I have a struct of values:

struct Inst
{
    int opc;
    int opc2;
    int opc3;
    int imm;
    int imm2;
    int rs1;
    int rs2;
    int rd;
};

For each value, I want there to be a corresponding string that represents that value. So if opc = 0x3, then its corresponding string would be "OP-IMM". So value can be an input that I know of. It's just a matter of mapping that value to its corresponding string. Functionally, this would look like so:

printf("%s", lookup(opc)) // If the value is 0x37, then it prints LUI, if it's 0x6F, then it prints JAL etc...

How would I do that?

Upvotes: 0

Views: 566

Answers (2)

reyad
reyad

Reputation: 1432

The following code does, what you want...I am assuming you don't have much instructions. If you've much more instruction like a Million, you should use Balanced Binary Search Tree instead of array.(note: I am using linear search to find matching key with an average search complexity of O(n) for each search).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
    int *keys; // this to hold keys
    char **vals; // this to hold valsues or strings
    int size;
    int capacity;
} Table;

Table *getTable(int capacity) {
    Table *table = (Table *)malloc(sizeof(Table));

    table->keys = malloc(sizeof(int) * capacity);
    table->vals = malloc(sizeof(char *) * capacity);
    
    table->size = 0;
    table->capacity = capacity;
    
    return table;
}

int insert(Table *table, int key, char *val) {
    if(table->size >= table->capacity) {
        // couldn't add more key/val pairs
        // capacity overflowed
        return 0;
    }
    // copy val into new dymanic char array string
    int l = strlen(val);
    char *buf = malloc(sizeof(char) * (l+1)); // l+1 for null char at the end
    strcpy(buf, val);

    table->keys[table->size] = key;
    table->vals[table->size] = val;

    table->size++;
    return 1; // key/val pair add is successful
}

char *lookup(Table *table, int key) {
    for(int i=0; i<table->size; i++) {
        if(table->keys[i] == key) {
            return table->vals[i];
        }
    }
    return NULL;
}

void destroyTable(Table *table) {
    for(int i=0; i<table->size; i++) {
        free(table->vals[i]);
    }
    free(table->keys);
    free(table->vals);
    free(table);
}

int main() {
    int capacity = 10;
    Table *table = getTable(capacity);

    int k1 = 12;
    char *v1 = "hello";

    int k2 = 19;
    char *v2 = "world!";

    insert(table, k1, v1);
    insert(table, k2, v2);

    char *val = lookup(table, k1);
    printf("%d: %s\n", k1, val);

    val = lookup(table, k2);
    printf("%d: %s\n", k2, val);

    destroyTable(table);

    return 0;
}

And the output for my input was:

12: hello
19: world!

which ensures that it works properly.

Also, note I've used decimal integer. For use hexadecimal you could as follows:

int key = 0x37;

And you're done...

[P.S.]: feel free to ask if anything is unclear.

Upvotes: 0

If you have few numbers (few is relative; actually can be a million easily without problems, depending on the system), and a numbering where all of the possible numbers in a valid range have a meaning, or at least most of them, you can have a simple array.

Let's have the following codes table:

0x0: invalid
0x1: "aaa"
0x2: "bbb"
0x3: "ccc"
0x4: invalid
0x5: "ddd"

An easy and efficient way to build a lookup table is the following:

const char lut[6][MAX_STRINGLEN + 1] = {
        NULL, "aaa", "bbb", "ccc", NULL, "ddd"
};

And use the string simply by calling the array at the index of the code lut[opcode].


In C2x (the next revision of the standard), there is a way to initialize the array with a binary file, which if the array size is very big, can mean a significant improvement in compilation time.

Upvotes: 0

Related Questions