Last active
December 15, 2015 07:18
-
-
Save reagent/5221935 to your computer and use it in GitHub Desktop.
Dynamic array + union
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
main | |
*.o | |
*.dSYM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdarg.h> | |
#include <string.h> | |
#define ARRAY_ALLOC_SEGMENT_SIZE 32 | |
#define STRING_MAX_SIZE 128 | |
typedef enum { | |
TYPE_INT, | |
TYPE_STRING | |
} ArrayType; | |
typedef struct Element { | |
union { | |
int as_integer; | |
char *as_string; | |
} value; | |
} Element; | |
typedef struct Array { | |
ArrayType type; | |
Element **elements; | |
int size; | |
int alloc_size; | |
} Array; | |
void array_expand(Array *array); | |
int compare(Array *array, int i1, int i2); | |
Array * | |
array_create(ArrayType type) | |
{ | |
Array *array = calloc(1, sizeof(Array)); | |
array->type = type; | |
array->size = 0; | |
array->alloc_size = ARRAY_ALLOC_SEGMENT_SIZE; | |
array->elements = calloc(array->alloc_size, sizeof(Element *)); | |
return array; | |
} | |
void | |
array_push(Array *array, ...) | |
{ | |
va_list ap; | |
Element *element; | |
int last_index = array->size; | |
if (array->size == array->alloc_size) { | |
array_expand(array); | |
} | |
array->elements[last_index] = calloc(1, sizeof(Element)); | |
element = array->elements[last_index]; | |
va_start(ap, array); | |
switch (array->type) { | |
case TYPE_INT: | |
element->value.as_integer = va_arg(ap, int); | |
break; | |
case TYPE_STRING: | |
element->value.as_string = calloc(STRING_MAX_SIZE + 1, sizeof(char)); | |
strncpy(element->value.as_string, va_arg(ap, char*), STRING_MAX_SIZE); | |
break; | |
} | |
va_end(ap); | |
array->size++; | |
} | |
Element * | |
array_pop(Array *array) | |
{ | |
Element *element = NULL; | |
if (array && array->size > 0) { | |
element = array->elements[(array->size - 1)]; | |
array->size--; | |
} | |
return element; | |
} | |
void | |
array_sort(Array *array) | |
{ | |
int swapped, cur, next; | |
Element *tmp; | |
do { | |
swapped = 0; | |
for (next = 1; next < array->size; next++) { | |
cur = next - 1; | |
if (compare(array, cur, next) == 1) { | |
tmp = array->elements[next]; | |
array->elements[next] = array->elements[cur]; | |
array->elements[cur] = tmp; | |
swapped = 1; | |
} | |
} | |
} while (swapped); | |
} | |
void | |
array_print(Array *array) | |
{ | |
int i; | |
Element *element; | |
if (array->size == 1) { | |
printf("Array contains %d element:\n", array->size); | |
} else { | |
printf("Array contains %d elements:\n", array->size); | |
} | |
printf(" ["); | |
for (i = 0; i < array->size; i++) { | |
element = array->elements[i]; | |
if (i > 0) { printf(", "); } | |
switch (array->type) { | |
case TYPE_INT: | |
printf("%d", element->value.as_integer); | |
break; | |
case TYPE_STRING: | |
printf("'%s'", element->value.as_string); | |
break; | |
} | |
} | |
printf("]\n"); | |
} | |
void | |
element_free(Element *element, int type) | |
{ | |
if (type == TYPE_STRING) { | |
free(element->value.as_string); | |
} | |
free(element); | |
} | |
void | |
array_free(Array *array) | |
{ | |
int i; | |
for (i = 0; i < array->size; i++) { | |
element_free(array->elements[i], array->type); | |
} | |
free(array->elements); | |
free(array); | |
} | |
int | |
main() | |
{ | |
int i; | |
Element *e; | |
// Integer array | |
Array *ints = array_create(TYPE_INT); | |
for (i = 10; i > 0; i--) { | |
array_push(ints, i); | |
} | |
array_print(ints); | |
array_sort(ints); | |
array_print(ints); | |
for (i = 0; i < 10; i++) { | |
e = array_pop(ints); | |
printf("Popped value was: %d\n", e->value.as_integer); | |
array_print(ints); | |
element_free(e, TYPE_INT); | |
} | |
// String array | |
Array *strings = array_create(TYPE_STRING); | |
array_push(strings, "10. Ten"); | |
array_push(strings, "09. Nine"); | |
array_push(strings, "08. Eight"); | |
array_push(strings, "07. Seven"); | |
array_push(strings, "06. Six"); | |
array_push(strings, "05. Five"); | |
array_push(strings, "04. Four"); | |
array_push(strings, "03. Three"); | |
array_push(strings, "02. Two"); | |
array_push(strings, "01. One"); | |
array_print(strings); | |
array_sort(strings); | |
array_print(strings); | |
for (i = 0; i < 10; i++) { | |
e = array_pop(strings); | |
printf("Popped value was: '%s'\n", e->value.as_string); | |
array_print(strings); | |
element_free(e, TYPE_STRING); | |
} | |
// Clean-up | |
array_free(ints); | |
array_free(strings); | |
return 0; | |
} | |
void | |
array_expand(Array *array) | |
{ | |
int new_size = array->alloc_size + ARRAY_ALLOC_SEGMENT_SIZE; | |
array->elements = realloc(array->elements, new_size * sizeof(Element *)); | |
array->alloc_size = new_size; | |
} | |
int | |
compare_strings(char *s1, char *s2) | |
{ | |
int result = 0, | |
cmp = strcmp(s1, s2); | |
if (cmp > 0) { | |
result = 1; | |
} else if (cmp < 0) { | |
result = -1; | |
} | |
return result; | |
} | |
int | |
compare_integers(int i1, int i2) | |
{ | |
int result = 0; | |
if (i1 > i2) { | |
result = 1; | |
} else if (i1 < i2) { | |
result = -1; | |
} | |
return result; | |
} | |
int | |
compare(Array *array, int i1, int i2) | |
{ | |
int result = 0; | |
Element *e1 = array->elements[i1], | |
*e2 = array->elements[i2]; | |
switch (array->type) { | |
case TYPE_INT: | |
result = compare_integers(e1->value.as_integer, e2->value.as_integer); | |
break; | |
case TYPE_STRING: | |
result = compare_strings(e1->value.as_string, e2->value.as_string); | |
break; | |
} | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CFLAGS=-g -Wall -Wextra | |
all: main | |
clean: | |
rm -rf *.o main *.dSYM |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment