From 8de727c4c44f4ad0f8acd6c14ba5aa96cc1864a0 Mon Sep 17 00:00:00 2001
From: Charles Barnwell <cxb23@drexel.edu>
Date: Fri, 7 Feb 2025 00:32:46 +0000
Subject: [PATCH] Upload New File

---
 1-C-Refresher/stringfun.c | 333 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 333 insertions(+)
 create mode 100644 1-C-Refresher/stringfun.c

diff --git a/1-C-Refresher/stringfun.c b/1-C-Refresher/stringfun.c
new file mode 100644
index 0000000..72763ba
--- /dev/null
+++ b/1-C-Refresher/stringfun.c
@@ -0,0 +1,333 @@
+#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  reverse_str(char*, int, int);
+int  find_word(char *, char*);
+int  replace_word(char*, char*, char*, int, int);
+int  print_words(char*, int, int);
+
+int setup_buff(char *buff, char *user_str, int len){
+    //TODO: #4:  Implement the setup buff as per the directions
+	if (len > BUFFER_SZ) return -1;
+
+	int str_len = 0;
+ 	char *temp = buff;
+
+	while (*user_str == ' ') buff++; // skip leading spaces
+
+	while (*user_str != '\0' && str_len < len - 1) {
+		if (*user_str == ' ' && (*(user_str + 1) == ' ' || *(user_str + 1) == '\0')) {
+			user_str++;
+			continue;
+		}
+			
+		*temp = *user_str;
+		temp++;
+		user_str++;
+		str_len++;
+	}
+	
+	*temp = '\0';
+
+	return str_len;
+
+}
+
+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 (len < str_len || buff == NULL) return -1;
+
+	int ctr = 0;
+	bool counting = false;
+    
+    while (*buff != '\0') {
+		if (*buff != ' ' && !counting) {
+			counting = true;
+			ctr++;
+		} else if (*buff == ' ' && counting) counting = false;
+		
+		buff++;
+    }
+    return ctr;
+}
+
+//ADD OTHER HELPER FUNCTIONS HERE FOR OTHER REQUIRED PROGRAM OPTIONS
+int reverse_str(char *buff, int buff_len, int str_len) {
+	if (buff_len == 0) {
+		printf("Empty String");
+		return -1;
+	}
+	
+	char *end = buff;
+	
+	while (*end != '\0') end++;
+	end--;
+	
+	char *rev_str = malloc(sizeof(char) * (str_len + 1));
+	if (rev_str == NULL) {
+        printf("Memory allocation error\n");
+        return -1;
+    }
+	
+	char *temp = rev_str;
+	while(end >= buff) {
+		*temp = *end;
+		temp++;
+		end--;
+	}
+
+	*temp = '\0';
+	
+	printf("Reversed String: %s\n", rev_str);
+	free(rev_str);
+	return 0;
+
+}
+
+int find_word(char *buff, char *word) {
+	const char *b = buff;
+    const char *w = word;
+
+    int index = 0; // to track the starting index of the word
+
+    while (*b != '\0') {
+        if (*b == *w) {
+            const char *b_temp = b;
+            const char *w_temp = w;
+
+            while (*w_temp != '\0' && *b_temp == *w_temp) {
+                b_temp++;
+                w_temp++;
+            }
+
+        	if (*w_temp == '\0') {
+                return index;
+            }
+        }
+
+        b++;
+        index++;
+    }
+
+    return -1; // word not found
+}
+
+int replace_word(char *buff, char *word, char *replacement, int buff_len, int str_len) {
+	if (str_len > buff_len || str_len == 0) return -2; // invalid input
+	
+	int index = find_word(buff, word);
+	if (index == -1) return -1; // word doesn't exist in string
+	
+	int word_len = 0;
+    while (word[word_len] != '\0') word_len++;
+
+    int replacement_len = 0;
+    while (replacement[replacement_len] != '\0') replacement_len++;
+
+    if (str_len - word_len + replacement_len > buff_len) return -3; // replcaement exceeds buffer size
+
+	if (replacement_len != word_len) {
+        char *end = buff + str_len;
+        char *src = buff + index + word_len;
+        char *dest = buff + index + replacement_len;
+
+        if (replacement_len > word_len) {
+            while (end >= src) {
+                *(dest--) = *(end--);
+            }
+        } else {
+            while (*src != '\0') {
+                *(dest++) = *(src++);
+            }
+            *dest = '\0';
+        }
+    }
+
+    char *replace_ptr = buff + index;
+    const char *replacement_ptr = replacement;
+
+    while (*replacement_ptr != '\0') *replace_ptr++ = *replacement_ptr++;
+
+	printf("Modified String: %s\n", buff);
+	return 0;
+
+}
+
+int print_words(char *buff, int buff_len, int str_len) {
+	if (str_len > buff_len) return -1;
+	if (str_len == 0) return 0;
+
+	int word_count = 0; // to start
+	int char_ctr = 0; // length of the current word
+	bool at_start = true; // if we are currently counting words
+
+	printf("Word Print\n----------\n");
+	
+	while (*buff != '\0') {
+		if (*buff != ' ' && at_start) {
+			word_count++;
+			at_start = false; // we are processing a new word
+			printf("%d. ", word_count);
+		}
+
+		if (*buff == ' ' && !at_start) { // we hit the end of the word
+			printf(" (%d)\n", char_ctr); // length of the current word
+			char_ctr = 0; //  start count for the next word
+			at_start = true; // we are starting a new word
+		} else { // we are just encountering a normal character
+			printf("%c", *buff); // current character
+			char_ctr++; // add to length of current string
+		}
+		buff++;
+	}
+	if (!at_start) printf(" (%d)\n", char_ctr); // this is for the last word
+	return word_count; // hold total number of words
+}
+
+
+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 argv[1] does not exist?
+    /* 
+    Since argv[0] is the name of the executable, argv[1] is the first parameter used as input. 
+    If argv[1] doesn't exist, then the program could run into problems. The code below prevents those.
+    */
+    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
+    /*
+	If the number of arguments is less than 3 (including the executable's name), 
+	print the usage of the program (the possible flags and input), then exit.
+    */
+    if (argc < 3){
+        usage(argv[0]);
+        exit(1);
+    }
+
+    input_string = argv[2]; //capture the user input string
+	
+	char *choice;
+	char *replacement;
+	if (opt == 'x') {
+		if (argc == 5) {
+			choice = argv[3];
+			replacement = argv[4];
+		} else {
+			printf("Error: invalid number of arguments");
+			exit(2);
+		}
+	}
+
+    //TODO:  #3 Allocate space for the buffer using malloc and
+    //          handle error if malloc fails by exiting with a 
+    //          return code of 99
+	buff = malloc(sizeof(char) * BUFFER_SZ);
+	if (buff == NULL) {
+		printf("Error setting up buffer");
+		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);
+        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':
+			rc = reverse_str(buff, BUFFER_SZ, user_str_len);
+        	if (rc < 0) {
+        		printf("Error reversing words, rc = %d", rc);
+        		exit(2);
+			}
+        	break;
+        case 'w':
+        	rc = print_words(buff, BUFFER_SZ, user_str_len);
+        	if (rc < 0) {
+                printf("Error printing words, rc = %d", rc);
+                exit(2);
+            }
+        	break;
+        case 'x':
+        	rc = replace_word(buff, choice, replacement, BUFFER_SZ, user_str_len);
+        	if (rc < 0) {
+                printf("Error replacing words, rc = %d", rc);
+                exit(2);
+            }
+            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?
+//  
+//          In a case where the global BUFFER_SZ variable is changed, 
+//          you don't want the behavior of each of the functions to
+//          to be affacted negatively. Providing both the pointer to
+//          the buffer and the length is good so that the length is
+//          never in question for any individual function.
+
-- 
GitLab