Select Git revision
gameLogic.js
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.
//