Tutorial 5 Solutions: Characters and Strings

  1. Ask your tutor any questions you have about the assignment.
  2. int isdigit( int ch )
    int islower( int ch )
    int toupper( int ch )
    (Note: you should be able to write these functions without knowing any actual ASCII codes.) 
    
    int isdigit( int ch )
    {
       return( ch >= '0' && ch <= '9' );
    }
    
    int islower( int ch )
    {
       return( ch >= 'a' && ch <= 'z' );
    }
    
    int toupper( int ch )
    {
       if( ch >= 'a' && ch <= 'z' ) {
          return( ch + 'A' - 'a' );
       }
       else {
          return( ch );
       }
    }
    
  3. Write a program sum_digits.c which reads characters from its input and counts digits.

    When the end of input is reached it should print a count of how many digits occured in its input and their sum.

    The only functions you can use are getchar and printf.

    For example:

    ./sum_digits
    1 2 3 o'clock
    4 o'clock rock
    4 digits which summed to 10
    ./sum_digits
    12 twelve 24 twenty four
    thirty six 36
    6 digits which summed to 18
    
    #include <stdio.h>
    
    int
    main(void) {
        int c;
        int digitCount, digitSum, digitValue;
    
        digitCount = 0;
        digitSum = 0;
    
        // getchar returns an int which will contain either
        // the ASCII code of the character read or EOF
    
        c = getchar();
        while (c != EOF) {
    
            // test if ch is digit, isdigit would be better
            if (c >= '0' && c <= '9') {
                digitCount = digitCount + 1;
                digitValue = c - '0';
                digitSum = digitSum + digitValue;
            }
    
            c = getchar();
        }
        printf("Input contained %d digits which summed to %d\n", digitCount, digitSum);
        return 0;
    }
    
  4. Write a program line_length.c which reads lines from its input and prints how many characters each line contains.

    The only functions you can use are fgets and printf.

    You can assume lines contain at most 4096 characters.

    For example:

    ./line_length
    Andrew Rocks
    line 12 characters long
    A very long line.
    line 17 characters long
    short
    line 5 characters long
    
    line 0 characters long
    
    #include <stdio.h>
    
    #define MAX_LINE 4096
    
    int
    main(void) {
        char line[MAX_LINE];
        int  i;
    
        while (fgets(line, MAX_LINE, stdin) != NULL) {
    
            // count characters before newline or '\0'
            i = 0;
            while (line[i] != '\n' && line[i] != '\0') {
                i = i + 1;
            }
            printf("line %d characters long\n", i);
        }
        return 0;
    }
    
  5. Write a program upper_case.c which reads characters from its input and convert all lower case letters to upper case.

    The only functions you can use are getchar and putchar.

    For example:

    ./upper_case
    I'm very angry that you dumped me for Gary!!!!!!
    I'M VERY ANGRY THAT YOU DUMPED ME FOR GARY!!!!!!
    
    #include <stdio.h>
    
    int
    main(void) {
        int c;
        int alphabetPosition;
    
        // getchar returns an int which will contain either
        // the ASCII code of the character read or EOF
    
        c = getchar();
        while (c != EOF) {
    
            // test if ch is digit, isdigit would be better
            if (c >= 'a' && c <= 'z') {
                alphabetPosition = c - 'a';
                c = 'A' + alphabetPosition;
            }
    
            putchar(c);
    
            c = getchar();
        }
        return 0;
    }
    
  6. Write a program strip_comments.c which reads lines from its input and prints them after removing any C // style comments. In another words if the line contains // it does not print the // or anything after it.

    The only functions you can use are fgets and printf.

    You can assume lines contain at most 4096 characters.

    For example (program output shown in bold):

    ./strip_comments
         x = x + 1;  // This means add one to the variable x
         x = x + 1;
    
    #include <stdio.h>
    
    #define MAX_LINE 4096
    
    int
    main(void) {
        char line[MAX_LINE];
        int  i;
    
        while (fgets(line, MAX_LINE, stdin) != NULL) {
    
            // strip // style comments from input
    
            i = 0;
            while (line[i] != '\n' && line[i] != '\0') {
    
                // safe to look at line[i+1] because
                // we know here line[i] != '\0'
    
                if (line[i] == '/' && line[i + 1] == '/') {
    
                    // replace // with end of -line
                    line[i] = '\n';
                    line[i + 1] = '\0';
    
                    // could break here but loop will stop anyway
                }
    
                i = i + 1;
            }
    
            // write possibly-modified line
    
            printf("%s", line);
        }
        return 0;
    }
    
    Also - is that a good comment to add to a C program?
      x = x + 1;  // This means add one to the variable x
    

    The above is a bad comment because it unnecessarily states the obvious.

    It adds nothing to the readers understanding of the program and worse, it clutters the program.

    Dont add comments like this.

  7. Write a program filter_empty_lines.c which reads lines from its input and prints them only if they contain a non-white-space-character.

    In another words remove lines are empty or contain only white-space.

    The only functions you can use are fgets and printf.

    You can assume lines contain at most 4096 characters.

    You can assume there are only 3 white space characters, space, tab & new-line.

    For example:

    ./filter_empty_lines
    full line
    full line
             
    another no-empty line
    another no-empty line
    
    #include <stdio.h>
    
    #define MAX_LINE 4096
    
    int
    main(void) {
        char line[MAX_LINE];
        int  i;
        int whiteSpaceCount;
    
        while (fgets(line, MAX_LINE, stdin) != NULL) {
    
            // print lines iff they contain a non white-space character
    
            i = 0;
            whiteSpaceCount = 0;
            while (line[i] != '\0') {
                // test for white space (isspace would be better here)
    
                if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n') {
                    whiteSpaceCount = whiteSpaceCount + 1;
                    // could break here
                }
    
                i = i + 1;
            }
    
            if (whiteSpaceCount > 0) {
                printf("%s", line);
            }
        }
        return 0;
    }
    
  8. Write a program letter_triangle.c that read a positive integer n and outputs a triangle of letters of height n as below. For example:
    ./letter_triangle
    Enter height: 3
      A
     BCB
    DEFED
    ./letter_triangle
    Enter height: 7
          A
         BCB
        DEFED
       GHIJIHG
      KLMNONMLK
     PQRSTUTSRQP
    VWXYZABAZYXWV
    ./letter_triangle
    Enter height: 10
             A
            BCB
           DEFED
          GHIJIHG
         KLMNONMLK
        PQRSTUTSRQP
       VWXYZABAZYXWV
      CDEFGHIJIHGFEDC
     KLMNOPQRSRQPONMLK
    TUVWXYZABCBAZYXWVUT
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Description: Prompts the user for a strictly positive number N              *
     *              and outputs an equilateral triangle of height N.               *
     *              The top of the triangle (line 1) is labeled with the letter A. *
     *              For all nonzero p < N, line p + 1 of the triangle is labeled     *
     *              with letters that go up in alphabetical order modulo 26        *
     *              from the beginning of the line to the middle of the line,      *
     *              starting wth the letter that comes next in alphabetical order  *
     *              modulo 26 to the letter in the middle of line p,               *
     *              and then down in alphabetical order modulo 26                  *
     *              from the middle of the line to the end of the line.            *
     *                                                                             *
     * Written by Eric Martin for COMP9021                                         *
     * modified by Andrew Taylor for 1911                                          *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    
    #include <stdio.h>
    #define NUM_LETTERS 26
    
    int main(void) {
        int ch, i, j, k;
        int height = 0;
    
    
        printf("Enter height: ");
        scanf("%d", &height);
    
        ch = 'A';
        for (i = 1; i <= height; i = i + 1) {
    
            /* Displays spaces on the left */
            for (j = 0; j < height - i; j = j + 1) {
                printf(" ");
            }
    
            /* Displays letters before middle column */
            for (k = 1; k < i; k = k + 1) {
                putchar(ch);
    
                /* code of next letter */
                ch = (ch - 'A' + 1) % NUM_LETTERS + 'A';
            }
    
            /* Displays middle column */
            putchar(ch);
    
            /* Displays letters after middle column */
            for (k = 1; k < i; k = k + 1) {
    
                /* Code of previous letter */
                ch = (ch - 'A' + (NUM_LETTERS-1)) % NUM_LETTERS + 'A';
                putchar(ch);
            }
            printf("\n");
    
            /* Code of first letter to be input on next line */
            ch = ((1 + i) * i / 2) % NUM_LETTERS + 'A';
        }
    
        return 0;
    }
    
  9. Write a program input_statistics.c that for the characters provided on standard input.:

    For example:

    ./input_statistics
        "Beauty is truth, truth beauty," ? that is all
        Ye know on earth, and all ye need to know.
    Input contains 27 blanks, tabs and new lines
    Number of words: 19
    Length of shortest word: 2
    Length of longest word: 8
    ./input_statistics
    And here is another example with only one line of input!!!!!!!!!
    Input contains 11 blanks, tabs and new lines
    Number of words: 11
    Length of shortest word: 2
    Length of longest word: 14
    
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Description: Outputs                                                        *
     *              - the number of blank characters (spaces, tabs and new lines)  *
     *              - the length of the shortest word                              *
     *                (any sequence of nonblank characters), and                   *
     *              - the length of the longest word                               *
     *                (any sequence of nonblank characters)                        *
     *              read from standard input.                                      *
     *                                                                             *
     * Written by Eric Martin for COMP9021                                         *
     * Modified by Andrew Taylor for COMP9021                                         *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    
    #include <stdio.h>
    
    int main(void) {
        int whiteSpaceCount;
        int wordMinLength, wordMaxLength, wordCurrentLength;
        int wordCount;
        int ch;
    
        wordCount = 0;
        whiteSpaceCount = 0;
        wordCurrentLength = 0;
    
        ch = getchar();
        while (ch != EOF) {
    
            // iswhite would be better here
            if (ch == ' ' || ch == '\t' || ch == '\n') {
    
                whiteSpaceCount = whiteSpaceCount + 1;
    
                // A complete word has just been read iff wordCurrentLength > 0,
                // which is then the length of that word.
    
                if (wordCurrentLength > 0) {
                    if (wordCount == 0) {
                        wordMinLength = wordCurrentLength;
                    } else if (wordCurrentLength < wordMinLength) {
                        wordMinLength = wordCurrentLength;
                    } else if (wordCurrentLength > wordMaxLength) {
                        wordMaxLength = wordCurrentLength;
                    }
    
                    wordCurrentLength = 0;
                    wordCount = wordCount + 1;
                }
            } else {
                wordCurrentLength = wordCurrentLength + 1;
            }
            ch = getchar();
        }
    
        printf("Input contains %d blanks, tabs and new lines\n", whiteSpaceCount);
    
        if (wordCount == 0) {
            printf("No word has been input\n");
        } else {
            printf("Number of words: %d\n", wordCount);
            printf("Length of shortest word: %d\n", wordMinLength);
            printf("Length of longest word: %d\n", wordMaxLength);
        }
    
        return 0;
    }
    
    
  10. Write a function void substr(char s[], char d[], int lo, int hi) where given a string s[], we want to extract from s[] a substring starting at lo and ending at hi inclusive. The resultant substring is to be returned in the character array d[]. Checks must be made to ensure that lo is within the length of s[]; if not, then d[] is an empty string. If s[] is shorter than specified by hi, then d[] contains the substring of s[] starting at lo to the '\0' character.
    void substr( char s[], char d[], int lo, int hi ){
        int i=0, j=0;
    
        // scan to s[lo], or end of s[]
        while( i < lo && s[i] != '\0' ) {
            i++;
        }
        if( i == lo ) {
            // keep copying until s[hi], or end of s[]
            while( i <= hi && s[i] != '\0' ) {
                d[j++] = s[i++];
            }
        }
        // finally, add the end-of-string marker
        d[j] = '\0';
    }