Wednesday, September 23, 2009

How to make c more comfortable part 1


This is first part about c language. I would like to provide useful tools which could make a coder's life much easier.

At first I would like to bring you round to use my Vector class-like library instead of regular c arrays as it provides much more flexibility and safety.



First of all you could suggest that this can be done a lot better. For example like they did it here  http://www.planetpdf.com/codecuts/pdfs/ooc.pdf but I thing that its complexity is not worth advantages it provides. Thus I will try to get as much of functionality and OOP approach virtues and still keep it simple.

I worked on a pretty large project in c which was developed through years by many programmers. Moreover those were at a different degrees of programming skill. The result was big messy buggy gob of code. When you wanted to change anything you had to analyze big piece of it and change it in a dozens of places and still pray that you had found all occurences. During my work on that project I work out some paths and I wanted to share with my suggestions to you.

I do not claim I know everything. I cannot guarantee that provided examples are free of bugs. Shall you find anything incorrect please let me know or drop a comment. I would appreciate it.

Data structures in c
During work usually we need to use arrays. They have many flows like:
* it is very easy to crash by writing to memory out of table space

* if you have pointer to array it is almost impossible to determine its length
* they are not dynamic, you have to predict needed size

Due to this fact they are often replaced by dynamic data structures as lists (etc.). They are quite fast and powerful. I would like to suggest different approach. Why not to provide arrays without arrays flows?
As a solution I would like to draw your attention to my library I called vector.

First of all it hides internal vector structure from a user so he is not able to mess up inside. He can only use provided methods and they are resistant to common mistakes. It is also dynamic, for example you defined it as an vector of 10 elements and you wanna assign element to 20 index. No problem vector automagically adjust his size to be able to contain it. You also always know its length. While it is protected from wild memory errors, for the data you are keeping in it the responsibility is yours.
What's more? It has few useful methods that allow you do things which you had to normally  give a few extra lines of code to do it in regular arrays.
And it is still pretty fast and with acceptable memory demands.

So to not to talk too much let's look at the examples.

Auxilary library which will be common to all projects. It contains some usefull and obvious datatypes.

Vector header and vector body.

And last but not least something to test it all.
main.c

Output ought to look like this:

Let's crate Vector from pointers to ints (1,2,3,4)
Vector length: 4
Retrieved from vector: 1, 2, 3, 4.
Vector length is now: 0
Now try to put pointer to int 5 on index: 6
There is 5 now on index = 6 and vector length is 7
and now to the same index let's put pointer to int = 6
There is 6 now on index = 6 and vector length is 7

We can push again those four ints as at start.
Vector length is 11
Lets iterate through vector.
Under idx: 0, there is: NULL
Under idx: 1, there is: NULL
Under idx: 2, there is: NULL
Under idx: 3, there is: NULL
Under idx: 4, there is: NULL
Under idx: 5, there is: NULL
Under idx: 6, there is: 6
Under idx: 7, there is: 1
Under idx: 8, there is: 2
Under idx: 9, there is: 3
Under idx: 10, there is: 4
Lets remove six node and print vector again
Under 6 index there was number 6 and we removed it.
Under idx: 0, there is: NULL
Under idx: 1, there is: NULL
Under idx: 2, there is: NULL
Under idx: 3, there is: NULL
Under idx: 4, there is: NULL
Under idx: 5, there is: NULL
Under idx: 6, there is: NULL
Under idx: 7, there is: 1
Under idx: 8, there is: 2
Under idx: 9, there is: 3
Under idx: 10, there is: 4

We do not want to have nulls in our vector and the size is too big in compare to
 containg data. Let's defrag vector.
Now length of our vector has changed to: 4
Under idx: 0, there is: 1
Under idx: 1, there is: 2
Under idx: 2, there is: 3
Under idx: 3, there is: 4

What about create another vector?
This time lets make it from regular c array.
Second vector has length: 4
Under idx: 0, there is: 5
Under idx: 1, there is: 4
Under idx: 2, there is: 3
Under idx: 3, there is: 2

Can we convert our vector back to c array?
In c array under idx: 0, there is: 5
In c array under idx: 1, there is: 4
In c array under idx: 2, there is: 3
In c array under idx: 3, there is: 2
At the end do not forget to destroy both vectors!

Let create two new vectors:
First V: idx: 0, there is: 1
First V: idx: 1, there is: 2
First V: idx: 2, there is: 3
Second V: idx: 0, there is: 4
Second V: idx: 1, there is: 5
Second V: idx: 2, there is: 6

Now try to insert second vector to the first one at position 1
Now first V: idx: 0, there is: 1
Now first V: idx: 1, there is: 4
Now first V: idx: 2, there is: 5
Now first V: idx: 3, there is: 6
Now first V: idx: 4, there is: 2
Now first V: idx: 5, there is: 3
The second vector remains unchanged
Ok, we can destroy both vectors.

And create them again:
First V: idx: 0, there is: 1
First V: idx: 1, there is: 2
First V: idx: 2, there is: 3
Second V: idx: 0, there is: 4
Second V: idx: 1, there is: 5
Second V: idx: 2, there is: 6

Are that vectors equal? no
Concatenate vectors
First V: idx: 0, there is: 1
First V: idx: 1, there is: 2
First V: idx: 2, there is: 3
First V: idx: 3, there is: 4
First V: idx: 4, there is: 5
First V: idx: 5, there is: 6
Second V: idx: 0, there is: 4
Second V: idx: 1, there is: 5
Second V: idx: 2, there is: 6

Lets check what index occupy value 5 in our vector.
Value 5 is on idx: 4
And how many 5 are there in vector?
There are/is 1 values 5

Get part of first vector from idx 3 to 5.
New V: idx: 0, there is: 4
New V: idx: 1, there is: 5
New V: idx: 2, there is: 6
First V: idx: 0, there is: 1
First V: idx: 1, there is: 2
First V: idx: 2, there is: 3
First V: idx: 3, there is: 4
First V: idx: 4, there is: 5
First V: idx: 5, there is: 6
Second V: idx: 0, there is: 4
Second V: idx: 1, there is: 5
Second V: idx: 2, there is: 6

Finaly compare new vector to secont vector, are they identical? yes

And remember: NEVER pass pointer to local variable to vector (because it will be
 undefined after function life cycle)

Process returned 0 (0x0)   execution time : 0.140 s
Press any key to continue.


Next time I will show how to make it even more class-like by invoking methods directly from object but there is also one flow involved.

Future plans:
Class-like String,
Class-like hash,
skip list,
thread like behaviour to achieve in muds

Hope you will find it useful and waiting for your opinions.


No comments:

Post a Comment