C- trying to code a 'spare array'; 'enum' fauled.


 
Thread Tools Search this Thread
Top Forums Programming C- trying to code a 'spare array'; 'enum' fauled.
# 1  
Old 09-07-2012
C- trying to code a 'spare array'; 'enum' fauled.

I am trying to implement a spare array in C that would be referenced by regular integers.
Right away: define array for maximum possible index elements completely is not what I trying to get!!!

It should be a construction that would have just 2 elements if I need to have just two indexes, like 2000 and 5, let say.

(Genarally, as a hash in perl, for example)
If I need to have that indexed by strings or characters, the 'enum' allows to nicely prepare that.

But with integers it is not compiled.
I mean no way to define
Code:
  enum E_TYPE {1,4,2};

By usage my intention is to have a way to work with an array of numbers referencing to elements by another set of numbers, that could be not consecuensed, not from 0 and without using the search by any way (loop, or any other smartness)

So, I would have related info-array, say, like this:
Code:
struct {int key; int val;} Inf_Arr[] = {
   {25, 44},
   {35, 55},
   (1,  99} };

And I would like to get Int_Arr[n].val by some Ref_Arr[ Int_Arr[n].key ]

So, having int a = Ref_Arr[25]; - I would have a==44

One again, I would like to construct data in a way to be able access the 'val' by the 'key' and (!!) - without using a 'switch-case', if, or any loop for each single 'key' through whole Inf_Arr[]

Does anybody know how it could be done?
Any idea?
# 2  
Old 09-07-2012
I have no idea what you're even trying to do with that enum. Usually you'd make an enum like enum { TITLE1=3, TITLE2=5, TITLE3=99 }; so that when you use TITLE1 in your code it becomes the number 3, and so forth. Their values are fixed at compile time, just like a #define and such.

I think you mean 'sparse array', not 'spare array'.

The C language's features closely match the CPU's features, so complex data types like sparse arrays aren't directly supported. You can make them, though. Here's a quick-and-simple one which works as a simple list like you wanted. Not the most efficient if you want it to hold thousands of numbers, but for a few dozen, should be fine...

Code:
#include <stdio.h>
#include <stdlib.h>

typedef struct pair {        int key, value;    } pair;

typedef struct sparse {
        int size, pos;
        pair *p;
}  sparse;

void sparse_free(sparse *s);
sparse *sparse_create(void);
int sparse_get(sparse *s, int key);
int sparse_set(sparse *s, int key, int value);

int main(void)
{
        int n;
        sparse *s=sparse_create();

        // Add a bunch of random elements to the sparse array
        // Keys will be numbers 0 through 7.  Values will be 0 through 10.
        for(n=0; n<10; n++)     sparse_set(s,rand()%8, n);
        // Find everything that was set.  Absent items will show as -1
        for(n=0; n<8; n++)      printf("key %d value %d\n", n, sparse_get(s, n));

        // Print the literal contents of the array raw
        printf("\nContents of sparse array\n");
        for(n=0; n<s->pos; n++)
                printf("I %d\tK %d\tV %d\n", n, s->p[n].key, s->p[n].value);

        sparse_free(s);
        return(0);
}

sparse *sparse_create(void)
{
        sparse *s=malloc(sizeof(sparse));
        if(s == NULL) return(NULL);

        s->size=16;     s->pos=0;
        s->p=malloc(sizeof(pair)*16);
        return(s);
}

int sparse_get(sparse *s, int key)
{
        int n;
        for(n=0; n<s->pos; n++) if(s->p[n].key == key) return(s->p[n].value);

        return(-1);
}

int sparse_set(sparse *s, int key, int value)
{
        int n;

        // Hunt for key.  If found, just update and return.
        for(n=0; n<s->pos; n++)
        if(s->p[n].key == key)
        {
                s->p[n].value=value;
                return(0);
        }

        // Add 16 more elements if full
        if(s->pos >= (s->size - 1))
        {
                pair *p=realloc(s->p, sizeof(pair) * (s->size+16));
                if(p == NULL) return(-1);
                s->size += 16;
                s->p=p;
        }

        // Add to end.
        s->pos++;
        s->p[s->pos].key=key;
        s->p[s->pos].value=value;
        return(0);
}

void sparse_free(sparse *s){ if(s) { free(s->p); free(s); } }

Code:
$ gcc sparse.c
$ ./a.out

key 0 value 0
key 1 value 8
key 2 value 6
key 3 value 3
key 4 value 7
key 5 value -1
key 6 value 1
key 7 value 5

Contents of sparse array
I 0     K 0     V 0
I 1     K 7     V 5
I 2     K 6     V 1
I 3     K 1     V 8
I 4     K 3     V 3
I 5     K 2     V 6
I 6     K 4     V 7

$


Last edited by Corona688; 09-07-2012 at 03:44 PM..
# 3  
Old 09-07-2012
Corona688 -
Thanks for replay. Not what I have asked, but appreciate attention!

'Spare'=='Sparse', thank for correction and sorry for misspelling.
Regarding the >>enum E_TYPE {1,4,2};<< I actually mean to have an ability to define an association like: typedef enum E_TYPE {1=0,4=1,2=2} E_TP; (Agree, looks ugly, but why not?)
So use it like " int a = (E_TP)4;" and get a==1.
Would be usefull Smilie

Unfortunately, your code is not appliable to my intention.

First:
to have an element the loop should be used: I would like to avoid run a loop on any info-by-key request!
Whith loop my task could be done absolutely simple:
Code:
  struct { int key,val; }INF[] = {{10,5},{20,4},{40,8}};
  int get_val(int key) {
    int i;
    for(i; i<(sizeof(INF)/sizeof(INF[0]);i++) 
       if (INF[i].key==key) return INF[i].val;
  }

That it! No any smart structure with the conditions static members, no any extra complication with pointing to internal member-array, no any dynamic allocations.
(BTW, in your example it is completely unneeded: assign values in declaration and define 'p' as sized array, if you use '16' in function.)

Second: My 'big point' is to define a data construction and avoid as possible any run-time functionality to get a value (except some initialization on beginning)


I'l try to explain again:

I have in a header file an INF array of structures with two integers .
I would like to construct a way to access second value by the first one.
And I'd like to do it WITHOUT any loop through whole INF array!

Also, I going to be able to make changes in the header file without touching the source code when I need add, change or remove a pair in the INF array.

If it would be not integer 'key', I would implement it with 'enum', having a reference-array, that by enumerated values (by default - the same as an array is indexed) would return the INF array index for member with 'key'-label (the enumeration element). By that I would heve the val-value!
That array would be initialized on beginning by one time loop through the INF array and assigning the INF index to the REF-array element with the index==enumerated value of the first INF int: key!
(Hope, now I have better explained what I am looking for?)

Last edited by alex_5161; 09-07-2012 at 04:52 PM..
# 4  
Old 09-07-2012
Quote:
Originally Posted by alex_5161
Corona688 -
Thanks for replay. Not what I have asked, but appreciate attention!

'Spare'=='Sparse', thank for correction and sorry for misspelling.
Regarding the >>enum E_TYPE {1,4,2};<< I actually mean to have an ability to define an association like: typedef enum E_TYPE {1=0,4=1,2=2} E_TP; (Agree, looks ugly, but why not?)
Because 1 isn't 0? Smilie enums are just integers, their definitions don't change the laws of mathematics.

I think you might be confused about what an enum is. They're integers, pure and simple. Declaring a variable to a certain type of enum is just telling the programmer which set of values it belongs to, the compiler doesn't do anything special with it. Their labels are just labels, they can't redefine the value of '1'. You can't even convert a number back into an enum's string. There's no connection.

Quote:
First:
to have an element the loop should be used: I would like to avoid run a loop on any info-by-key request!
If you must avoid a loop and get it exactly right the first look every time, you need a lookup table. This can be done in as little as one instruction sometimes. If you know for a fact you won't have any numbers higher than 255, it wouldn't even be a very large lookup table...

Code:
int lookup(unsigned char v)
{
        static const int l_val[256]={ // static locals are like globals, initialized once on program load
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        return(l_val[v]);
}

If you're using the GNU compiler, you can write it much more tersely(though the table will still be 256 elements):

Code:
int lookup(unsigned char v)
{
        static const int l_val[256]={ [10]=5, [20]=4, [40]=8 }
        return(l_val[v]);
}

Quote:
(BTW, in your example it is completely unneeded: assign values in declaration and define 'p' as sized array, if you use 16 in function.
I had thought you wanted a general-purpose sparse array.

The CPU will never psychically know which in an array of 3 elements has the one you want. It has to look. If you make it a lookup table, the problem is solved, since to find element 3, you look inside index 3...

Quote:
If it would be not integer 'key', I would implement it with 'enum'
enum's are integers. Their labels don't have any magic conversion properties. You can't even get an enum's label back from its integer. They lose all meaning when compiled, becoming pure numbers.

Quote:
I have in a header file an INF array of structures with two integers.
Never put data in your header files. (Or function definitions, for that matter.) All you need to say in the header is that the variable exists at all like extern int lookup_table[256]; Put its actual definition somewhere else.

Last edited by Corona688; 09-07-2012 at 05:13 PM..
This User Gave Thanks to Corona688 For This Post:
# 5  
Old 09-07-2012
Designated inits in gcc actually work with enums! This might give you something close to what you wanted...

Code:
#include <stdio.h>

enum { A, B, C };
enum { D=5, E, F };

const int lookup[256]={ [A] = D,
                        [B] = E,
                        [C] = F };

int main(void)
{
        printf("A[%d] -> D[%d]\n", A, lookup[A]);
        return(0);
}

For more details, http://gcc.gnu.org/onlinedocs/gcc-4....ted-Inits.html

Last edited by Corona688; 09-07-2012 at 05:21 PM..
This User Gave Thanks to Corona688 For This Post:
# 6  
Old 09-07-2012
Thanks ,Corona688 for extended responce!
I will think about your points and advices and replay later.

(I am complitely fine about 'enum' and understand what it is internaly. The only point that is skipped in your explanation is the existed labels during run time. It is not just #define that vaiporing on precompilation. )
# 7  
Old 09-07-2012
Quote:
Originally Posted by alex_5161
(It is not just #define that vaiporing on precompilation. )
Unfortunately I must disagree. For your purposes, they amount to #define's without the mess. They don't vanish in precompilation, but they do vanish in a later phase of compilation, values set and irreversible. Your program can't iterate through them, convert them to or from strings, or map one set of them to another unless you do it the hard way, building your own tables of values to look them up in. They're just labels for numbers.

In C++, enum's are a little more strict to prevent some of that weirdness. They didn't add anything that'd actually help you, though. They didn't add any syntax to iterate through them, convert them to or from strings, or map one set of them to another, just made it harder to set an enum to an invalid value. They prevented you from doing arithmetic on enums like myenum++ since that might possibly end up at an invalid enum. They prevented you from assigning an enum from an integer without a typecast in case that causes an invalid enum. And so forth. (No, it doesn't actually check if the enums are valid if you typecast. It just lets it through.) So C++ code at runtime is still as ignorant of their status as anything but numbers as C is.

Last edited by Corona688; 09-07-2012 at 06:40 PM..
This User Gave Thanks to Corona688 For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Solaris

How to determine if i have spare disks in Solaris?

Hi Guys, obviously new to SOLARIS SUN SPARC 5.10 I would really appreciate if you help me see how to find free disks available in my system. Like i am a linux admin. If i want to grow a file system in linux. I would first have a look at my volume groups to see if they have free PEs if not then... (2 Replies)
Discussion started by: aiqbal
2 Replies

2. Programming

Mixed enum types - coverity defect

Hi All, I came across this error "MIXING ENUM TYPES" when I run my C program against the Coverity Tool. I've made many search relating to the error, but I didnt find the exact solution. Can anyone help me to overcome this.? Thanks in Advance.!! (3 Replies)
Discussion started by: Parameswaran
3 Replies

3. Solaris

How to get spare disks working

Dears how can i make this spare disks working online to replace a defective disks vxdisk list DEVICE TYPE DISK GROUP STATUS c0t10d0s2 sliced - - error c0t11d0s2 sliced disk08 rootdg online c1t16d0s2 sliced ... (3 Replies)
Discussion started by: thecobra151
3 Replies

4. Programming

enum and C preprocessor

Say I have a list of enumerations I wish to use to select a variable at compile-time: enum pins { PIN_A=1, PIN_B=7, PIN_C=6, } int VAR1, VAR2, VAR3, VAR4, VAR5, VAR6, VAR7; #define PIN_TO_VAR(NUM) VAR ## NUM int main(void) { PIN_TO_VAR(PIN_A)=32;... (2 Replies)
Discussion started by: Corona688
2 Replies

5. Solaris

Hot Spare replacement

Hi Guys, Can Someone pls let me know the thorough process for Hot spare replacement as current Hot spare slice has broken down . :mad: Thanks ---------- Post updated at 06:34 PM ---------- Previous update was at 05:21 PM ---------- Update : Its a solaris 10 box (1 Reply)
Discussion started by: Solarister
1 Replies

6. Solaris

Hot Spare pool

One more query in SVM :) Now with hot spare spool... I can understand adding/replacing a slice in particular hot spare pool with "-a / -r" option (or) adding a slice to all existing hot spare pool with "-all" option. Here my query is for deleting, we have only option "-d". 1) If the hot... (2 Replies)
Discussion started by: gowthamakanthan
2 Replies

7. Programming

enum in c++

#include <iostream> #include <stdio.h> using namespace std; typedef struct A { enum a{ red,blue,green}a; }obj11; obj11 obj1; int main() { //obj1.a=red; // how to set variable ? cout<<"sizeof struct is n"<<sizeof(obj1); cout<<"obj1.a is"<<obj1.a; if... (1 Reply)
Discussion started by: crackthehit007
1 Replies

8. IP Networking

DNS ENUM RR interpretation

Hi Guys, This is really really urgent. Am looking out for some quick answers. I'm developing a DNS Resolver client that interprets DNS Query repsonses & pass on the needful to DNS applications. When an ENUM query(modified to an nslookup naptr query) is issued & an NAPTR RR(Resource Record)... (1 Reply)
Discussion started by: smanu
1 Replies

9. Programming

what is the base type of enum

helo i have asked in exam what that what is the base type of enum options are given bewlo (1) long int (2) short int (3) signed int (4) unsigned int can u tell me what is the exact answer from the above option Regards, Amit (1 Reply)
Discussion started by: amitpansuria
1 Replies

10. UNIX for Dummies Questions & Answers

Vfstab on spare disk - HOW ? Mount ?

Hi, guys ! Could someone clarify one thing for me: I start machine from disk0, and want to check the /etc/vfstab on disk1. How do i do it ? Tried to write: cd / mount /dev/dsk/c0t1d0s0 /mnt But if I do cd /mnt, it is empty. I expected to see disk1 there ? Or am I wrong ? How do I... (3 Replies)
Discussion started by: DGoubine
3 Replies
Login or Register to Ask a Question