-1

I have a simple program (based on example from The C programming language ed. 2 section 1.5.2 book) for characters counting. The program itself is very simple, however I am no getting the expecting results.

It seems that numberOfChars is incremented twice and I do not not why...?

I am using cygwin + gcc compiler, please see the image: compilation+test

int main () {   
    int numberOfChars;  

    for(numberOfChars = 0; getchar() != EOF; numberOfChars++) 
        ;   //null statement

    printf("Number of chars = %d\n", numberOfChars);

    return 0;
}

Thanks for any help :-)

hyde
  • 60,639
  • 21
  • 115
  • 176
Pavel
  • 21
  • 2
    For an empty statement use `{}` instead of `;`. Because `;` right after a `for` loop may seem like a typo, and when it is a type it's a very complicated bug for this reason some compilers will issue a warning with your code. Please post the input, the actual result and the desired result. – Iharob Al Asimi Feb 07 '16 at 12:53
  • 3
    Please don't post text as images. Instead, copy/paste the text into the question. – fuz Feb 07 '16 at 12:54
  • 1
    @Pavel getchar reads all characters including the new line character. So if you pressed Enter then '\n' was also counted. – Vlad from Moscow Feb 07 '16 at 12:55
  • 3
    @iharob Taken from aforementioned book: "The body of this for loop is empty, because all of the work is done in the test and increment parts. But the grammatical rules of C require that a for statement have a body The isolated semicolon,called a null statement, is there to satisfy that requirement. We put it on a separate line to make it visible. " – Pavel Feb 07 '16 at 13:01
  • @Pavel I understand that, I am not telling you not to do it. Just to avoid the possible confusion, `{}` looks more intentional than `;`. – Iharob Al Asimi Feb 07 '16 at 13:07
  • 3
    @iharob: I for one disagree. The standard notation for an empty loop body is a semicolon on a line on its own. The empty braces look weird. And I refer to the original documentation of the C language for support — The C Programming Language by the ineffable K&R, Kernighan and Ritchie. – Jonathan Leffler Feb 07 '16 at 16:21
  • @JonathanLeffler The `{}` is suggested for an `if` statement where an empty statement would not make sense, but in this case I can see how you are 100% right. – Iharob Al Asimi Feb 07 '16 at 16:27
  • @iharob: I very seldom have an empty statement after an `if`, if only because by inverting the condition there is no need for it. That would be a 'code smell'. – Jonathan Leffler Feb 07 '16 at 16:33

2 Answers2

0

To get a 3, you can write:

#include <stdio.h>

int main () {
        int numberOfChars = 0;

        do {
                while(getchar() != '\n')
                        numberOfChars++;
        } while(getchar() != EOF && numberOfChars++);

        printf("Number of chars = %d\n", numberOfChars);

        return 0;
}

Then press Ctrl + D to exit the nested loop.

In fact, your program is correct. It gave you 6 because you've entered 6 characters: 1, \n, 2, \n, 3, \n.

nalzok
  • 14,965
  • 21
  • 72
  • 139
  • 1
    That is inscrutable code, not helped by omitting the braces around the body of the outer `do … while` loop. If the loop body is itself a compound statement (anything more complex than an assignment or function call) use the braces. I can see how the code works. I'm not sure the code is a useful modification. It also doesn't count the extra newline, so it gives the wrong answer. Sending an EOF indication to the code sends it into a tizzy too. – Jonathan Leffler Feb 07 '16 at 16:29
  • @JonathanLeffler Improved, looks better? – nalzok Feb 07 '16 at 16:43
  • 1
    Calling getchar more than once like that is non-idiomatic C, the questioner simply needs to run the program on a file, which he can inspect with something like `od -c` to avoid confusion – Rob11311 Feb 07 '16 at 19:01
  • Looking at the original code, I would have used a single while loop instead of the `for` loop; the increment would be the body of the while loop. Other than that, it is fine, and was giving the correct answer because the input consisted of three digits and three newlines. The main problem was understanding the newlines are characters. – Jonathan Leffler Feb 09 '16 at 04:24
  • The double loop still makes this code harder to understand by quite a margin than the original code. The inner loop eats characters up to and including a newline, though it doesn't count the newline. It then reads the first character of the next line and jumps back to the inner loop after incrementing the count. If the next line happened to be empty (the next character after one newline is a second newline), the second newline would be counted — so this code counts characters except for newlines, except that when there are two newlines in a row, it counts the second one. Tricky indeed! – Jonathan Leffler Feb 09 '16 at 04:26
0

Create a file, then run the cygwin od program, followed by a run of the example C program :

od -x < testfile
a.out < testfile

Then you can see what & how many characters you had exactly in the file and avoid surprises.

As a debugging aid, if I suspected something was wrong, I'd add something like :

int c; for(numberOfChars = 0; (c = getchar()) != EOF; numberOfChars++) 
    printf( "\0x%x", c);

To understand the processing my code was doing.

Rob11311
  • 1,396
  • 8
  • 10