Skip to content
Snippets Groups Projects
Commit f7e566e0 authored by Wendy Nguyen's avatar Wendy Nguyen
Browse files

assignment 1

parent 3c219138
Branches
No related tags found
No related merge requests found
#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, int);
//add additional prototypes here
int wordPrint(char *buff, char user_str_len);
void reverse(char *buff, int user_str_len);
int wordFound(char *str, char *word);
int replace(char *src, char *word, char *replacement, char *dest, int buff_len);
int setup_buff(char *buff, char *user_str, int len){
//TODO: #4: Implement the setup buff as per the directions
/*
- Make all white spaces single space
- Count the length
- Return -1 if length > BUFFER_SZ
- Else: fill dots in and return length
*/
int space = 0;
int user_str_len = 0;
while (*user_str != '\0' && user_str_len <= len) {
if (*user_str != ' ') {
*buff = *user_str;
buff++;
space = 0;
user_str_len++;
} else {
if (space == 0) {
*buff = *user_str;
buff++;
user_str_len++;
space += 1;
}
}
user_str++;
}
if (*user_str != '\0' && user_str_len > len) {
return -1;
}
int buff_curr_len = user_str_len;
while (buff_curr_len < len) {
*buff = '.';
buff++;
buff_curr_len++;
}
buff = buff - buff_curr_len;
return user_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 (str_len == 0) {
return 0;
}
int wc = 0;
for (int i = 0; i < str_len; i++) {
if (*buff == ' ') {
wc += 1;
}
buff++;
}
wc += 1;
return wc;
}
//ADD OTHER HELPER FUNCTIONS HERE FOR OTHER REQUIRED PROGRAM OPTIONS
int wordPrint(char *buff, char user_str_len) {
int charCount = 0;
int wordCount = 1;
printf("Word Print \n----------\n");
printf("%d. ", wordCount);
while (*buff != '.') {
if (*buff != ' ') {
printf("%c", *buff);
charCount++;
} else {
printf(" (%d)\n", charCount);
charCount = 0;
wordCount++;
printf("%d. ", wordCount);
}
buff++;
}
printf(" (%d)\n", charCount);
printf("Number of words returned: %d\n", wordCount);
buff = buff - user_str_len;
}
void reverse(char *buff, int user_str_len) {
char temp;
char *end = buff + user_str_len - 1;
while (end > buff) {
temp = *buff;
*buff = *end;
*end = temp;
end--;
buff++;
}
}
int wordFound(char *str, char *word) {
int wordLength = 0;
while (*word != '\0') {
if (*str != *word) {
return 0; // first word in string is not the wanted word
}
wordLength++;
str++;
word++;
}
word = word - wordLength;
if (*str != ' ' && *str != '\0' && *str != '.') {
return 0;
}
str = str - wordLength;
return wordLength;
}
int replace(char *src, char *word, char *replacement, char *dest, int buff_len) {
int match;
int newWord = 1;
char * original_dst = dest;
int destLength = 0;
int replmLength = 0;
int wordNotFound = 1;
while (*replacement != '\0') {
replmLength++;
replacement++;
}
replacement = replacement - replmLength;
while (*src != '.') {
if (newWord) {
match = wordFound(src, word);
// if word to replace is found, copy replacement to dest instead
if (match > 0) {
wordNotFound = 0;
while (*replacement != '\0') {
destLength++;
if (destLength > buff_len) {
return -1;
}
*dest = *replacement;
dest++;
replacement++;
}
src = src + match;
replacement = replacement - replmLength;
}
}
if (*src == '.') {
break;
}
destLength++;
if (destLength > buff_len) {
return -1;
}
*dest = *src;
if (*src == ' ') {
newWord = 1;
} else {
newWord = 0;
}
dest++;
src++;
}
if (wordNotFound) {
return 1;
}
dest = dest - destLength;
// printf("Replaced string: %s\n", dest);
return destLength;
}
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?
// This is to validate if the command has a correct syntax and all minimum required arguments
// so that the following operations can run with valid inputs or the type of error can be
// specified to help the user fix it and find the correct command that is going to work
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 if statement below is to make sure the user
// uses a command with at least 1 flag and 2 required
// arguments to proceed. Otherwise, an error will
// occur and the syntax will be provided to help them
// enter the correct command
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 = malloc(sizeof(char)*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\n", 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 'w':
wordPrint(buff, user_str_len);
break;
case 'r':
reverse(buff, user_str_len);
break;
case 'x':
if (argc < 5) {
printf("Not Implemented!\n");
exit(1);
}
char *word = argv[3]; // word to replace
char *replacement = argv[4];
char *dest = malloc(sizeof(char) * 50);
int destLenght = replace(buff, word, replacement, dest, BUFFER_SZ);
if (destLenght == -1) {
printf("Not implemented! Replacement is causing buffer overflow.\n");
exit(2); // overflow error
}
if (destLenght == 1) {
printf("Not implemented! Word not found.\n");
exit(3); // error with provided service
}
user_str_len = setup_buff(buff, dest, BUFFER_SZ);
free(dest);
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?
//
// Providing both the pointer and the length is necessary
// because it will help the function keep track of the length
// of the buffer while and after each step of modification
// to avoid overflow as well as to set up the buffer after
// the string operation is complete (so that it always has
// exactly 50 bytes)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment