Why does getchar() not work right? - c

Today, I wrote a simple piece of code that uses getchar() to count the characters you input. But when I compile it on Cygwin, it does not work. It always prints 0, but I never input anything or I can't input any characters it prints 0.
However, if I compile it with VC++6.0, it works.
#include<stdio.h>
int main(void)
{
long nc;
nc = 0;
while(getchar() != EOF)
++nc;
printf("The total of characters you inputed is %ld.\n", nc);
return 0;
}

This email thread talks about a bug that sounds much like yours, but I can't see that there are any follow-ups to it.
I would be interested to know what happened when you try
while(getc(stdin) != EOF)
and if that doesn't work, try
while(fgetc(stdin) != EOF)
All of them should work, though this page suggests there could be implementation differences between these functions.
Another thing you could try is to print the ASCII value of what you get:
printf("%d\n",(int)getchar());
Also, try piping output from a file instead of typing it in the console. Create a file input.txt, put some characters in it, and do
cat input.txt | ./program
EDIT: You write running cat and piping it works. I would say simply update your Cygwin version. You have encountered a bug. Get the newest versions of Cygwin and the compiler, and you should be good to go. Another option is to use scanf.

Related

Why some code examples from The C Programming Language book don't work as expected?

I'm trying to learn C Language, and I'm reading and testing a lot about it, but sometimes is difficult to understand why somethings just don't work as expected. Why the example code showed on page 18 of The C Programming Language, Second Edition (Kernighan and Ritchie), don't work? It doesn't show any results for me.
#include <stdio.h>
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf ("%ld\n", nc);
}
It doesn't show anything because it's waiting for input.
If you're running this like ./the_executable, it'll always be reading your input because of getchar(). And it'll show the results only after the input stream ends.
You can cut it off manually by pressing Control+D. Or use the contents of a file as input:
./the_executable < test_file.txt
The C Programming Language, Second Edition by Brian Kernighan and Dennis Ritchie is a very good book, but it is quite old and refers to an outdated definition of the C language. The program you posted uses an obsolete syntax for main. It should be modified as:
#include <stdio.h>
int main() {
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
return 0;
}
As you can see, the difference is minimal and in this particular case, the above version would also compile with the pre-ansi compilers in use at the time the book was written.
The program reads bytes from the standard input and just counts how many it could read before reaching the end of file.
You should run this program from a terminal window and type some data and signal the end of file by pressing Ctrl and D on unix systems such as linux and OS/X or Ctrl and Z followed by Enter on Microsoft systems.
You can also redirect input from a file and will get the number of bytes in this file, possibly adjusted on Microsoft systems due to line ending conversion.
Running the program directly from an IDE is not demonstrative because IDE's usually do not keep the terminal window open when the program exits, preventing the user from seeing the final output.
It should indeed work as expected.
The reason why you are confusing it with not working because you are expecting printf to print something for you (value of nc), but the catch is there is another statement getchar() before printf which is reading standard input with the help of while loop until you input EOF which is entered by ^D (control + D) in unix, like cat command if you used on *nix or by redirecting input to your program from a file using < operator, like
./a.out < someFile.txt
You have to enter the "end of file" condition. So ctrl Z or ctrl C should work.

Why I can't reach stdin at startup on Raspberry-Pi Jessie Lite?

I have this code. what I want to do is to wait for user to press 'q' to end the program.
.
...starting few threads, which use fflush(stdout) (just saying...)
.
char n = 0;
while (n != 'q') {
n = getchar(); //tried to use scanf() here as well
printf("%c", n);
}
...killing all threads...
return 0;
When I run this in a normal Linux enviroment it works fine.
The problem starts when I run this program at startup on my raspberry-pi with debian jessie lite distribution (I added the path to the program to /etc/rc.local) - it ends in an infinite loop, scanf is still returning -1 and getchar() some weird character and the program won't end, when I press q. Ctrl+C doesn't work either so there is no way, how to end the program.
Any suggestions? (at least how to kill the program...?)
Edit: To let you know what the program does.
Raspberry-pi with this program is attached to some serial ports and converts and transfers some GPS data. It should work "out of the box" without any keyboard or mouse or monitor. = Just plug the device to some cables and do nothing more. In some cases someone would like to see log files on the raspberry, so he needs to stop the program, obviously.
Edit2: when I did the same with some normal Raspbian, it worked fine too.
Update:
I tried to debug it - shrinked the code to this only
int main(void){
char n=0;
int x;
while (n != 'q'){
clearerr(stdin);
x=scanf("%c",&n);
printf("%c %d\n",n,x);
}
return 0;
}
added service start udev to rc.local and tried command update.rc.d udev enable
output on raspberry-pi when launched at startup is still
-1
-1
-1
.
.
so there definitely have to be something wrong with stdin.
After startup and on other systems, the output is obviously q 1 (when I press 'q' (and enter) ...)
when I tried to read from /dev/tty, fopen() returned NULL
Really need a help with this
The idiomatic way to write this loop is:
int c;
while ((c = getchar()) != EOF && c != 'q'){
putchar(c);
}
Your implementation cannot detect end of file and will loop forever, printing funny characters such as ÿ.
Just a wild guess that stdin maybe redirected to something else and you need to read from keyboard directly. try the following code:
FILE *tty = fopen("/dev/tty", "r");
if (!tty) {
exit(1);
}
int n=0;
while (n != 'q'){
n=fgetc(tty); //tried to use scanf() here as well
printf("%c",(char)n);
}

Character Counter from "The C Programming Language" Not Working As I Expected

I am reading through "The C Programming Language", and working through all the exercises with CodeBlocks. But I cannot get my character counter to work, despite copying it directly from the book. The code looks like this:
#include <stdio.h>
main(){
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
When I run the program, it opens a window I can type in, but when I hit enter all that happens is it skips down a line and I can keep typing, but I think it's supposed to print the number of characters.
Any idea what's going wrong?
This line:
while (getchar() != EOF)
means that it keeps reading until the end of input — not until the end of a line. (EOF is a special constant meaning "end of file".) You need to end input (probably with Ctrl-D or with Ctrl-Z) to see the total number of characters that were input.
If you want to terminate on EOL (end of line), replace EOF with '\n':
#include <stdio.h>
main(){
long nc;
nc = 0;
while (getchar() != '\n')
++nc;
printf("%ld\n", nc);
}
Enter is not EOF. Depending on your OS, Ctrl-D or Ctrl-Z should act as EOF on standard input.
I ran into the problem tonight, too. Finally found out that Ctrl-D on Linux worked. You build the source file using cc, and start the program and input a word, then press Ctrl-D twice when finished typing. The number that the program countered will be printed just behind the very word you just typed, and the program terminates immediately. Just like this:
The above answer provided by nujabse is correct. But recently coming across this issue myself and researching the answer, I would like to add why.
Using Ctrl+C tells the terminal to send a SIGINT to the current foreground process, which by default translates into terminating the application.
Ctrl+D tells the terminal that it should register a EOF on standard input, which bash interprets as a desire to exit.
What's the difference between ^C and ^D

count blanks from the input

I wrote a program to count blanks. I can compile it and run it, it's fine. But why it does not display the count?
#include<stdio.h>
main()
{
int count=0;
int c;
while((c=getchar())!=EOF)
{
if(c == ' ') count++;
}
printf("%d\n",count);
}
Your exact code (errors and all) works as you'd expect at ideone.
How do you terminate the input? To send an EOF signal to your program from the console type, at the beginning of a line, CtrlD in Linux or CtrlZ in Windows.
Also try to run with redirected input. Something like
yourprog < data.txt
or
echo one two three four | yourprog
You're probably not getting the EOF that you expect from input. You may be expecting the Enter key to be EOF, which will not happen. Have you tried using one of the ctrl+ combinations such as Z or D (depending on OS) to send the EOF ?

Help With K&Rs Counting Chars Example

I'm working my way through K&R's 2nd edition, and I've been stumped with this seemingly simple example:
#include <stdio.h>
main(){
double c;
for(c = 0; ((getchar() != EOF) && (getchar() != '\n')); ++c)
;
printf("%.0f\n",c);
}
It simply isn't working correctly. I added in the (getchar() != '\n') portion to end the program when I press enter, but that doesn't really help either.
Here's some sample output, using the gcc that comes with Mac OSX 10.6 dev tools.
pool-000:Desktop user$ ./a.out
a
0
pool-000:Desktop user$ ./a.out
asdf
2
pool-000:Desktop user$ ./a.out
asfasf
3
So something is obviously wrong. I'm on page 18, if that helps. This isn't homework, this is for fun!
Thanks :)
Each call to getchar() will wait for a character to be read, so you're reading more than you think per iteration of the loop.
Also, at least in my opinion, a counter is (almost) never a double, you should use an integer type such as plain old int.
The problem with doing two "getchar()" operations is that you will read TWO get chars in the conditional test... before you get to the ++c.
Ditch the "EOF" comparison and it should work as you expect.

Resources