Initial Commit. Strings seem to work!

This commit is contained in:
Aaron Helton
2019-10-09 21:02:15 -04:00
commit 16c4eaceae
5 changed files with 239 additions and 0 deletions

8
CMakeLists.txt Normal file
View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.14)
project(NameSort C)
set(CMAKE_C_STANDARD 11)
add_executable(NameSort src/main.c src/name_string.c include/name_string.h)
target_include_directories(NameSort PRIVATE ${CMAKE_SOURCE_DIR}/include)

33
include/name_string.h Normal file
View File

@@ -0,0 +1,33 @@
// Created by Aaron on 10/6/2019.
#ifndef TEST_NAME_STRING_H
#define TEST_NAME_STRING_H
#include <stdint.h>
#define MAX_STR_SIZE 255
typedef uint8_t strlen_t;
/*
* C Doesn't define any standard string structure, so we'll make a simple one of
* our own. This string struct currently only support ascii character strings,
* so names using international characters currently won't work correctly.
*
* Name strings are arbitrarily capped at a length of 255, as that should fit
* almost all reasonable names. The 256th value is reserved for the null byte.
* In the off chance that this struct is ever initiated with a string larger
* than 255 characters, the string shall be truncated to make room for the null
* byte.
*/
typedef struct NAME_STR {
char *c_str;
strlen_t len;
} string;
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);
#endif

51
sandbox/Sort Me.txt Normal file
View File

@@ -0,0 +1,51 @@
Adkins
Asby
Baker
Bostwick
Broome
Byfield
Clevenger
Fitzjerrell
Graff
Lundy
Tanton
Hagberg
Hendrickson
Hickey
Nylon
Reyes
Reynolds
Starkey
Kalivoda
Rogers
Glock
Routson
Kha
Dulaney
Guenther
Hatfield
Stegman
Sullivan
Taylor
Padgett
Heigl
Peery
Wile
Hillman
Foley
McVey
Phillips
Williams
Bain
Cachedon
Kirkland
Evans
Ellis
McCrave
Dean
Michael
Giddings
Laymon
Fife
White

23
src/main.c Normal file
View File

@@ -0,0 +1,23 @@
#include <stdio.h>
#include <name_string.h>
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);
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);
return 0;
}

124
src/name_string.c Normal file
View File

@@ -0,0 +1,124 @@
//
// Created by Aargo on 10/6/2019.
//
#include <name_string.h>
#include <stdlib.h>
string *create_from_cstr(const char *str)
{
string *new_str = (string *)malloc(sizeof(string));
if(!str)
{
//The passed c string is a null or invalid pointer.
new_str->c_str = NULL;
new_str->len = 0;
return new_str;
}
strlen_t index; //Declare outside of loop for reuse
strlen_t size = 0;
for(index = 0; index < MAX_STR_SIZE && str[index] != '\0'; index++)
{
size++;
}
//Make sure to +1 for the null byte at the end
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];
}
new_str->c_str[index] = '\0';
new_str->len = index; //Note that len does not include the null byte
return new_str;
}
void destroy_string(string *str)
{
if(str)
{
if(str->c_str)
{
free(str->c_str);
}
str->c_str = 0;
}
free(str);
}
string *concatenate_string(string *str, 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);
new_str->len = total_len;
for(strlen_t index = 0; index < str->len; index++)
{
new_str->c_str[index] = str->c_str[index];
}
for(strlen_t index = 0; index < other->len; 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)
{
if(str->len < other->len)
{
return -1;
}
else if(str->len > other->len)
{
return 1;
}
else
{
return 0;
}
}
/*
* This function takes advantage of the fact that in ASCII, a-z and A-Z are
* always 32 values apart. This will NOT work for other character sets, but few
* systems use anything other than ASCII and Unicode. This happens to work with
* Unicode characters as well, but that is merely a happy accident of the spec.
*
* If compiling on a EBCDIC system or anything else that uses a different
* default character encoding, you'll need to either chance this code or
* re-encode all text.
*/
static char lowercase(char c)
{
if(c < 'A' || c > 'Z')
{
return c;
}
return (char)(c-32);
}
int compare_on_alphabet(string *str, string *other)
{
strlen_t min_len = min(str->len, other->len);
for(strlen_t index = 0; index < min_len; index++)
{
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);
}