Vector is a C library that allows you to hold a dynamic number of elements in one container which isn't limited in how many elements you can store just like a conventional array.
Vector is inspired by std::vector from the C++'s STL library.
Installing libvector
is pretty easy. It counts with a CMake config file that sets up everything for you.
mkdir build
cmake -G Ninja -S . -B build
sudo cmake --build build --target install
Of course you can use another build tool instead of Ninja
if you want.
After installing libvector
, make sure you:
#include <vector.h>
Let's suppose you have all your code in a file main.c
and you're using GCC
as your compiler.
gcc main.c `pkg-config --cflags --libs vector`
Replace gcc with you compiler.
If you're using CMake in your project, you can also find libvector
with the find_package
CMake command, for example:
find_package(Vector REQUIRED)
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
target_link_libraries(${PROJECT_NAME} vector)
Notice the capital 'V' in the find_package
command, and the lower 'v' in the target_link_libraries
command!
Let's imagine you want to store an indefinite number of names. You'd do that like:
StringVector names = {0};
string_vector_add(&names, "John");
string_vector_add(&names, "Alie");
string_vector_add(&names, "Josh");
Here, because you haven't explicitly initialized the vector with string_vector_init()
, it's automatically initialized to hold, by default, 10 strings.
But that isn't limited to that, let's add 8 strings more. That would give us a total of 11 strings, but we just have memory for 10, right?
string_vector_add(&names, "James");
string_vector_add(&names, "Joseph");
string_vector_add(&names, "Ninia");
string_vector_add(&names, "Miguelina");
string_vector_add(&names, "Natty");
string_vector_add(&names, "Katie");
string_vector_add(&names, "Louis");
string_vector_add(&names, "David");
At first glance we could think that the program will crash because we're writing into memory we don't own, but that's not true with libvector
.
string_vector_add()
is smart enough to detect those scenarios, and will increase the vector size 10 spaces more. Why 10? Why not just 1 space?
At the end that's what we're needing, right? That's true, but the thing is that we would be resizing the vector every time we add one more string.
To avoid that, libvector
resizes the StringVector
to hold 10 strings more, so that operation won't need to be performed every single time.
Also, please notice the way the StringVector is declared: StringVector names = {0}
.
This is strictly necessary because if you don't declared it that way, bad things could and will happen!
You can use = {0}
or = {NULL}
, I prefer the former rather than the latter because of simplicity, but use whatever you're comfortable with.
A StringVector
isn't limited to add one string at a time. Let's imagine you already have an array of names. You can add that array to your StringVector
as well.
char *other_names[] = { "Josefa", "Nidia", "Mon", "Natalie", "Stephanye" };
string_vector_add_array(&names, other_names, 5);
In this scenario, libvector
won't increase the StringVector
10 more spaces if it determines the StringVector
needs to be bigger.
libvector
will increase the StringVector
to hold n more strings.
So, at the end of the day, names
' size will be 16. Initially 3, later it had to increase 10 more: 13, occupying just 11.
And adding 5 more strings through string_vector_add_array()
will make libvector
to increase names
' size to adjust itself to be able to hold those 5 more strings, resulting in 16 strings.
If you're in a situation where libvector
had to increase your StringVector
to hold 10 more strings, but your StringVector
is holding, for example, 3 strings, you can
use string_vector_shrink_to_fit()
to tell libvector
to make its size equal to the items it holds.
StringVector names = {0};
string_vector_add(&names, "John Doe");
string_vector_add(&names, "Alice");
string_vector_add(&names, "James");
string_vector_print(&names);
string_vector_shrink_to_fit(&names);
string_vector_print(&names);
Here we're using string_vector_print()
to print the StringVector
, it will print every string the StringVector
holds, but also it tells you how many items it holds, and how many items it can hold.
Then we're shrinking names
to adjust its size to the number of items it's currently holding, and finally printing it again for you to be sure the operation was performed successfully.
NumericVector
behaves almost the same as StringVector
. By default it works with double
s, so it'd be pretty easy to cast to other numeric types, e.g., int
.
The operations you can perform in a vector, be it StringVector
or NumericVector
starts with its name. You can see every operation we performed in StringVector
started with string_vector_*
.
That's exactly the same as for NumericVector
.
When you finish working with NumericVector
or StringVector
, you must call: numeric_vector_free(&numeric_vector)
or string_vector_free(&string_vector)
.
Vector type | Operation | Return type | Description |
---|---|---|---|
NumericVector | numeric_vector_init(&vector, initial_size | bool | Initalizes vector to hold initial_size items. |
NumericVector | numeric_vector_free(&vector) | void | Frees vector s allocated memory. MUST be called when you're done working with the vector. |
NumericVector | numeric_vector_add(&vector, number) | bool | Adds number to vector . Resizes vector to hold 10 more strings if needed. |
NumericVector | numeric_vector_add_array(&vector, numbers, n) | bool | Adds array of numbers numbers containing n strings to vector . Resizes vector to hold n items more if needed. |
NumericVector | numeric_vector_reserve(&vector, spaces) | bool | Reserves spaces more spaces for vector , in addition to the ones it currently holds. |
NumericVector | numeric_vector_shrink_to_fit(&vector) | bool | Shrinks vector to adjust its size the the items it currently holds. |
NumericVector | numeric_vector_clear(&vector) | bool | Clears vector leaving its capacity as untouched. |
NumericVector | numeric_vector_copy(&src, &dest, initialize? | bool | Copies src 's values into dest . With last argument you can control whether libvector will initialize dest or not. |
NumericVector | numeric_vector_insert(&vector, value, position) | bool | Inserts value into vector at position position . |
NumericVector | numeric_vector_replace(&vector, position, value) | bool | Replaces the value at position position with value . |
NumericVector | numeric_vector_erase(&vector, start, length) | bool | Erases length items starting from start . If length is greather than the vector's bounds and less than the vector capacity, just erase the last item. |
NumericVector | numeric_vector_get_capacity(&vector) | size_t | Returns vector 's capacity. |
NumericVector | numeric_vector_pop(&vector) | double | Takes out and returns the last item in vector . |
NumericVector | numeric_vector_get_first(&vector) | double | Returns first item held by vector. |
NumericVector | numeric_vector_get_at(&vector, item_position) | double | Returns item on position item_position held by vector. |
NumericVector | numeric_vector_get_last(&vector) | double | Returns last item held by vector. |
NumericVector | numeric_vector_print(&vector) | void | Prints all the strings held by vector . Also tells how many items are held, and how many items can be held without resizing. |
StringVector | string_vector_init(&vector, initial_size) | bool | Initalizes vector to hold initial_size items. |
StringVector | string_vector_free(&vector) | void | Frees vector s allocated memory. MUST be called when you're done working with the vector. |
StringVector | string_vector_add(&vector, string) | bool | Adds string to vector . Resizes vector to hold 10 more strings if needed. |
StringVector | string_vector_add_array(&vector, strings, n) | bool | Adds array of strings strings containing n strings to vector . Resizes vector to hold n items more if needed. |
StringVector | string_vector_reserve(&vector, spaces) | bool | Reserves spaces more spaces for vector , in addition to the ones it currently holds. |
StringVector | string_vector_shrink_to_fit(&vector) | bool | Shrinks vector to adjust its size the the items it currently holds. |
StringVector | string_vector_clear(&vector) | bool | Clears vector leaving its capacity as untouched. |
StringVector | string_vector_copy(&src, &dest, initialize? | bool | Copies src 's values into dest . With last argument you can control whether libvector will initialize dest or not. |
StringVector | string_vector_insert(&vector, value, position) | bool | Inserts value into vector at position position or leaves vector untouched in case of an error. |
StringVector | string_vector_replace(&vector, position, value) | bool | Replaces the value at position position with value . |
StringVector | string_vector_erase(&vector, start, length) | bool | Erases length items starting from start . If length is greather than the vector's bounds and less than the vector capacity, just erase the last item. |
StringVector | string_vector_get_capacity(&vector) | size_t | Returns vector 's capacity. |
StringVector | string_vector_pop(&vector) | char * | Takes out and returns the last head-allocated item in vector . Calling string_vector_free() won't free it, so you have to do it. |
StringVector | string_vector_strlen(&vector, item_position) | size_t | Returns vector item's length on position item_position . |
StringVector | string_vector_get_first(&vector) | const char * | Returns first item held by vector. |
StringVector | string_vector_get_at(&vector, item_position) | const char * | Returns item on position item_position held by vector. |
StringVector | string_vector_get_last(&vector) | const char * | Returns last item held by vector. |
StringVector | string_vector_print(&vector) | void | Prints all the strings held by vector . Also tells how many items are held, and how many items can be held without resizing. |