K&R C Programs Exercise 7-1

Exercise 7-1. Write a program that converts upper case to lower or lower case to upper, depending on the name it is invoked with, as found in argv[0].

Unix convention: a single binary is installed under two names via symlinks (tolower and toupper). argv[0] holds the name used to invoke the program. Checking whether "lower" appears anywhere in argv[0] with strstr handles paths like /usr/bin/tolower and bare tolower alike.

Solution

/* K&R Exercise 7-1 — upper/lower case converter, behaviour set by argv[0]
 * Compile: gcc -ansi -Wall ex7-1.c -o tolower
 *          ln -s tolower toupper
 * Usage:   ./tolower < input.txt    (converts to lower)
 *          ./toupper < input.txt    (converts to upper) */
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int c;
    int to_lower;
    (void)argc;

    /* strstr handles full paths: "/usr/bin/tolower" also contains "lower" */
    to_lower = (strstr(argv[0], "lower") != NULL);

    while ((c = getchar()) != EOF)
        putchar(to_lower ? tolower(c) : toupper(c));

    return 0;
}

Compile, Link, and Test

gcc -ansi -Wall ex7-1.c -o tolower
ln -s tolower toupper

echo "Hello, World!" | ./tolower     # hello, world!
echo "Hello, World!" | ./toupper     # HELLO, WORLD!

Expected Output

hello, world!
HELLO, WORLD!

Testing without Symlinks

If you don't want to create a symlink, copy and rename:

cp tolower toupper
echo "Hello" | ./toupper    # HELLO

Or pass the path directly — since argv[0] is whatever string the shell used to invoke the program:

cp tolower ./tolower_copy
echo "hello" | ./tolower_copy   # to_lower = true (contains "lower")

What This Exercise Teaches

  • argv[0] as program identity — the shell sets argv[0] to the invocation path; a program can inspect this to alter its behaviour, which is how tools like gzip/gunzip and vi/vim/view share a single binary
  • strstr for substring matching — checking for "lower" as a substring handles ./tolower, /usr/bin/tolower, and to_lower uniformly
  • Conditional expression in putcharputchar(to_lower ? tolower(c) : toupper(c)) keeps the loop body to a single statement; the direction is decided once before the loop, not on every character

Set Up Your C Environment

← Chapter 6 Solutions  | 
Chapter 7 Solutions  | 
Exercise 7-2 →

Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>