Search code examples
cloopswhile-loopreturninfinite-loop

Why is return 0 not working in this case?


I recently started learning C from The C Programming Language by Brian Kernighan and Dennis Ritchie. In that book, there's a whole subsection (1.5.1, 2nd Ed.) where the authors create a file copying program (but I am using this as a text (input by the user) copying program). Their code basically looks like this

#include <stdio.h>

int main()

{
    int c;
    c = getchar();

    while (c != EOF) {
        putchar(c);
        c = getchar();
    }
}

This code works fine when run, but the program never stops. The program keeps on waiting for inputs and goes on copying them, endlessly, never terminating. Now I wanted to create a program where this endless copying does terminate. To do so, I tweaked the code a little bit. Here's my code

#include <stdio.h>

int main()

{
    int c;
    c = getchar();

    while (c != EOF) {
        putchar(c);
        c = getchar();
    }

    return 0;

}

I thought that explicitly writing return 0; at the end might do the job, but it seems that the output doesn't change at all. I also tried using if-else conditions and looping them as follows

#include <stdio.h>

int main()

{
    int c;
    c = getchar();

    while (1) {

        if (c != EOF){
            putchar(c);
            c = getchar();
        }

    else
        return 0;
    }
}

But the program didn't change at all in this case as well.

My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?

Here, it is important for me to clarify what I mean by "once" (or "n times" for that matter). When I use the command prompt (I use Windows) to run the compiled file, the program expects an input. I enter the input through my keyboard, and then press Enter to see the reproduced input. After this, the program again expects me to enter some input. I don't want this to happen. I want the program to end by itself after it copies my input once. This is what I mean by "once" (and the above definition can easily be extended for "n times" as well).


@anatolyg and @Jabberwocky have suggested the use of \n (new line escape character) to make the program work. But this solution fails when the input contains linebreaks, for example

my code does
not work so

I am asking
for help here

Copying this into the command prompt as the input, and using the program suggested by the above two users yields only my code does as the output, which is not what I wanted as an output. Is there any way I can make this program work for text blocks with linebreaks and also make it stop after one input (in this case, the whole text block is just one input)?


After interacting with the other people here, I have come to realise that my definition of "one input" or "once" is quite vague, unclear and not at all concrete. Thus it is nothing but expected that C cannot do what I want it to do. I am accepting the answer which suggests to use the new-line escape character as a signal to terminate the program, because that is the closest to what I had in my mind. Thank you all.


Solution

  • Since you want to read only one line of input, you can terminate the loop on the end-of-line character '\n'.

    c = getchar();
    
    while (c != '\n') {
        putchar(c);
        c = getchar();
    }
    

    If you use a Windows terminal to enter data to your program, this will be enough. If you redirect the input to your program, so that it comes from a file, it will read the file up to the first newline character. However, if the file contains no newline character, your program will get EOF at end of file. So the terminating condition should also check for EOF.

    c = getchar();
    
    while (c != '\n' && c != EOF) {
        putchar(c);
        c = getchar();
    }
    

    If you want to read the first n lines from the file/terminal, you need a counter. Then your code will become a bit more complicated, and I think an endless loop with exits in the middle would be a better implementation.

    int line_counter = 0;
    int max_lines = 5;
    
    while (1) {
        int c = getchar();
        if (c == EOF)
            break;
    
        putchar(c);
    
        if (c == '\n')
        {
            ++line_counter;
            if (line_counter == max_lines)
                break;
        }
    }
    

    Another method for separating between inputs is with an empty line. This redefines input format to have "paragraphs" of text. This will complicate the code a little more - it should also hold the previous character it read. To detect an empty line, which marks the end of a paragraph: if both previous and current character are end-of-line characters, the paragraph of text has just ended.

    int record_counter = 0;
    int max_records = 5;
    int prev_c = '\n';
    
    while (1) {
        int c = getchar();
        if (c == EOF)
            break;
    
        putchar(c);
    
        if (prev_c == '\n' && c == '\n')
        {
            ++record_counter;
            if (record_counter == max_records)
                break;
        }
    
        prev_c = c;
    }