Saturday 8 January 2011

The C Programming Language (K&R) 01x06—File Copying (p. 18)—Exercises 1-6, 1-7


The trek continues through the book “The C Programming Language” by Brian Kernighan and Dennis Ritchie aka K&R. At times, I pause to reflect on what it all means and write about it in this blog: my experiences in the jungle of C code.

The reasons I’m doing it? To learn the language. To show others I know something about the C. To create notes for future reference where, on a blog, I can easily find an answer on something I did previously. To practice my writing of documentation and in general.

I am using Visual C++ 2010 and creating the code as a console application. I keep hearing about gcc as a compiler. There’s one to check out. I think it’s open source. Take about a revolution in the world of computing: open source.

K&R p. 18, File Copying

This blog continues from what I wrote here. It’s all about the standard I/O library and its functions: getchar()and putchar() and EOF (not a function).

Exercise 1-6 asks us to verify that the expression (c = getchar()) != EOF is either 1 or 0. I was so wrapped up in looking at the value of EOF I wrote a bunch of other code. I got sidetracked. Besides. How do I enter EOF from the keyboard when the console window is up?

I’m used to console environments where you can hit break. That’s what the break key is for. That works on certain mainframe computers, but the break key stops the program and it’s not an EOF character. In the Microsoft DOS environment, you would hit control-break to get the same result. Or control-C. But again, that terminates the program not what I was looking for. (Note: You can intercept the control-C message and disable it. So even in DOS, control break doesn’t always work.)

Back to entering EOF with key strokes. I tapped a bunch of keys. I knew all the regular characters would simply pass through and display. They weren’t EOF.

Next step? Use alt-<num> to send an ASCII value to the program. Hold down the <alt> key and type a number and you’ll get the ASCII value. So <alt> 32 is space. None of those worked. Not 0, 13 etc.

Then I tried different <ctrl>+letter combos. A, B, C—oops don’t want break. It turns out that <ctrl> Z creates the EOF state. Go figure. I suppose if you have to choose a letter to represent the end of a stream of characters then Z—Zed—makes the most sense.
  
But there’s a twist. It only works if you enter it thus: enter, <ctrl> z, enter. That is, it has to be at the start of a newline and you have to hit enter to send the data to the program. The implementation of getchar() uses buffering. It doesn’t send each key stroke immediately to the program. It waits, storing data in a buffer then when enter is hit, it sends all the data to the program. And that’s not C standard, but how it’s implement by the compilers. Regardless of the computer you use, there’s always the standard and what your computer and compiler will do. They aren’t always the same. Doesn’t matter what environment you’re working on.

And why EOF? It’s odd when the program is dealing with a characters from the keyboard. After all EOF means End of file? There’s no end on the keyboard. While I haven’t confirmed it, I know what’s happening. The getchar() function will work on any input that the standard I/O library can communicate with. Be that a keyboard or file or some other input device. On the mainframe it was easy to switch output to the console or a file or a printer. Same for inputs. It didn’t matter. The same processing was done and so a file does have an EOF marker. Use that.



Exercise 1-6. Verify that the expression getchar() != EOF is 0 or 1.

Exercise 1-7. Write a program to print the value of EOF.

Part 1: Test if EOF is 0 or 1.

Sample code.

// The standard library includes the system function.
#include <cstdlib>

// C++ standard I/O library
#include <cstdio>

int main()
{

// Use EOF value as condition.
if (EOF)
printf("EOF is true therefore non-zero.\n");
else
printf("EOF is false therefore equal to zero.\n");

// Test if EOF is 0.
if (EOF == 0)
printf("EOF equals zero.\n");
else
printf("EOF doesn't equal zero.\n");

// Test if EOF is 1.
if (EOF == 1)
printf("EOF equals one.\n");
else
printf("EOF doesn't equal one.\n");

// Test if EOF is positive.
if (EOF >= 0)
printf("EOF is positive.\n");
else
// Note, we already know it's not zero.
printf("EOF is negative.\n");

// This code shows it's neither zero or one.

// Display EOF
//

// printf("EOF is " + EOF);
// error C2664: 'printf' : cannot convert parameter 1 from 'System::String ^' to 'const char *'
printf("EOF is ");
putchar(EOF);

// putchar("\n");
// error C2664: 'putchar' : cannot convert parameter 1 from 'const char [2]' to 'int'
// "\n" is a string, not a character
// use single quotes for a character as in '\n'
putchar('\n'); // works

// keep console window open
system("pause");

// return some value
return 0;

}

Here’s the console window:


Part 2: Test if EOF is 0 or 1.

Sample code.

// The standard library includes the system function.
#include <cstdlib>

// C++ standard I/O library
#include <cstdio>

int main()
{

// Test getchar() != EOF is 0 or 1.
//

// Use getchar() != EOF value as condition.
if (getchar() != EOF)
     printf("getchar() != EOF is true therefore non-zero.\n");
else
     printf("getchar() != EOF is false therefore equal to zero.\n");

// Test if getchar() != EOF is 0.
if ((getchar() != EOF) == 0) 
     printf("getchar() != EOF equals zero.\n");
else
     printf("getchar() != EOF doesn't equal zero.\n");

// Test if getchar() != EOF is 1.
if ((getchar() != EOF) == 1)
     printf("getchar() != EOF equals one.\n");
else
     printf("getchar() != EOF doesn't equal one.\n");

// Test if getchar() != EOF is positive.
if ((getchar() != EOF) >= 0)
     printf("getchar() != EOF is positive.\n");
else
     // Note, we already know it's not zero.
     printf("getchar() != EOF is negative.\n");

// keep console window open
system("pause");

// return some value
return 0;
}

Because the getchar() function is invoked, the program requires some keystrokes—hit space four times then enter.


1 comment:

  1. Thanks for this.
    It realy helped for the putchar('\b')

    keep it up.

    ReplyDelete