0

I have experience in C++ so admittedly this shouldn't be too hard for me to understand but I guess it is. Im learning C from K&R's "The C Programming Language". I am performing this example from Chapter 1 Page 18, the example at the bottom of the page.

#include <stdio.h> 
int main(){
    double nc;
    for(nc = 0; getchar() != EOF; ++nc)
        ;
    printf("%.0f \n", nc);
    return 0;
}

I am redirecting input from the keyboard to instead be read from a text file (using the '<' when running a.out), and the text file has absolutely nothing in it, not even a newline character.

The program prints a 1. Shouldn't it be 0? Is there a character that is being read that isn't an EOF value? Or is the for loop executing its contents once, then increment by 1, then check the condition?

Thank you for the help!

Milly
  • 17
  • 2
  • 4
    can't reproduce https://ideone.com/jwgJCw. Your file is not empty. – Stargateur Jun 22 '17 at 19:51
  • "Is there a character that is being read that isn't an EOF value? " - if you suspect that, what's stopping you from doing something with the result of `getchar()` besides comparing to EOF and throwing it away? Instead, save it to a var, and do something useful like hex-rep print it in the otherwise-empty loop body you have currently. – WhozCraig Jun 22 '17 at 19:53
  • 2
    @SouXin that isn't true. The increment step never fires if the initial condition expression is false. And it only fires *after* the body (admittedly empty in this case) is iterated first. – WhozCraig Jun 22 '17 at 19:54
  • 2
    What does `wc -c filename` say? – Barmar Jun 22 '17 at 19:55
  • 2
    @SouXin You can't use a counter as the condition if the end condition is EOF, not a count. His loop syntax is perfectly fine. – Barmar Jun 22 '17 at 19:57
  • @SouXin you just pasted one of many reasons why cplusplus.com, in a word, *sucks*. That statement is *wrong*. The [description on cppreference.com](http://en.cppreference.com/w/cpp/language/for) is correct. – WhozCraig Jun 22 '17 at 19:58
  • If the standard input provided 0 characters then yes, the program would print 0. Since it prints 1 instead, it follows that there was one character in the standard input, not zero. If indeed the standard input was redirected from a file, then that file was not empty. Even if it contained no newline, perhaps it contained a space character or another non-printable character. – John Bollinger Jun 22 '17 at 20:00
  • 1
    In Unix *any* file that you create with any common text editor *will* have a sole new line. – Antti Haapala -- Слава Україні Jun 22 '17 at 20:03
  • What is the size of the file, as reported by a file browser tool? – Weather Vane Jun 22 '17 at 20:05
  • In this case it's more idiomatic to use a `while` loop. Because `for` should only be used when you know when the loop end. You can't know how many time `getchar()` return a valid character. But this don't mater. – Stargateur Jun 22 '17 at 20:06
  • @AnttiHaapala is that true of the much used Notepad++? Can Unix files have size 0? – Weather Vane Jun 22 '17 at 20:12
  • 1
    @AnttiHaapala I don't believe that's true. If you do `vi foo.txt` and just save and quit without doing anything else, it creates a file of 0 bytes. – lurker Jun 22 '17 at 20:32
  • Get a more recent book. K&R rev2 is outdated since 18 years. rev1 should be burried 10m below groundlevel. – too honest for this site Jun 22 '17 at 21:00
  • 1
    @Stargateur: That is disputable. I don't see a problem with the `for` loop. – too honest for this site Jun 22 '17 at 21:02
  • @Olaf this is a question of coding practice I don't want to start a war about this. An answer describe what I mean ["The main difference between the for's and the while's is a matter of pragmatics: we usually use for when there is a known number of iterations, and use while constructs when the number of iterations in not known in advance."](https://stackoverflow.com/a/2950945/7076153) – Stargateur Jun 22 '17 at 21:05
  • 1
    I can provide my test input file as well as my code file if needed. I don't know if there could be a character that I'm just not seeing that is being counted as not being EOF – Milly Jun 22 '17 at 21:21
  • 1
    @AnttiHaapala: I guess `vim` isn't a common editor, then — though it seems pretty commonly used to me. If I run `vim xx` (where there is no file `xx` in the current directory), and then use `:w` to write the file, it reports: `"xx" [New] 0L, 0C written`, and a subsequent `wc xx` reports `0 0 0 xx`, and `ls -l xx` reports `-rw-r--r-- 1 jleffler staff 0 Jun 22 14:25 xx`. That looks like an empty file to me, not a one-line file. – Jonathan Leffler Jun 22 '17 at 21:26
  • 3
    @MiliainareGryphon: You could change your loop to: `double nc; int c; for (nc = 0; (c = getchar()) != EOF; ++nc) printf("%d\n", c);` to see whether the loop body is run. Note that `getchar()` returns an `int`, not a `char`. – Jonathan Leffler Jun 22 '17 at 21:30
  • 1
    @Stargateur: That's why I wrote "disputable". If that was the wrong term, I appreciate a better one, I always like to learn. Point is such a comment was not helpful for exactly the reason itt is personal preference. – too honest for this site Jun 22 '17 at 21:36
  • 1
    The number of characters in a file is never a fractional value, so it would be better to use a long for nc. – stark Jun 22 '17 at 21:41
  • Something tells me your file has a newline. – cs95 Jun 22 '17 at 21:50
  • The most important thing you can do while *"learning C"* is to **enable compiler warnings** by including at minimum, `-Wall -Wextra` in your compiler string and then do not accept code until it compiles cleanly without warning. (that would most likely have solved your problem here) If not, and you still needed to debug further, See [**How to debug small programs**](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) and talk to the duck... – David C. Rankin Jun 22 '17 at 21:58
  • one good way to create an empty file on Linux at least is to use the `touch` command, i.e. `touch empty.txt; wc empty.txt 0 0 0 empty.txt` – bruceg Jun 22 '17 at 23:12

0 Answers0