Skip to content
Snippets Groups Projects
Commit caa1033f authored by Ziheng Chen's avatar Ziheng Chen
Browse files

Upload New File

parent c8af61d2
Branches
No related tags found
No related merge requests found
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define SPACE_CHAR ' '
//prototypes for functions to handle required functionality
// TODO: #1 What is the purpose of providing prototypes for
// the functions in this code module
/*
Prototypes in C are critical for forward declarations,
type checking, code modularity, and enhancing readability.
They ensure the program compiles without errors
when functions are used before being defined.
*/
void usage(char *);
int count_words(char *);
void reverse_string(char *);
void word_print(char *);
void usage(char *exename){
printf("usage: %s [-h|c|r|w] \"string\" \n", exename);
printf("\texample: %s -w \"hello class\" \n", exename);
}
//count_words algorithm
// 1. create a boolean to indicate if you are at the start of a word
// initialize to false
// 2. Loop over the length of the string
// 2a. Get the current character aka str[i]
// 2b. Is word_start state false?
// - Is the current character a SPACE_CHAR?
// * if YES, continue loop (a.k.a) goto top with "continue;"
// * if NO, we are at the start of a new word
// > increment wc
// > set word_start to true
// 2c. Else, word_start is true
// - Is the current character a SPACE_CHAR?
// * if YES we just ended a word, set word_start to false
// * if NO, its just a character in the current word so
// there is nothing more to do
// 3. The current word count for the input string is in the wc variable
// so just 'return wc;'
int count_words(char *str){
// Suggested local variables
int len = strlen(str);
int wc = 0;
bool word_start = false;
// Please implement
for (int i = 0; i < len; i++) {
char current = str[i]; // Get the current character
if (!word_start) { // If not in a word
if (current != SPACE_CHAR) { // If the current character is not a space
wc++; // Increment word count
word_start = true; // Mark the start of a new word
}
} else { // If already in a word
if (current == SPACE_CHAR) { // If the current character is a space
word_start = false; // Mark the end of the current word
}
}
}
return wc;
}
//reverse_string() algorithm
// 1. Initialize the start and end index variables
// a. end_idx is the length of str - 1. We want to remove one
// becuase at index str[len(str)] is the '\0' that we want
// to preserve because we are using C strings. That makes
// the last real character in str as str[len(str)-1]
// b. start_idx is 0, thus str[0] is the first character in the
// string.
//
// 2. Loop while end_idx > start_idx
// 2a. swap the characters in str[start_idx] and str[end_idx]
// 2b. increment start_idx by 1
// 2c. decrement end_indx by 1
//
// 3. When the loop above terminates, the string should be reversed in place
void reverse_string(char *str){
// Suggested local variables
int end_idx = strlen(str) - 1; //should be length of string - 1
int start_idx = 0;
char tmp_char;
// Please implement
while (end_idx > start_idx) {
tmp_char = str[start_idx]; // Store the start character temporarily
str[start_idx] = str[end_idx]; // Replace start character with end character
str[end_idx] = tmp_char; // Replace end character with the temporary character
start_idx++; // move the start index forward
end_idx--; // move the end index backward
}
//return;
}
//word_print() - algorithm
//
// Start by copying the code from count words. Recall that that code counts
// individual words by incrementing wc when it encounters the first character
// in a word.
// Now, at this point where we are incrementing wc we need to do a few more things
// 1. incrment wc, and set word_start to true like before
// 2. Now, set wlen to zero, as we will be counting characters in each word
// 3. Since we are starting a new word we can printf("%d. ", wc);
//
// If word_start is true, we are in an active word, so each time through the loop
// we would want to:
// 1. Check if the current character is not a SPACE_CHARACTER
// a. IF it is NOT A SPACE -> print the current character, increment wlen
//
// 2. In the loop there are 2 conditions that indicate a current word is ending:
// a. word_start is false and the current character is a SPACE_CHARACTER
// OR
// b. the current loop index is the last character in the string (aka the
// loop index is last_char_idx)
//
// IF either of these conditions are true:
// * Print the word length for current word - printf(" (%d)\n", wlen);
// * Set word_start to false
// * Set wlen to 0 given we are starting a new word
//
// EXAMPLE OUTPUT
// ==============
// ./stringfun -w "C programming is fun"
// Word Print
// ----------
// 1. C (1)
// 2. programming (11)
// 3. is (2)
// 4. fun (3)
void word_print(char *str){
//suggested local variables
int len = strlen(str); //length of string - aka strlen(str);
int last_char_idx = len - 1; //index of last char - strlen(str)-1;
int wc = 0; //counts words
int wlen = 0; //length of current word
bool word_start = false; //am I at the start of a new word
// Please implement
for (int i = 0; i < len; i++) {
char current = str[i]; // Get the current character
if (!word_start) {
if (current != SPACE_CHAR) { // If not in a word
wc++; // Increment word count
word_start = true; // Mark the start of a new word
wlen = 0; // Reset word length for the new word
printf("%d. ", wc); // Print the word index
}
}
if (word_start) { // If we are in a word
if (current != SPACE_CHAR) { // If the current character is not a space
printf("%c", current); // Print the character
wlen++; // Increment the word length
}
// Check if we reached the last character or the end of the word
if (current == SPACE_CHAR || i == last_char_idx) {
if (i == last_char_idx && current != SPACE_CHAR) {
// Handle the last word if it doesn't end with a space
//wlen++;
//if (word_start){
printf(" (%d)\n", wlen);
} else if (current == SPACE_CHAR) {
printf(" (%d)\n", wlen); // Print the word length and newline
}
word_start = false; // Mark the end of the current word
}
}
}
}
int main(int argc, char *argv[]){
char *input_string; //holds the string provided by the user on cmd line
char *opt_string; //holds the option string in argv[1]
char opt; //used to capture user option from cmd line
//THIS BLOCK OF CODE HANDLES PROCESSING COMMAND LINE ARGS
if (argc < 2){
usage(argv[0]);
exit(1);
}
opt_string = argv[1];
//note arv[2] should be -h -r -w or -c, thus the option is
//the second character and a - is the first char
if((opt_string[0] != '-') && (strlen(opt_string) != 2)){
usage(argv[0]);
exit(1);
}
opt = opt_string[1]; //get the option flag
//handle the help flag and then exit normally
if (opt == 'h'){
usage(argv[0]);
exit(0);
}
//Finally the input string must be in argv[2]
if (argc != 3){
usage(argv[0]);
exit(1);
}
input_string = argv[2];
//ALL ARGS PROCESSED - The string you are working with is
//is the third arg or in arv[2]
switch (opt){
case 'c': {
int wc = count_words(input_string); //variable for the word count
//TODO: #2. Call count_words, return of the result
// should go into the wc variable
printf("Word Count: %d\n", wc);
break;
}
case 'r': {
//TODO: #3. Call reverse string using input_string
// input string should be reversed
reverse_string(input_string);
printf("Reversed string: %s\n", input_string);
//TODO: #4. The algorithm provided in the directions
// state we simply return after swapping all
// characters because the string is reversed
// in place. Briefly explain why the string
// is reversed in place - place in a comment
/*
The string is reversed in place because strings in C
are arrays of characters passed by reference (via a pointer).
Modifying the array elements inside the function directly
affacts the original string in memory, which avoids the need
for creating and copying to a new string to save memory and
processing time.
*/
break;
}
case 'w': {
printf("Word Print\n----------\n");
word_print(input_string);
//TODO: #5. Call word_print, output should be
// printed by that function
break;
}
//TODO: #6. What is the purpose of the default option here?
// Please describe replacing this TODO comment with
// your thoughts.
/*
The default option acts as a catch-all for invalid or unexpected input.
This ensures the program can gracefully handle incorrect command-line arguments
by providing usage information and exiting.
It prevents undefined behavior by validating all inputs.
*/
default:
usage(argv[0]);
printf("Invalid option %c provided, exiting!\n", opt);
exit(1);
}
//TODO: #7. Why did we place a break statement on each case
// option, and did not place one on default. What
// would happen if we forgot the break statement?
/*
The break statements prevent fall-through behavior in a switch statement.
Without them, the program would execute all subsequent cases until it encounters a break.
This could lead to incorrect or unintended behavior.
*/
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment