2

I am trying to solve a problem from the K&R C programming book that requires one to write a low level I/O program which reads text from a file and prints it on screen, if no input file is given in the command line, it must take input from STDIN and print on the screen. I think I have solved the problem and my code is as given below:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

void llfilecopy (int, int);

int main(int argc, char *argv[])
{
    int ifd, i = 1;
    printf("buffer = %d", BUFSIZ);

    if (argc == 1)
        llfilecopy (0, 1);

    else
    {
        while (--argc > 0)
        {
            if ((ifd = open(argv[i++], O_RDONLY, 0)) == EOF)
            {
                printf("cat: cant open %s\n", *argv);
                return 1;
            }
            else
            {
                llfilecopy (ifd, 1);
                printf ("\n\n");
                close(ifd);
            }

        }
    }
    return 0;
}
void llfilecopy (int ifd, int ofd)
{
    char buff [BUFSIZ];
    int n;

    while ((n = read (ifd, buff, BUFSIZ)) > 0)
    {
        if (write (ofd, buff, n) != n)
            printf ("cat: write error on stdout");
    }
}

However, I am facing a funny problem which I cannot account for. Notice the printf statement in line 3 after main(). If I use the following

printf("buffer = %d", BUFSIZ);

this printf is executed after printing the file on screen. If however I add a '\n' i.e.

printf("buffer = %d\n", BUFSIZ);

the printf is executed before printing the file to screen. Perhaps its just a silly mistake of mine. Can you please point out whats going wrong here? Thank you so much. I am using the online GDB - GCC C compiler https://www.onlinegdb.com/online_c_compiler#

6
  • stdout is by default buffered. This means printf or similar functions don't cause the characters to appear on the output device immediately. They are written to an internal buffer instead. The characters appear when the buffer is flushed. K&R should explain this somewhere. Commented Dec 19, 2024 at 7:39
  • 2
    GDB is a debugger, not a compiler. The compiler is gcc. That site uses a combination of the gcc compiler and the gdb debugger. Commented Dec 19, 2024 at 7:41
  • 2
    @paxdiablo Nothing wrong with using K&R for an introduction to C. It's a bit dated, but hey, so am I. Commented Dec 19, 2024 at 8:00
  • 2
    Ironically, the issue in your low-level IO post is the high-level IO :) Commented Dec 19, 2024 at 11:14
  • 1
    Tip: Error messages should be written to stderr. Replace printf( ... ) with fprintf( stderr, ... ) Commented Dec 19, 2024 at 11:15

1 Answer 1

4

Your target seems to be line buffered, meaning it won't update a line until it gets a "flush" instruction to move everything in the buffer to the screen.

Flushing can be done in 3 ways:

  • Adding the \n character to the printf format string or equivalent (calling puts etc).
  • An explicit call to fflush(stdout).
  • Reaching the end of the program.
Sign up to request clarification or add additional context in comments.

2 Comments

Just for completeness, you'll probably also flush once the output buffer is full, even if a newline has not been sent. This may occur if, for example, you've output 4K of information with no other flush-causing event. This can also be affected by things like setvbuf.
There's at least one more way to flush stdout: call a function that reads stdin. For example, printf("prompt:"); / scanf("%d", &x); prints the prompt before blocking on terminal I/O, when run on a terminal without redirection. (But if stdout is redirected to a file, it isn't flushed by scanf on stdin from the terminal.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.