Search code examples
ckernighan-and-ritchie

K&R answer 1-12 (using functions to reduce the number of lines of code)


I have written the following program to answer Kernighan and Ritchies ch1 problem 12.

The issue is that I have never really understood how to properly use functions and would like to know why the one I wrote into this program, getcharc(), does not work?

What are good resources that explain correct function usage. Where? and How?

I know the optimal solution to this problem from Richard Heathfield's site (which uses || or, rather than nested while statements, which I have used), however I would like to know how to make my program work properly:

#include <stdio.h>
int getcharc ();
// Exercise 1-12
// Copy input to output, one word per line
// words deleniated by tab, backspace, \ and space

int main()
{
    int c;

    while ((c = getchar()) != EOF) {
        while ( c == '\t') {
            getcharc(c);
        }
        while ( c == '\b') {
            getcharc(c);
        }
        while ( c == '\\') {
            getcharc(c);
        }
        while ( c == ' ') {
            getcharc(c);
        }
        putchar(c);
    }
}
int getcharc ()
{
    int c;

    c = getchar();
    printf("\n");
    return 0;
}

The original program (and I know it has bugs), without the function was:

#include <stdio.h>

// Exercise 1-12
// Copy input to output, one word per line
// words deleniated by tab, backspace, \ and space

int main()
{
    int c;

    while ((c = getchar()) != EOF) {
        while ( c == '\t') {
            c = getchar();
            printf("\n");
        }
        while ( c == '\b') {
            c = getchar();
            printf("\n");
        }
        while ( c == '\\') {
            c = getchar();
            printf("\n");
        }
        while ( c == ' ') {
            c = getchar();
            printf("\n");
        }
        putchar(c);
    }
}

So all I am trying to do with the function is to stop

c = getchar();
printf("\n");

being repeated every time.


Solution

  • One of the possible solution is, change prototype for your function to int getcharc (int c, int flag).
    Now your code after some modification;

    #include <stdio.h>
    int getcharc (int c, int flag);
    // Exercise 1-12
    // Copy input to output, one word per line
    // words deleniated by tab, backspace, \ and space
    
    int main()
    {
        int c;
        int flag = 0;  //to keep track of repeated newline chars.
    
        while ((c = getchar()) != '\n') {
            flag = getcharc(c, flag);   // call getcharc() for each char in the input string. Testing for newline and printing of chars be done in the getcharc() function
        }
        return 0;     
    }
    
    int getcharc (int c, int flag)
    {
            if( (c == ' ' || c == '\t' || c == '\b' || c== '\\')  && flag == 0)
            {
                printf("\n");
                flag = 1;
            }
            else
            {
                if(c != ' ' && c != '\t' && c != '\b' && c!= '\\')
                    {
                         putchar(c);
                         flag = 0;
                    }
            }
            return flag;
    }
    

    EDIT:

    but I wanted to keep the nested while statements rather than using || or

    Your nested while loop is executing only once for each character as grtchar() reads one character at one time. No need of nested loops here! You can check it by replacing while to if and your code will give the same output for a given string. See the output here.

    know the optimal solution to this problem from Richard Heathfield's site (which uses || or, rather than nested while statements, which I have used), however I would like to know how to make my program work properly:

    You make your program work to some extent (with your bugs) by adding an if condition and a break statement as;

    #include <stdio.h>
    int getcharc (int c);
    
    int main()
    {
        int c;
    
        while ((c = getchar()) != '\n') {
            while ( c == '\t') {
                c = getcharc(c);
                if(c != '\t')
                    break;
                }
    
            ....
            ....
    
    
            while ( c == ' ') {
                c = getcharc(c);
                if(c != ' ')
                    break;
                }
            putchar(c);
        }
        return 0;
    }
    int getcharc (int c)
    {
        c = getchar();
        printf("\n");
        return c;
    }