Exercise 16: Character Count

For this assignment you will write a program that counts the number of times a target character appears in some input. The character to search for will be specified as a command line argument. The input text could either be a command line argument or standard input. Your program should also be able to search for the character in a randomly generated string. This is a longer exercise, make sure to appropriately use functions. You must have 4 functions:

  1. A function to validate the number of characters in the random string
  2. A function to count the target character in a command line arguement
  3. A function to count the target character from standard input

Write the entire program in the provided file, char_count.c.

main()

In the past, our main() function has had no parameters. Since we want to use the command line arguments in this program we will need to add two parameters to the function:

int main(int argc, char *argv[]) {
    ...

Program Behavior

If you compiled the program and named the executable char-count, then you must be able to run the program like so:

./char-count h hello
1

The program prints out 1, because there is 1 'h' in "hello".

You must also be able to run your program so that it searches through standard input to count occurrences like this:

./char-count h
hello, how are you?
2

When reading from standard input you will read every character until you get to EOF. Remember that you need to press Ctrl+d in the terminal to send an EOF. You may see a “D” along with the printed number as a result.

I recommend getting it to work with either command line input or standard input first, and then getting it to work with both.

The command line arguments are passed into main() by the operating system through the argv parameter. argc is the number of arguments. If you run the program as shown in the first example, then argc will be 3, argv[0] will be "./char-count", argv[1] will be "h", and argv[2] will be "hello".

argv[1] contains the target character, but it is a string not a single character. To access the character itself, get the first character of argv[1] using argv[1][0].

You should also be able to check for the option -r to generate a random string with uppercase A-Z and lowercase a-z letters of the length specified (length must be > 0). To check if the string is equal to -r you can use the strcmp function from string.h. For example:

./char-count -r 12 h
HhasOIGowaeh
2

Notice how the random string is also displayed. This portion of the assignment will be tested manually.

Input Validation

If the program is called incorrectly, you must detect the input error, print a message describing what is wrong, and return a non-zero exit code. The exit code is simply the value that main() returns. So far we have had our programs always return 0, but here we will return different values based on different error conditions.

If the program is run correctly there will be either 2, 3, or 4 arguments, so if argc has any other value, print a message about how to correctly use the program and return 1.

The user might also pass a string as the target (in argv[1]) that has more than 1 character in it and if that string is not -r then print a message indicating what is wrong and return 2.

If the random string operator -r is used, it must appear after the program name (argv[1]), be followed with a number that is > 0, and be followed by the target character. The program uses atoi() to convert the strings to integers, but atoi() does not do any validation for you. For example, atoi("abc") returns 0 and atoi("10abc") returns 10. Your program must provide better input validation to notifies the user if the numbers provided are not positive integers. The simplest way to do this is to loop over all the characters in the potential number string argument (argv[2] when using -r) string and make sure each character is a digit. The isdigit() function from ctype.h can do this for you. You will also need to make sure the string is not all zeros (since zero is not a positive integer). If the number is found to be invalid (not a number or <= 0) return 3.

Example Output

Here are some example valid runs of the program, and the expected output.

./char-count h hello
1

./char-count -r 5 f
faFpf
2

Normally spaces separate command line arguments. If you want to use an argument that contains spaces, you can use quotes:

./char-count b "big brown bear"
3

./char-count e
command line arguments are great
4

Here are some example runs of the program of invalid runs with the expected output and return code.

Incorrect number of arguments - return code 1

./char-count
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

./char-count a too many arguments
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

./char-count -r
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

./char-count -r h
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

./char-count -r hello
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

./char-count -r 0
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

./char-count -r 7
Usage:
Counting from standard input: ./char-count <character>
Counting from the command line: ./char-count <character> <input string>
Counting from a random string: ./char-count <random string operator> <string length> <character>

Invalid character argument - return code 2

./char-count hello hello
The <character> argument must contain a single character

./char-count -r 12 hello
The <character> argument must contain a single character

Invalid character argument - return code 3

./char-count -r 0 y
The <string length> argument must be a positive integer

./char-count -r h h
The <string length> argument must be a positive integer

./char-count -r -1 k
The <string length> argument must be a positive integer

./char-count -r 000000000 t
The <string length> argument must be a positive integer

Local Testing

You can run the GitHub testing locally with the command:

make gh-test-char-count

Submission

Push your code to GitHub. The tests will make sure that your program prints the correct output when given valid arguments, and that the error code is correct when passed incorrect arguments.

Grading

Your grade for this assignment will be out out of 10 points: