Skip to content
Snippets Groups Projects
Select Git revision
  • a60b4c57078e17d5ecabf1ac92faa92ca5aab1c3
  • main default
2 results

dshlib.h

Blame
  • stringfun.c 8.37 KiB
    #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);
    
    //prototypes for functions to handle required functionality
    int  count_words(char *, int);
    //add additional prototypes here
    
    int setup_buff(char **buff, char *user_str, int len){
        //First create a buffer and checks if the memory will be allocated properly 
        *buff = (char *)malloc(len);
        if (!buff) {
            return -2; 
        }
        //Variables to help move through the string and also count length 
        char *buff_ptr = *buff; 
        char *str_ptr = user_str;
    
        int white_space_checker = 0;
        int length_of_string = 0; 
    
        while (*str_ptr != '\0') {
            if (*str_ptr == ' ' || *str_ptr == '\t') {
                
                if ( white_space_checker == 0 ) {  //I know nested if's are bad but it's the onl way I could think of 
                    *buff_ptr++ = ' ';             // Using whitespace checker to determine to add it to the buffer or not 
                    length_of_string++;
                    white_space_checker = 1;
    
                }
            } else { 
                *buff_ptr++ = *str_ptr; 
                length_of_string++;
                white_space_checker = 0;
    
            }
            
            if (length_of_string >= BUFFER_SZ) {    //Checks if the length is past the buffer or not  
                free(*buff);
                return -1;
    
            }
    
            str_ptr++;           
                
        }
            int actual_length = length_of_string;
        while (length_of_string < BUFFER_SZ) {  //To fill up buffer with .
            *buff_ptr++ = '.';
            length_of_string++;
        }
        return actual_length;
    }
    
    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 str_len) {
    
        if (buff == NULL || str_len <= 0) { //Makes sure it valid 
            printf("Error: Invalid input.\n");
            return -1;
        }
        
        int words_in_string = 0; 
    	 int white_space = 1;
    
    
    	 for(int i = 0; i < str_len; i++) { //Uses length to only count words no including the buffer 
    	 	if (buff[i] != ' ') {           //Based on whitespace to count words
            if( white_space == 1 ) {
    		  		words_in_string++;
    				white_space = 0;
    		  	}
    		  } else {
    		  		white_space = 1;
    		}
    	}
    
        printf("Word Count %d\n", words_in_string);
        return words_in_string;
    }
    
    int reverse_words(char *buff, int str_len) {
        if (buff == NULL || str_len <= 0 ) { 
            printf("Error: Invalid input.\n") ;
            return -1 ;
        }
    	 
    	 char *reversed_buff = (char *)malloc((str_len + 1) * sizeof(char)); //+1 for null terminator 
    	 
        int start = 0 ;
        int end = str_len - 1; 
                                //I chose to copy it into a new list that is reversed, because I thought it would be a little more simplier 
    	 while (start <= end) { //It's like when a tire is spun and the words on it are reversed on the bottom. 
    	 	reversed_buff[start] = buff[end];
    		reversed_buff[end] = buff[start]; //Only copying the string and not the buffer '.'
    		start++;
    		end--;
    	 }
    
    	 reversed_buff[str_len] = '\0';
    
    	 printf("Reversed String:%s\n", reversed_buff);
    
    	 free(reversed_buff); //Even freed the reversed_buff. Memory leaks are a joke to me 
    
    	 return 0;
        }
    
    
    int write_string(char* buff, int len) {
        printf("Word Print\n----------\n");
    
        char word[len];
        int word_count = 0;
        int line_number = 1;
        int line_position = 0;
        //I use a loop to print out each line one at a time 
        for (int i = 0; i < len; i++) {
    	 		if(buff[i] == '.') {
    			break ;
    			}
            if (buff[i] != ' ' && buff[i] != '\0') {
                word[line_position] = buff[i];
                line_position++;
                word_count++;
    
            } else {
            if (word_count > 0) {
                word[line_position] = '\0'; //Resets the word 
                printf("%i. %s (%i)\n", line_number,word,word_count);
                line_number++;
                line_position = 0;
                word_count = 0 ;
            }
            //reset word counter
        
        }
    	 }
    //This one handles the last word in the string 
        if ( word_count > 0 ) {
            word[line_position] = '\0';
            printf("%i. %s (%i)\n", line_number, word, word_count);
        }
        
    	 return 0 ;
    }
    
    
    //ADD OTHER HELPER FUNCTIONS HERE FOR OTHER REQUIRED PROGRAM OPTIONS
    
    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
    
         // argv is a way to split a string up into seperate pieces 
         //The purpose of argv[0] is that it allows you to call a certain part of the command line using 
         //A bracket and number
         //This is a way to be able to pass on arguements into the function
         // and it's make the program a lot easier to work with for developers and users alike
    
        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
        //     The purpose of this is that it checks how many arguements are passed into it to make sure that 
        //      It has the arguements required to function properly. If it's less than 3 then it exits the program
        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 * sizeof(char));
        if (buff == NULL) {
            printf("Error: Memory buggin fwah  ");
        }
    
        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, user_str_len);  //you need to implement
                if (rc < 0){
                    printf("Error counting words, rc = %d", rc);
                    exit(2);
                }
                break;
    
            //TODO:  #5 Implement the other cases for 'r' and 'w' by extending
            //       the case statement options
            case 'r':
                rc = reverse_words(buff, user_str_len);
                if (rc < 0) {
                    printf("Error reversing words, rc = %dn\n",rc);
                    exit(3);
                }
    				break;
    
            case 'w':
                rc = write_string(buff, BUFFER_SZ);
                if (rc < 0) {
                	printf("Error writing string, rc = %d\n", rc);
                	exit(2);
    				}
    				break;
    
    		  case 'x':
                if (argc != 5) {
    				usage(argv[0]);
                exit(3);
                }
    
    				printf("Not implmented!\n");
    				exit(2);
    				break;
    
            default:
                usage(argv[0]);
                exit(1);
                break;
    
        }
    
        //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?
    //          
    //          I think it's good practice, because having both the pointer
    //          passing the buffer size everything is important, because
    //          then it makes the code more readable and also it can make it 
    //          so that it will be a bit easier to reused in the future 
    //          because you can put in different buffers and stuff and 
    //          you can prevent a lot of errors, because you can check the size 
    //          of the buffer whenever.
    //