diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..b1d5ffd05b4a2a5df0a3d7e7f0ab95a9d60d40d1
Binary files /dev/null and b/.DS_Store differ
diff --git a/Hw2/Makefile b/Hw2/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..98655dade808fd2c6a73f8197139945b63ec66b6
--- /dev/null
+++ b/Hw2/Makefile
@@ -0,0 +1,20 @@
+# Compiler settings
+CC = gcc
+CFLAGS = -Wall -Wextra -g
+
+# Target executable name
+TARGET = stringfun
+
+# Default target
+all: $(TARGET)
+
+# Compile source to executable
+$(TARGET): stringfun.c
+ $(CC) $(CFLAGS) -o $(TARGET) $^
+
+# Clean up build files
+clean:
+ rm -f $(TARGET)
+
+# Phony targets
+.PHONY: all clean
\ No newline at end of file
diff --git a/Hw2/stringfun b/Hw2/stringfun
new file mode 100755
index 0000000000000000000000000000000000000000..8cb7308c3a354760af3f736e12c9caff340d3342
Binary files /dev/null and b/Hw2/stringfun differ
diff --git a/Hw2/stringfun.c b/Hw2/stringfun.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b962f14954e141daf70cd6d5ed24682c20b91ea
--- /dev/null
+++ b/Hw2/stringfun.c
@@ -0,0 +1,255 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+
+#define BUFFER_SZ 50
+
+//prototypes
+void usage(char *);
+void print_buff(char *, int);
+int setup_buff(char *, char *, int);
+
+//prototypes for functions to handle required functionality
+int count_words(char *, int, int);
+//add additional prototypes here
+
+
+int setup_buff(char *buff, char *user_str, int len){
+ //TODO: #4: Implement the setup buff as per the directions
+ bool isSpace = false;
+ int count = 0;
+
+ while (*user_str != '\0' && count < BUFFER_SZ - 1) { // stop when reaching the end-of-buffer
+ if (*user_str != '\t'){
+ if (*user_str != ' ' || isSpace == false) {
+ *buff = *user_str;
+ if (*user_str == ' '){
+ isSpace = true;
+ } else {
+ isSpace = false;
+ }
+ buff++;
+ user_str++;
+ count++;
+ } else {
+ user_str++;
+ isSpace = false;
+ }
+ } else {
+ user_str++;
+ }
+ }
+ int ret = count;
+ if (count > len){
+ return -1;
+ }
+ while (count <= len){
+ *buff = '.';
+ buff++;
+ count++;
+ }
+
+ return ret; //for now just so the code compiles.
+}
+
+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){
+ //YOU MUST IMPLEMENT
+ if (str_len > len){
+ return -1;
+ }
+
+ if (str_len==0){
+ return 0;
+ }
+ int words = 1;
+ for (int i=0; i<str_len; i++){
+ if (*buff == ' '){
+ words++;
+ }
+ buff++;
+ }
+ return words;
+}
+
+//ADD OTHER HELPER FUNCTIONS HERE FOR OTHER REQUIRED PROGRAM OPTIONS
+
+void reverse_string(char *buff, int len, int str_len){
+ int lim;
+ if (len < str_len){
+ lim = len;
+ } else {
+ lim = str_len;
+ }
+ char *newBuff = (char*)malloc(BUFFER_SZ);
+ for (int i=0; i<lim; i++){
+ *newBuff = *buff;
+ newBuff--;
+ buff++;
+ }
+
+ for (int i=0; i<lim; i++){
+ putchar(*(newBuff+i));
+ }
+
+ printf("\n");
+}
+
+void word_print(char *buff, int len, int str_len){
+ int lim;
+ if (len < str_len){
+ lim = len;
+ } else {
+ lim = str_len;
+ }
+
+ int count = 1;
+ int track = 0;
+ printf("Word Print\n");
+ printf("--------------\n");
+ printf("%d. ", count);
+ for (int i=0; i<lim; i++){
+ if (*buff != ' '){
+ putchar(*buff);
+ track++;
+ } else {
+ printf(" (%d)\n",track);
+ count++;
+ printf("%d. ", count);
+ track = 0;
+ }
+ buff++;
+ }
+ printf(" (%d)\n",track);
+}
+
+// void replace(char *buff, *new_buff)
+
+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
+
+ /*
+ If arv[1] does not exist, the condition argc < 2, so the program will safely exit and print the usage:
+ usage: ./stringfun [-h|c|r|w|x] "string" [other args]
+ */
+
+ 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 if statement make sure that users provide a string after the namefile and the operation (-h|c|r|w|x)
+ If not, it will print the usage
+ */
+ 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
+ // CODE GOES HERE FOR #3
+ buff= (char*)malloc(BUFFER_SZ);
+ 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);
+ 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);
+ exit(2);
+ }
+ printf("Word Count: %d\n", rc);
+ break;
+ // TODO: #5 Implement the other cases for 'r' and 'w' by extending
+ // the case statement options
+ case 'r':
+ reverse_string(buff, BUFFER_SZ, user_str_len);
+ break;
+
+ case 'w':
+ word_print(buff, BUFFER_SZ, user_str_len);
+ break;
+
+ case 'x':
+ if (argc < 5){
+ printf("Need 3 arguments: sample string and 2 other strings\n");
+ exit(1);
+ } else {
+ // buff= (char*)malloc(BUFFER_SZ);
+ // old_string = argv[3];
+ // old_str_len = setup_buff()
+ // new_string = argv[4];
+ // new_str_len = setup_buff(buff, new_string, BUFFER_SZ);
+ printf("Not Implemented\n");
+ break;
+ }
+
+ default:
+ usage(argv[0]);
+ 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?
+//
+// PLACE YOUR ANSWER HERE
+
+//
+
+// We need the pointer to access and modify the values in the address.
+// Providing the length is a good practice since we sometimes need to
+// use the length (of the buffer and the user string) to make sure that
+// there is no buffer overflow or similiar errors appear in our function.
\ No newline at end of file
diff --git a/Hw2/test.sh b/Hw2/test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f2b431b8bdf429bc90753656d0f73ef64cd3b2cc
--- /dev/null
+++ b/Hw2/test.sh
@@ -0,0 +1,100 @@
+#!/usr/bin/env bats
+
+@test "no args shows usage" {
+ run ./stringfun
+ [ "$status" -eq 1 ]
+ [ "${lines[0]}" = "usage: ./stringfun [-h|c|r|w|x] \"string\" [other args]" ]
+}
+
+@test "bad args shows usage" {
+ run ./stringfun -z "Bad arg usage"
+ [ "$status" -eq 1 ]
+ [ "${lines[0]}" = "usage: ./stringfun [-h|c|r|w|x] \"string\" [other args]" ]
+}
+
+@test "check -h" {
+ run ./stringfun -h
+ [ "$status" -eq 0 ]
+ [ "${lines[0]}" = "usage: ./stringfun [-h|c|r|w|x] \"string\" [other args]" ]
+}
+
+@test "wordcount" {
+ run ./stringfun -c "There should be eight words in this sentence"
+ [ "$status" -eq 0 ]
+ [ "$output" = "Word Count: 8
+Buffer: [There should be eight words in this sentence......]" ]
+}
+
+@test "remove extra spaces" {
+ run ./stringfun -c " The strange spaces should be removed from this "
+ [ "$status" -eq 0 ]
+ [ "$output" = "Word Count: 8
+Buffer: [The strange spaces should be removed from this....]" ]
+}
+
+@test "reverse" {
+ run ./stringfun -r "Reversed sentences look very weird"
+ [ "$status" -eq 0 ]
+ [ "$output" = "Buffer: [driew yrev kool secnetnes desreveR................]" ]
+}
+
+@test "print words" {
+ run ./stringfun -w "Lets get a lot of words to test"
+ [ "$status" -eq 0 ]
+ [ "$output" = "Word Print
+----------
+1. Lets(4)
+2. get(3)
+3. a(1)
+4. lot(3)
+5. of(2)
+6. words(5)
+7. to(2)
+8. test(4)
+
+Number of words returned: 8
+Buffer: [Lets get a lot of words to test...................]" ]
+}
+
+@test "check max length" {
+ run ./stringfun -r "This is the maximum length string that should work"
+ [ "$status" -eq 0 ]
+ [ "$output" = "Buffer: [krow dluohs taht gnirts htgnel mumixam eht si sihT]" ]
+}
+
+@test "check over max length" {
+ run ./stringfun -w "This is a string that does not work as it is too long"
+ [ "$status" -ne 0 ]
+}
+
+
+
+@test "basic string search replace" {
+ run ./stringfun -x "This is a bad test" bad great
+ [ "$output" = "Buffer: [This is a great test..............................]" ] ||
+ [ "$output" = "Not Implemented!" ]
+}
+
+@test "search replace not found" {
+ run ./stringfun -x "This is a a long string for testing" bad great
+ [ "$status" -ne 0 ] ||
+ [ "$output" = "Not Implemented!" ]
+}
+
+@test "basic overflow search replace" {
+ run ./stringfun -x "This is a super long string for testing my program" testing validating
+ [ "$output" = "Buffer: [This is a super long string for validating my prog]" ] ||
+ [ "$output" = "Not Implemented!" ]
+}
+
+@test "test overflow string replace" {
+ run ./stringfun -x "This is a super long string for testing my program" testing validating
+ [ "$output" = "Buffer: [This is a super long string for validating my prog]" ] ||
+ [ "$output" = "Not Implemented!" ]
+}
+
+@test "test shorter string replace" {
+ run ./stringfun -x "This is a super long string for testing my program" program app
+ [ "$output" = "Buffer: [This is a super long string for testing my app....]" ] ||
+ [ "$output" = "Not Implemented!" ]
+}