Added vector code and a strip function for strings.
This commit is contained in:
@@ -26,8 +26,11 @@ typedef struct NAME_STR {
|
||||
|
||||
string *create_from_cstr(const char *str);
|
||||
void destroy_string(string *str);
|
||||
string *concatenate_string(string *str, string *other);
|
||||
|
||||
int compare_on_length(string *str, string *other);
|
||||
string *concatenate_string(const string *str, const string *other);
|
||||
void strip(string *str);
|
||||
|
||||
int compare_on_length(const string *str, const string *other);
|
||||
int compare_on_alphabet(const string *str, const string *other);
|
||||
|
||||
#endif
|
||||
|
||||
122
src/main.c
122
src/main.c
@@ -1,23 +1,117 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <name_string.h>
|
||||
|
||||
#define MIN_VEC_SIZE 8
|
||||
//stdint guarantees the least types, unlike the standard uint32_t;
|
||||
typedef uint_least32_t uint32;
|
||||
|
||||
//Simple vector implementation for our strings
|
||||
typedef struct str_vector
|
||||
{
|
||||
string **array;
|
||||
uint32 size;
|
||||
uint32 _capacity;
|
||||
} string_vector;
|
||||
|
||||
string_vector *create_vector(uint32 capacity)
|
||||
{
|
||||
if(capacity < MIN_VEC_SIZE)
|
||||
{
|
||||
capacity = MIN_VEC_SIZE;
|
||||
}
|
||||
string_vector *vec = malloc(sizeof(string_vector));
|
||||
vec->array = malloc(sizeof(string *) * capacity);
|
||||
vec->size = 0;
|
||||
vec->_capacity = capacity;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/*
|
||||
* For our particular program, we don't need the ability to remove items from
|
||||
* the vector, as we'll only ever be adding to it.
|
||||
*/
|
||||
void vector_add(string_vector *vector, string *str)
|
||||
{
|
||||
if(vector->size == vector->_capacity)
|
||||
{
|
||||
string **new_array = malloc(sizeof(string *) * vector->_capacity * 2);
|
||||
for(uint32 index = 0; index < vector->_capacity; index++)
|
||||
{
|
||||
new_array[index] = vector->array[index];
|
||||
}
|
||||
free(vector->array);
|
||||
vector->array = new_array;
|
||||
vector->_capacity *= 2;
|
||||
}
|
||||
vector->array[vector->size] = str;
|
||||
vector->size++;
|
||||
}
|
||||
|
||||
void print_vector(string_vector *vector)
|
||||
{
|
||||
for(uint32 index = 0; index < vector->size; index++)
|
||||
{
|
||||
printf("%s", vector->array[index]->c_str);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare function to be used by qsort. Due to the implementation in the C
|
||||
* Standard Library, this function necessarily accepts void * and must cast to
|
||||
* the type it expects.
|
||||
*/
|
||||
int compare(const void *str1, const void *str2)
|
||||
{
|
||||
const string *first = *(const string **) str1;
|
||||
const string *second = *(const string **) str2;
|
||||
|
||||
int res = compare_on_length(first, second);
|
||||
if(res == 0)
|
||||
{
|
||||
return compare_on_alphabet(first, second);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sorts the passed vector with the rules that:
|
||||
* 1. Strings are sorted by length first, not alphabet.
|
||||
* 2. Strings are sorted by alphabet only if they are the same length.
|
||||
*/
|
||||
void perform_length_alphabet_sort(string_vector *vector)
|
||||
{
|
||||
qsort((void *) vector->array, vector->size, sizeof(string *), compare);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
string *test = create_from_cstr("Testing");
|
||||
printf("String: %s\n", test->c_str);
|
||||
printf("Size expected: %d\n", 7);
|
||||
printf("Actual Size: %d\n", test->len);
|
||||
char *tests[10] = {
|
||||
"What ",
|
||||
"Where",
|
||||
" When",
|
||||
" Why ",
|
||||
"How",
|
||||
"Test1",
|
||||
"Test2",
|
||||
"Anne",
|
||||
"Jill",
|
||||
"Bob"
|
||||
};
|
||||
|
||||
string *other = create_from_cstr("This is also a test");
|
||||
string *combined = concatenate_string(test, other);
|
||||
printf("First String: %s\n", test->c_str);
|
||||
printf("Second String: %s\n", other->c_str);
|
||||
printf("Expected: TestingThis is also a test\n");
|
||||
printf("Actual: %s\n", combined->c_str);
|
||||
printf("Length of first string: %d\n", test->len);
|
||||
printf("Length of second string: %d\n", other->len);
|
||||
printf("Expected Length: %d\n", test->len + other->len);
|
||||
printf("Length of Combined String: %d\n", combined->len);
|
||||
string_vector *vector = create_vector(0);
|
||||
|
||||
for(uint32 index = 0; index < 10; index++)
|
||||
{
|
||||
string *str = create_from_cstr(tests[index]);
|
||||
strip(str);
|
||||
vector_add(vector, str);
|
||||
}
|
||||
|
||||
print_vector(vector);
|
||||
perform_length_alphabet_sort(vector);
|
||||
printf("\nSorted Array\n------------\n");
|
||||
print_vector(vector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
string *create_from_cstr(const char *str)
|
||||
{
|
||||
string *new_str = (string *)malloc(sizeof(string));
|
||||
string *new_str = (string *) malloc(sizeof(string));
|
||||
if(!str)
|
||||
{
|
||||
//The passed c string is a null or invalid pointer.
|
||||
@@ -24,7 +24,7 @@ string *create_from_cstr(const char *str)
|
||||
}
|
||||
|
||||
//Make sure to +1 for the null byte at the end
|
||||
new_str->c_str = (char *)malloc(sizeof(char)*size + 1);
|
||||
new_str->c_str = (char *) malloc(sizeof(char) * size + 1);
|
||||
for(index = 0; index < size && *str != '\0'; index++)
|
||||
{
|
||||
new_str->c_str[index] = str[index];
|
||||
@@ -47,17 +47,21 @@ void destroy_string(string *str)
|
||||
free(str);
|
||||
}
|
||||
|
||||
string *concatenate_string(string *str, string *other)
|
||||
string *concatenate_string(const string *str, const string *other)
|
||||
{
|
||||
if(!str || !other)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(str->len + other->len > MAX_STR_SIZE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strlen_t total_len = str->len + other->len;
|
||||
|
||||
string *new_str = (string *)malloc(sizeof(string));
|
||||
new_str->c_str = (char *)malloc(sizeof(char)*total_len + 1);
|
||||
string *new_str = (string *) malloc(sizeof(string));
|
||||
new_str->c_str = (char *) malloc(sizeof(char) * total_len + 1);
|
||||
new_str->len = total_len;
|
||||
|
||||
for(strlen_t index = 0; index < str->len; index++)
|
||||
@@ -66,13 +70,78 @@ string *concatenate_string(string *str, string *other)
|
||||
}
|
||||
for(strlen_t index = 0; index < other->len; index++)
|
||||
{
|
||||
new_str->c_str[index+str->len] = other->c_str[index];
|
||||
new_str->c_str[index + str->len] = other->c_str[index];
|
||||
}
|
||||
new_str->c_str[total_len] = '\0';
|
||||
return new_str;
|
||||
}
|
||||
|
||||
int compare_on_length(string *str, string *other)
|
||||
static int is_whitespace(char c)
|
||||
{
|
||||
if(c == ' ' || c == '\t' || c == '\n' || c == '\v')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strip(string *str)
|
||||
{
|
||||
//Sanity check
|
||||
if(!str || !str->c_str || str->len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Strip the left side
|
||||
strlen_t lstrip_index = 0;
|
||||
for(strlen_t index = 0; index < str->len; index++)
|
||||
{
|
||||
if(is_whitespace(str->c_str[index]))
|
||||
{
|
||||
lstrip_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Find right side strip index
|
||||
strlen_t rstrip_index = str->len;
|
||||
for(strlen_t index = str->len - 1; index >= 0; index--)
|
||||
{
|
||||
if(is_whitespace(str->c_str[index]))
|
||||
{
|
||||
rstrip_index--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(lstrip_index == rstrip_index)
|
||||
{
|
||||
free(str->c_str);
|
||||
str->c_str = NULL;
|
||||
str->len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strlen_t chop_off = lstrip_index + (str->len - rstrip_index);
|
||||
char *new = malloc(sizeof(char) * (str->len - chop_off + 1));
|
||||
for(strlen_t index = lstrip_index; index < rstrip_index; index++)
|
||||
{
|
||||
new[index - lstrip_index] = str->c_str[index];
|
||||
}
|
||||
new[rstrip_index - lstrip_index] = '\0';
|
||||
free(str->c_str);
|
||||
str->c_str = new;
|
||||
str->len -= chop_off;
|
||||
}
|
||||
}
|
||||
|
||||
int compare_on_length(const string *str, const string *other)
|
||||
{
|
||||
if(str->len < other->len)
|
||||
{
|
||||
@@ -104,10 +173,10 @@ static char lowercase(char c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return (char)(c-32);
|
||||
return (char) (c - 32);
|
||||
}
|
||||
|
||||
int compare_on_alphabet(string *str, string *other)
|
||||
int compare_on_alphabet(const string *str, const string *other)
|
||||
{
|
||||
strlen_t min_len = min(str->len, other->len);
|
||||
for(strlen_t index = 0; index < min_len; index++)
|
||||
@@ -115,9 +184,13 @@ int compare_on_alphabet(string *str, string *other)
|
||||
char str_lower_char = lowercase(str->c_str[index]);
|
||||
char other_lower_char = lowercase(other->c_str[index]);
|
||||
if(str_lower_char < other_lower_char)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if(str_lower_char > other_lower_char)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
//Only difference is length
|
||||
return compare_on_length(str, other);
|
||||
|
||||
Reference in New Issue
Block a user