Cprog Assignment2 Tricky Stuff

Collection of tricky stuff I encountered during C Programming Assignment #2 (HW2-*)

Checking for EOF. What's wrong with this code?

char c;
while((c = getchar()) != EOF) …

CORRECT WAY:
int c;
while((c = getchar()) != EOF) …

Explanations:
http://www.cs.tau.ac.il/~efif/courses/Software1_Spring_03/practices/practice3.php
http://c-faq.com/stdio/getcharc.html

EOF Flag (win vs. linux)

When you run the character copying program, and it begins copying its input (your typing) to its output (your screen), you may find yourself wondering how to stop it. It stops when it receives end-of-file (EOF), but how do you send EOF? The answer depends on what kind of computer you're using. On Unix and Unix-related systems, it's almost always control-D. On MS-DOS machines, it's control-Z followed by the RETURN key. Under Think C on the Macintosh, it's control-D, just like Unix. On other systems, you may have to do some research to learn how to send EOF.

http://www.eskimo.com/~scs/cclass/notes/sx6b.html

Note: On my Windows XP the ctrl-z didn't behave same as in the Eclipse Console and linux1 Bash Shell
Environment with the following line of code:

scanf(" %c %d %d", &tableMarker, &rows, &columns)

on WinXP in a cmd.exe shell i have to press ctrl-z/enter 4 times whereas in the eclipse console and
linux bash shell just works. Well, cmd.exe never was a real shell :)

getchar waits until a whole line (with ENTER at the end) is typed,

int getchar(void) include: <stdio.h> Reads a single character from the standard input stream (stdin). returns the ASCII code (*) of the next available character. If no characters are currently available, it waits until one is typed. (In fact, it waits until a whole line (with ENTER at the end) is typed, otherwise the backspace key would be useless). Returns the value EOF (which is -1) if end-of-file is reached. Note is you store the result of this function in a char variable instead of an int you may have trouble detecting end-of-file. To type end-of-file on the keyboard, under unix (most shells) type control-D. Under DOS or windows or the Bourne shell for unix, type control-Z. Control characters are interpreted correctly: when newline/ENTER is typed, the return value is '\n', which is 10. Backspace, Delete, and Control-C, etc, can not be read by getchar, as they are processed by the operating system before the line of input is made available to user programs.

Observations

It's interesting that also files without an explicit newline contain an implicit newline character.

b96123@linux1:~/workspace> xxd test.txt
0000000: 6c69 6e65 5f77 6974 686f 7574 5f6e 6577 line_without_new
0000010: 6c69 6e65 0a line.
b96123@linux1:~/workspace> more test.txt
line_without_newline

In fact the file test.txt consists of only one line without an explicit newline.

If I really enter a newline after the line of text then the file consists actually of two newlines.
b96123@linux1:~/workspace> xxd test2.txt
0000000: 6c69 6e65 5f57 4954 485f 6e65 776c 696e line_WITH_newlin
0000010: 650a 0a e..
b96123@linux1:~/workspace> more test2.txt
line_WITH_newline

[EOF]

Problem cases

The console window in Eclipse in Debug mode (gdb) and in the normal program execution mode behaves differently. Windows Shells (ctrl-z and enter) and UNIX Shells (ctrl-d without enter) also behave differently. IMHO the best way to test a program which reads input from stdin is:

./program < input.txt

Sample Code to process text files when the last line is terminated by EOF (i.e there is no implicit newline after the last line of input)

getchar / ungetc

...
    while( (inputChar = getchar()) != EOF) {
 
        // If the current char is a newline we must call getchar 
        // again to get the next number
        // Also catches the CR+LF case 
        if( inputChar == '\r') {
            inputChar = getchar();
        }
        if( inputChar == '\n') {
            inputChar = getchar();
        }        
        ungetc(inputChar,stdin);
        scanf("%d", &numberOfNumbersToRead);
        getchar(); // skip newline
      ...
    }

scanf

Input consists of 3 numbers per line:
1 2 3
4 5 6EOF

...
    while( scanf("%d %d %d", &a, &b, &c) == 3) {      
       .. 
    }
...
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License