LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-07-2003, 12:20 PM   #1
NSKL
Senior Member
 
Registered: Jan 2002
Location: Rome, Italy ; Novi Sad, Srbija; Brisbane, Australia
Distribution: Ubuntu / ITOS2008
Posts: 1,207

Rep: Reputation: 47
getchar()


Im learning C (yes again!) and by following some examples in the book, i wrote two programs (exactly the way they are in the book) but im not happy with their output. Here are the programs, they should be self explanatory:

#include <stdio.h>

/* Count lines in input */
main ()
{

int c, nl;

nl = 0;
while ((c == getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
}

and the second one

/* Count characters in input, 1st version */

#include <stdio.h>

main ()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}


They compile ok, but the printf() lines are never executed. This is waht i get when pressing random keys (and enter) while running the program:

|:-(Tue Jan 7 16:26:39)-(nskl@Slackbox:~)$ ./a.out
d
f
dgf
h

hj
f
dsf
z

and i have to ctrl-C out of it. So how do i get out of getchar(), i thought it was like with scanf() when i press enter the program flows on. Im confused yet again why printf() line is never executed, or how to send EOF to getchar() so the program can flow on.
Thanks
-NSKL

Last edited by NSKL; 01-07-2003 at 12:27 PM.
 
Old 01-07-2003, 01:04 PM   #2
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985
well you have a while loop that just loops... there's no block - { and } to contain the acutal instructions, so it's jsut the ++nc that's being exectued infinitely.
 
Old 01-07-2003, 01:06 PM   #3
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Code:
while ((c == getchar()) != EOF)
This line should read:
Code:
while ((c = getchar()) != EOF)
/* One '=' less  before getchar() */
This could explain why the loop doesn't end. However the second program looks correct to me.

Anyways you will need to know how to have the program read an EOF.

Three ways to do this:

(1) Send a text file through a pipe to your a.out, instead of pressing keys after running your a.out. After the whole file is processed by your program, an EOF is sent automagically:

$ cat /etc/passwd | ./a.out

(2) Run ./a.out like you have done already and press CTRL-d when done entering text. CTRL-d sends an EOF.

(3) Use the shell contruction called "here document":

$ ./a.out << QQQ
this is the text you
are typing to get it processed
by your program
QQQ

Good luck!
 
Old 01-07-2003, 01:10 PM   #4
moses
Senior Member
 
Registered: Sep 2002
Location: Arizona, US, Earth
Distribution: Slackware, (Non-Linux: Solaris 7,8,9; OSX; BeOS)
Posts: 1,152

Rep: Reputation: 50
Oh, boy. . .

Ok, first, you don't really have a while *LOOP*, you have a
single while statement. You need to enclose the statements in
curly brackets
while (getchar() != EOF)
{
++nc;
printf("%ld\n", nc);
}

However, getchar() doesn't really seem to be what you want.
Using getchar(), you get the following output from the above
code:

./countc
a
1
2
b
3
4
c
5
6
d
7
8

This is because you are reading in two characters ("a\n" is not a
single character), and so it increments nc twice.

for the countlines, you have several problems:
You don't want c to be an int, you're checking to see if c is
equal to the output of getchar, so you never actually assign a
value to c, so checking to see if c is the new line character
doesn't ever work (unless you happen to hit a memory spot
that causes this to come true).

Just some hints. . . Get a different book.

Last edited by moses; 01-07-2003 at 01:11 PM.
 
Old 01-07-2003, 01:10 PM   #5
moses
Senior Member
 
Registered: Sep 2002
Location: Arizona, US, Earth
Distribution: Slackware, (Non-Linux: Solaris 7,8,9; OSX; BeOS)
Posts: 1,152

Rep: Reputation: 50
damn!
hungry kid caused me to be late in posting. . .
=-}
 
Old 01-07-2003, 01:11 PM   #6
kolargol
Member
 
Registered: Jan 2003
Posts: 56

Rep: Reputation: 3
try typing ctrl-d, this is equivalent to end of file, it should stop the loop
 
Old 01-07-2003, 01:18 PM   #7
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Ok, first, you don't really have a while *LOOP*, you have a
single while statement. You need to enclose the statements in
curly brackets
No, not necessarily. If there is only one statement in the while loop (and that the case here), it's OK to not have the curly brackets. Same goes for the if statement inside the while in the first code.

The code listings are correct. Except for one '=' too much (see my first reply)

Quote:
You don't want c to be an int [..snip..]
Not true. Actually an int is more correct here, for getchar() does return an int, not a char. See the man page.

Last edited by Hko; 01-07-2003 at 01:19 PM.
 
Old 01-07-2003, 01:42 PM   #8
NSKL
Senior Member
 
Registered: Jan 2002
Location: Rome, Italy ; Novi Sad, Srbija; Brisbane, Australia
Distribution: Ubuntu / ITOS2008
Posts: 1,207

Original Poster
Rep: Reputation: 47
Ah! Now im so lost, some people say one thing, others say other. The book is K&R "The C programming Language" Anyway i will revise my programs according to your suggestions and i'll try figuring the rest by myself, and whoah! 6 replies in less than an hour.
I really appreciate your help everyone
thank you
-NSKL

EDIT: I did as suggested and now the programs work the way they should, but damn, K&R is supposed to be a good book, but if examples in it dont work that makes it, lets put it, "less good". And just not to make a fool of myself, i checked for 50th time, and the programs are written in the book the way i posted them above, except a double == on one place.
Thank you again everyone
-NSKL

Last edited by NSKL; 01-07-2003 at 01:51 PM.
 
Old 01-07-2003, 02:01 PM   #9
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985
maybe it was a test...?
 
Old 01-07-2003, 02:24 PM   #10
NSKL
Senior Member
 
Registered: Jan 2002
Location: Rome, Italy ; Novi Sad, Srbija; Brisbane, Australia
Distribution: Ubuntu / ITOS2008
Posts: 1,207

Original Poster
Rep: Reputation: 47
Dont think so, it introduces new concepts in the program, and its on the beggining of the book (page 19).
Still i read another C book, "C for absolute beginners" and although K&R book is much more complex, packs more knowledge in less pages, i find it very good. It also gives Exercises so you can test what you have learned. But i immgine you already have this book so theres no point describing it.....
Thanks again
-NSKL
 
Old 01-07-2003, 03:40 PM   #11
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
K&R is supposed to be a good book, but if examples in it dont work that makes it, lets put it, "less good".
Just don't worry. There's nothing wrong with the book. It's K&R for heaven's sake! And there's nothing wrong with the code examples. They work, right?

In fact it was just that you didn't know how to send an EOF from the shell.

K&R is a good book
 
Old 01-07-2003, 03:51 PM   #12
NSKL
Senior Member
 
Registered: Jan 2002
Location: Rome, Italy ; Novi Sad, Srbija; Brisbane, Australia
Distribution: Ubuntu / ITOS2008
Posts: 1,207

Original Poster
Rep: Reputation: 47
Are you trying to convince me or yourself
I like the book as i said in my previous post, it's just that the poor guys forgot a pair of {}, no biggie.
It's incredible how much stuff they packed in 250 pages. I read one section then take an hour to "digest" it then proceed. It'll take me forever to finish the book, but im sure it's worth it.
Thanks again for all the help
-NSKL
 
Old 01-07-2003, 06:30 PM   #13
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Are you trying to convince me or yourself
None of the above. :-) I'm really absolutely 100% sure.
This time I even pasted both your code examples into vi, removed the '=', compiled and ran them.

I even compared the output of the programs with the wordcount utility "wc", and your programs have the same result as:

$ wc -l /etc/passwd
$ wc -m /etc/passwd

Quote:
I like the book as i said in my previous post, it's just that the poor guys forgot a pair of {}, no biggie.
No, they didn't.
Third time: The code is correct.
So is this one (though stupid and useless: it just exits):
Code:
int main()
{
    while (1) while (1) while (1)
    if (1) if (1) return 0;
}

Last edited by Hko; 01-07-2003 at 06:47 PM.
 
Old 01-08-2003, 01:35 PM   #14
NSKL
Senior Member
 
Registered: Jan 2002
Location: Rome, Italy ; Novi Sad, Srbija; Brisbane, Australia
Distribution: Ubuntu / ITOS2008
Posts: 1,207

Original Poster
Rep: Reputation: 47
Ok, sorry, i didnt realize.
I still don't understand tho.
This:

/* Count characters in input, 1st version */

#include <stdio.h>

main ()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}

and this


/* Count characters in input, 1st version */

#include <stdio.h>

main ()
{
long nc;
nc = 0;
while (getchar() != EOF) {
++nc;
printf("%ld\n", nc);
}
}

Are different, because the first one, which is exactly as in the book, does not report the characters in input, while the second one does, when { } is added. Now, the program is supposed to report characters in input, but the first one never does, because printf() is never executed, thus the example doesn't work.
Now im a newbie, so i might be well wrong like before, if so please correct me, and sorry for this wasting of your time.
Thanks
-NSKL
 
Old 01-08-2003, 06:08 PM   #15
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
I didn't realize that it still didnt work for you. Sorry, about that.
Like I said, I compiled them, and they both worked for me.

But there there is a difference between the two programs you listed in your last post. The output is different. Maybe you think the first is not working, because you expect a different output. It acutally does execute the printf() and outputs the number of characters.

I'll try to explain.
The first one counts all input character's in memory, using the variable nc. And only after reading all of the characters it outputs only one number, which is the number of counted characters.
It does not output anything as long the program did not read an EOF.
The second program outputs the number of characters after every line (when the <ENTER> key is pressed). And it does so, while counting.

Try changing the first program, to make its output more noticable:

printf("\n\nCounted %ld characters.\n\n", nc);

Use CTRL-d to send a EOF and see what happens. It has counted all characters you entered, but it outputs only one number. And that, I'm quite sure what the authors of the progam ment it to do.

There is a utility on your linux system called "wc" (WordCount), which can be used to count character, words, lines and the longest line, depending on the switches you give it on the command line.

Maybe the effect of the program is more clear to you when you have these programs count characters/lines from a file. Then do the same with "wc -m" to compare the results. Here's the shell session I am talking about on my computer:
Code:
$ cat /etc/passwd | ./a.out

Counted 1209 characters.

$ cat /etc/passwd | wc -m
      1209
So the file /etc/passwd contains 1209 characters.

If do the same with your version with the { } then it ouputs 1209 lines with increasing numbers from 1 to 1209. This is because that program outputs while counting.

The difference between the first and second program (of your last post) is that the printf() is included in the while loop!

To have both codes equivalent, the second one should read:
Code:
main ()
{
    long nc;
    nc = 0;
    while (getchar() != EOF) {
        ++nc;
    }
    printf("%ld\n", nc);
}
Note that the } is now above the printf(), and it works exactly the same as the version from the book, without { } . And I believe this is the way it K&R meant it to work.

In C, whitespace (space, tab, enter/return) don't make difference. So the following loops are equivalent:
Code:
    /* --1-- */
    while (getchar() != EOF) ++nc;

    /* --2-- */
    while (getchar() != EOF) 
        ++nc;

    /* --3-- */
    while (getchar() != EOF) {
        ++nc;
    }
There's one more thing to wonder about. With the printf() included in the while loop (your second code), one would expect it outputs the number of character directly after each character read. You anly notice this when you are typing the input into the program instead of feeding it the contents of a file with "cat", see above.

This doesn't happen because UNIX (and linux as well) buffer input by lines. So the terminal waits until it receives a linefeed (ENTER key) and the the terminal sends the whole line at once to your program.

This behaviour can be changed, from the shell as well as from a program, but that's quite beyond this subject.

I hope this help. Have fun!

Last edited by Hko; 01-08-2003 at 06:16 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
getchar() satellite Programming 10 12-24-2017 02:47 PM
getchar() question h/w Programming 3 12-23-2003 05:53 PM
about getchar() captainstorm Programming 6 10-11-2003 05:14 AM
getchar() not working? lackluster Programming 3 06-24-2002 09:09 AM
getchar() Winter Programming 6 05-11-2002 02:49 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:01 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration