Skip to content
Snippets Groups Projects
Select Git revision
  • master
1 result

makefile

Blame
  • stringfun.c 4.63 KiB
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.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);
    void reverse_string(char *, int);
    void word_print(char *, int, int);
    
    int setup_buff(char *buff, char *user_str, int len) {   //TODO: #4:  Implemented the setup buff as per the directions
        char *b_ptr = buff;
        char *u_ptr = user_str;
        int user_len = 0;
        bool last_was_space = false;
    
        while (*u_ptr != '\0') {
            if (user_len >= len) {
                return -1; // Error: Input string exceeds buffer size
            }
    
            if (*u_ptr == ' ' || *u_ptr == '\t') {
                if (!last_was_space) {
                    *b_ptr = ' ';
                    b_ptr++;
                    user_len++;
                    last_was_space = true;
                }
            } else {
                *b_ptr = *u_ptr;
                b_ptr++;
                user_len++;
                last_was_space = false;
            }
            u_ptr++;
        }
    
        while (user_len < len) {
            *b_ptr = '.';
            b_ptr++;
            user_len++;
        }
    
        return user_len;
    }
    
    int count_words(char *buff, int len, int str_len) {
        if (str_len > len) {
            return -1; // Error: String length exceeds buffer size
        }
    
        int word_count = 0;
        bool at_start = true;
    
        for (int i = 0; i < str_len; i++) {
            char c = *(buff + i);
    
            if (at_start && c != ' ') {
                word_count++;
                at_start = false;
            } else if (c == ' ') {
                at_start = true;
            }
        }
    
        return word_count;
    }
    
    void reverse_string(char *buff, int str_len) {
        for (int i = 0, j = str_len - 1; i < j; i++, j--) {
            char temp = *(buff + i);
            *(buff + i) = *(buff + j);
            *(buff + j) = temp;
        }
    }
    
    void word_print(char *buff, int len, int str_len) {
        printf("Word Print\n----------\n");
        int word_start = 0;
    
        for (int i = 0; i <= str_len; i++) {
            if (i == str_len || *(buff + i) == ' ') {
                printf("%.*s (%d)\n", i - word_start, buff + word_start, i - word_start);
                word_start = i + 1;
            }
        }
    }
    
    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 main(int argc, char *argv[]) {
        char *buff;
        char *input_string;
        char opt;
        int rc;
        int user_str_len;
    
        // TODO: #1 Explain why this is safe
        // This ensures that argv[1] exists and starts with '-'. If not, the program exits.
        if ((argc < 2) || (*argv[1] != '-')) {
            usage(argv[0]);
            exit(1);
        }
    
        opt = (char) *(argv[1] + 1); // Get the option flag
    
        if (opt == 'h') {
            usage(argv[0]);
            exit(0);
        }
    
        // TODO: #2 Explain the purpose of this check
        // This ensures the user provided a string as the second argument (argv[2]).
        if (argc < 3) {
            usage(argv[0]);
            exit(1);
        }
    
        input_string = argv[2]; // Capture user input string
    
        // TODO: #3 Allocate buffer and handle memory allocation failure
        buff = (char *) malloc(BUFFER_SZ);
        if (buff == NULL) {
            printf("Error: Memory allocation failed.\n");
            exit(99);
        }
    
        user_str_len = setup_buff(buff, input_string, BUFFER_SZ);
        if (user_str_len < 0) {
            printf("Error setting up buffer, error = %d\n", user_str_len);
            free(buff);
            exit(2);
        }
    
        switch (opt) {
            case 'c': // Word count
                rc = count_words(buff, BUFFER_SZ, user_str_len);
                if (rc < 0) {
                    printf("Error counting words, rc = %d\n", rc);
                    free(buff);
                    exit(2);
                }
                printf("Word Count: %d\n", rc);
                break;
                        //TODO:  #5 Implemented the other cases for 'r' and 'w' by extending
                        //the case statement options
            case 'r': // Reverse string
                reverse_string(buff, user_str_len);
                printf("Reversed String: %.*s\n", user_str_len, buff);
                break;
    
            case 'w': // Word print
                word_print(buff, BUFFER_SZ, user_str_len);
                break;
            
    
            default:
                usage(argv[0]);
                free(buff);
                exit(1);
        }
    
        // TODO: #6 Free the buffer before exiting
        free(buff);
        exit(0);
    }
    
    // TODO: #7 Answer
    // Providing both the pointer and length ensures safer processing, as functions
    // cannot assume strings are null-terminated or rely on external constraints.
    // This minimizes memory-related errors.