Skip to content

Instantly share code, notes, and snippets.

@reagent
Last active December 15, 2015 07:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reagent/5221935 to your computer and use it in GitHub Desktop.
Save reagent/5221935 to your computer and use it in GitHub Desktop.
Dynamic array + union
main
*.o
*.dSYM
#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;
}
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