diff --git a/stringfun.c b/stringfun.c
new file mode 100644
index 0000000000000000000000000000000000000000..c52442353febac6f4aa2259bb28bc967da63149d
--- /dev/null
+++ b/stringfun.c
@@ -0,0 +1,424 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define BUFFER_SZ 50
+
+// prototypes
+void usage(char *);
+void print_buff(char *, int);
+int setup_buff(char *, char *, int);
+int count_words(char *, int, int);
+// add additional prototypes here
+int reverse_string(char *, int, int);
+int print_words(char *, int, int);
+int replace_string(char *, char *, int, char *, char *);
+int get_str_len(char *);
+
+// Helper function for string length
+int get_str_len(char *str)
+{
+    char *ptr = str;
+    while (*ptr)
+        ptr++;
+    return ptr - str;
+}
+
+int setup_buff(char *buff, char *user_str, int len)
+{
+    if (!buff || !user_str)
+        return -2;
+
+    char *src = user_str;
+    char *dst = buff;
+    int count = 0;
+    int space_seen = 1; // Start true to handle leading spaces
+
+    // Skip leading whitespace
+    while (*src == ' ' || *src == '\t')
+        src++;
+
+    // Copy and process the string
+    while (*src != '\0')
+    {
+        if (count >= len)
+            return -1;
+
+        if (*src == ' ' || *src == '\t')
+        {
+            if (!space_seen && *(src + 1) != '\0')
+            {
+                *dst++ = ' ';
+                count++;
+                space_seen = 1;
+            }
+        }
+        else
+        {
+            *dst++ = *src;
+            count++;
+            space_seen = 0;
+        }
+        src++;
+    }
+
+    // Remove trailing space if it exists
+    if (count > 0 && *(dst - 1) == ' ')
+    {
+        dst--;
+        count--;
+    }
+
+    // Pad with dots
+    while (count < len)
+    {
+        *dst++ = '.';
+        count++;
+    }
+
+    return count - (buff + len - dst);
+}
+
+void print_buff(char *buff, int len)
+{
+    printf("Buffer:  ");
+    for (int i = 0; i < len; i++)
+    {
+        putchar(*(buff + i));
+    }
+    putchar('\n');
+}
+
+void usage(char *exename)
+{
+    printf("usage: %s [-h|c|r|w|x] \"string\" [other args]\n", exename);
+}
+
+int count_words(char *buff, int len, int str_len)
+{
+    if (!buff || str_len <= 0 || str_len > len)
+        return -1;
+
+    char *ptr = buff;
+    int count = 0;
+    int in_word = 0;
+
+    while (ptr < buff + str_len)
+    {
+        if (*ptr != ' ' && !in_word)
+        {
+            count++;
+            in_word = 1;
+        }
+        else if (*ptr == ' ')
+        {
+            in_word = 0;
+        }
+        ptr++;
+    }
+
+    return count;
+}
+
+// ADD OTHER HELPER FUNCTIONS HERE FOR OTHER REQUIRED PROGRAM OPTIONS
+int reverse_string(char *buff, int len, int str_len)
+{
+    if (!buff || str_len <= 0 || str_len > len)
+        return -1;
+
+    char *start = buff;
+    char *end = buff + str_len - 1;
+    char temp;
+
+    while (start < end)
+    {
+        temp = *start;
+        *start = *end;
+        *end = temp;
+        start++;
+        end--;
+    }
+
+    return 0;
+}
+
+int print_words(char *buff, int len, int str_len)
+{
+    if (!buff || str_len <= 0 || str_len > len)
+        return -1;
+
+    char *start = buff;
+    char *current = buff;
+    int word_count = 0;
+    int word_len;
+
+    printf("Word Print\n----------\n");
+
+    while (current < buff + str_len)
+    {
+        while (current < buff + str_len && *current == ' ')
+        {
+            current++;
+        }
+        if (current >= buff + str_len)
+            break;
+
+        start = current;
+        word_len = 0;
+
+        while (current < buff + str_len && *current != ' ')
+        {
+            word_len++;
+            current++;
+        }
+
+        if (word_len > 0)
+        {
+            word_count++;
+            printf("%d. ", word_count);
+
+            char *temp = start;
+            while (temp < start + word_len)
+            {
+                putchar(*temp);
+                temp++;
+            }
+
+            printf(" (%d)\n", word_len);
+        }
+    }
+
+    printf("Number of words returned: %d\n", word_count);
+    return word_count;
+}
+
+int replace_string(char *buff, int len, int str_len, char *search, char *replace)
+{
+    if (!buff || !search || !replace || str_len <= 0 || str_len > len)
+        return -1;
+
+    char *current = buff;
+    char *end = buff + str_len;
+    int search_len = get_str_len(search);
+    int replace_len = get_str_len(replace);
+
+    // Find search string
+    int found = 0;
+    while (current < end - search_len + 1)
+    {
+        char *s1 = current;
+        char *s2 = search;
+        int match = 1;
+
+        for (int i = 0; i < search_len; i++)
+        {
+            if (*s1++ != *s2++)
+            {
+                match = 0;
+                break;
+            }
+        }
+
+        if (match)
+        {
+            found = 1;
+            break;
+        }
+        current++;
+    }
+
+    if (!found)
+        return -2;
+
+    // Calculate new length
+    int new_len = str_len - search_len + replace_len;
+    if (new_len > len)
+        return -3;
+
+    // Shift content if needed
+    if (replace_len != search_len)
+    {
+        char *src = current + search_len;
+        char *dst = current + replace_len;
+
+        if (replace_len > search_len)
+        {
+            char *src_end = end - 1;
+            char *dst_end = src_end + (replace_len - search_len);
+            while (src_end >= src)
+            {
+                *dst_end-- = *src_end--;
+            }
+        }
+        else
+        {
+            while (src < end)
+            {
+                *dst++ = *src++;
+            }
+        }
+    }
+
+    // Copy replacement
+    char *replace_ptr = replace;
+    while (*replace_ptr)
+    {
+        *current++ = *replace_ptr++;
+    }
+
+    // Update dots
+    char *dot_start = buff + new_len;
+    while (dot_start < buff + len)
+    {
+        *dot_start++ = '.';
+    }
+
+    return new_len;
+}
+
+int main(int argc, char *argv[])
+{
+    char *buff;         // placehoder for the internal buffer
+    char *input_string; // holds the string provided by the user on cmd line
+    char opt;           // used to capture user option from cmd line
+    int rc;             // used for return codes
+    int user_str_len;   // length of user supplied string
+
+    // TODO:  #1. WHY IS THIS SAFE, aka what if arv[1] does not exist?
+    //       PLACE A COMMENT BLOCK HERE EXPLAINING
+    /* This is safe because we check argc < 2 before accessing argv[1].
+     * If there aren't enough arguments, we exit before attempting to
+     * access argv[1], preventing any buffer overrun.
+     */
+    if ((argc < 2) || (*argv[1] != '-'))
+    {
+        usage(argv[0]);
+        exit(1);
+    }
+
+    opt = (char)*(argv[1] + 1); // get the option flag
+
+    // handle the help flag and then exit normally
+    if (opt == 'h')
+    {
+        usage(argv[0]);
+        exit(0);
+    }
+
+    // WE NOW WILL HANDLE THE REQUIRED OPERATIONS
+    // TODO:  #2 Document the purpose of the if statement below
+    //       PLACE A COMMENT BLOCK HERE EXPLAINING
+    /* This ensures we have enough arguments for all operations except help.
+     * Every operation needs at least program name, option, and input string,
+     * so we need at least 3 arguments.
+     */
+    if (argc < 3)
+    {
+        usage(argv[0]);
+        exit(1);
+    }
+
+    input_string = argv[2]; // capture the user input string
+
+    // TODO:  #3 Allocate space for the buffer using malloc and
+    //           handle error if malloc fails by exiting with a
+    //           return code of 99
+    buff = (char *)malloc(BUFFER_SZ);
+    if (!buff)
+    {
+        exit(99);
+    }
+
+    user_str_len = setup_buff(buff, input_string, BUFFER_SZ); // see todos
+    if (user_str_len < 0)
+    {
+        printf("Error setting up buffer, error = %d", user_str_len);
+        free(buff);
+        exit(2);
+    }
+
+    switch (opt)
+    {
+    case 'c':
+        rc = count_words(buff, BUFFER_SZ, user_str_len); // you need to implement
+        if (rc < 0)
+        {
+            printf("Error counting words, rc = %d", rc);
+            free(buff);
+            exit(2);
+        }
+        printf("Word Count: %d\n", rc);
+        break;
+
+    case 'r':
+        rc = reverse_string(buff, BUFFER_SZ, user_str_len);
+        if (rc < 0)
+        {
+            printf("Error reversing string\n");
+            free(buff);
+            exit(3);
+        }
+        break;
+
+    case 'w':
+        rc = print_words(buff, BUFFER_SZ, user_str_len);
+        if (rc < 0)
+        {
+            printf("Error printing words\n");
+            free(buff);
+            exit(3);
+        }
+        break;
+
+    case 'x':
+        if (argc != 5)
+        {
+            printf("Error: -x requires search and replace strings\n");
+            free(buff);
+            exit(1);
+        }
+        rc = replace_string(buff, BUFFER_SZ, user_str_len, argv[3], argv[4]);
+        if (rc < 0)
+        {
+            switch (rc)
+            {
+            case -1:
+                printf("Error: Invalid parameters\n");
+                break;
+            case -2:
+                printf("Error: Search string not found\n");
+                break;
+            case -3:
+                printf("Error: Replacement would exceed buffer size\n");
+                break;
+            }
+            free(buff);
+            exit(3);
+        }
+        break;
+
+    default:
+        usage(argv[0]);
+        free(buff);
+        exit(1);
+    }
+
+    // TODO:  #6 Dont forget to free your buffer before exiting
+    print_buff(buff, BUFFER_SZ);
+    free(buff);
+    exit(0);
+}
+
+// TODO:  #7  Notice all of the helper functions provided in the
+//           starter take both the buffer as well as the length.  Why
+//           do you think providing both the pointer and the length
+//           is a good practice, after all we know from main() that
+//           the buff variable will have exactly 50 bytes?
+//
+/* Passing both pointer and length is good practice because:
+ * 1. Prevents buffer overflows through bounds checking
+ * 2. Makes functions reusable with different buffer sizes
+ * 3. Follows principle of least privilege
+ * 4. Makes code more maintainable if buffer size changes
+ * 5. Helps catch programming errors through explicit length checks
+ */
\ No newline at end of file