Controlling getchar() in while loop - c

Say I have a simple while loop to enter **1*0* characters.
After more than 10, I want the loop to stop.
However, the break seems not to take effect.
Only when I press Enter it ends. Can anyone explain please?
int count = 0;
int numchars = 10;
ch = getchar();
while( ch != '\n' && ch != '\0' ) {
array[count] = ch;
count++;
if ( count > numchars ){
break;
}
ch = getchar();
}
Thanks.

stdin is not your tty, even when your tty is connected to stdin. Unless you put your tty in raw mode, the program does not see any data at all until you hit return. When you hit return, all of the data on the line is sent to the program, which then enters the loop and reads characters until it breaks out of the loop. If you really want the program to see characters as you press them, you will need to do a lot more work. Look into libraries like ncurses first, and then do some research on how to put a tty into raw mode. And then write the simple program that requires the user to hit return.

use getch() or getche() instead of getchar() and numchars=9 for 10 characters.

Related

How to echo stdin to stdout

it's a very simple question, how to echo every char that I type in stdin to stdout? I'm trying to do it for a long time and I've tried many ways and no one works well. The best I could do was to get what I typed after application end.
The best I did was:
#include <stdio.h>
int main()
{
while (1)
{
int ch = getc(stdin);
if(ch == EOF) break;
putc(ch, stdout);
}
return 0;
}
Thanks.
You need to flush the stdout:
int main()
{
while (1)
{
int ch = getc(stdin);
fflush(stdout);
if(ch == EOF) break;
putc(ch, stdout);
}
return 0;
}
The code you have should work just fine, as long as you hit enter. In most systems, the program will get input in a line oriented fashion. If you want to echo the key immediately after it is hit, you will need to change the input method for the program. On many systems, this would be getch(), but there may be other requirements you have to satisfy before you can use the interface (ncurses requires some additional setup, for example).
When echoing the data immediately after the key is hit, you will be required to flush the output in some way. If you are sending the output to stdout, then a call to fflush() will work. If you are using some system specific output command, you may be required to call some kind or window refresh routine.
I wonder if a better way would be:
int ch;
while((ch = getchar()) >= 0)
{
putchar(ch);
}
Then if you call this:
echo this is my input | ./myprogram
it would output the entire stdin this is my input without hitting the enter key.

Unable to print number of characters using getchar, in Ubuntu

I am new to C, and to Ubuntu. I wrote a very simple program to count the number of characters using while and getchar(). The program is:
#include <stdio.h>
main() {
int i;
int c= 0;
while ( ( i = getchar() ) != EOF ){
c++ ;
}
printf( "%d characters\n" , c) ;
return 0;
}
I saved it and compiled it using gcc c1.c -o c1. No errors reported. I executed the program using ./c1 . I give the input as daniweb then I press enter, but the count is displayed. What went wrong? Is it infinite loop? How does getchar() determine EOF when input is given from keyboard?
On the terminal you can send EOF to an application by pressing Ctrl+D. You can also do something like this:
echo "blablub" | ./yourprogram
To count how many characters are in blablub. In this case EOF is sent automatically.
Pressing enter sends a new line character to your program, not EOF. As others have mention already, use Ctrl+D to send EOF. If you want to stop reading characters on newline, change your while loop to this:
while ( ( i = getchar() ) != '\n' ){
c++ ;
}

Getting input in the if condition

#include <stdio.h>
// copy input to output
// my version
int main()
{
int c;
printf("\n\nUse CONTROL + D to terminate this program\n\n");
while ((c = getchar()) != EOF) {
putchar(c);
}
if ((c = getchar()) == EOF) {
printf("\n\nProgram TERMINATED\n\n");
}
return 0;
}
When I enter control + D, the body of the if statement runs. That's what I had wanted, but as I analyzed the code more thoroughly, shouldn't it ask for my input again since the if's condition is (c = getchar()) == EOF?
When you hit ^D, input to the program is closed, so getchar() will subsequently always return EOF.
Control-D is canonical mode end-of-file character. When entered at the beginning of a line it causes an EOF condition to be seen by the process, that is the read returns 0. However if if Control-D is entered somewhere other than the beginning of the line it just causes the read to return immediately with what has been input thus far.
If you hit Control-D twice in a row you should see what I think you asking about.
EDIT
Here is a pretty good explanation.
^D terminates the program instantly. Thus you're getchar would never return when ^D is hit.
That is why REPL like python exits using 'exit()'.
If you want, try to use 'q' for quiting:

count the number of lines, words, and characters within an input

Right now I am going through a book on C and have come across an example in the book which I cannot get to work.
#include <stdio.h>
#define IN 1
#define OUT 0
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
It's supposed to count the number of lines, words, and characters within an input. However, when I run it in the terminal it appears to do nothing. Am I missing something or is there a problem with this code?
The program only terminates when the input ends (getchar returns EOF). When running on terminal, this normally never happens and because of this it seems that the program is stuck. You need to close the input manually by pressing Ctrl+D (possibly twice) on Linux or pressing F6 and Enter at the beginning of the line on Windows (different systems may use different means for this).
It's waiting for input on stdin. Either redirect a file into it (myprog < test.txt) or type out the data and hit Ctrl-D (*nix) or Ctrl-Z (Windows).
When you run it, you need to type in your text, press return, then type Ctrl-d and return (nothing else on the line) to signify end-of-file. Seems to work fine with my simple test.
What it is doing is entering a loop for input. If you enter a character or newline, nothing happens on the screen. You need to interrupt the process (on my Mac this is CTRL+D) which serves as EOF. Then, you will get the result.
getchar() returns the input from the standard input. Start typing the text for which you want to have the word count and line count. Your input terminates when EOF is reached, which you do by hitting CTRL D.
CTRL D in this case acts as an End Of Transmission character.
cheers
I usually handle this kind of input like this (for Linux):
1. make a file (for example, named "input.txt"), type your input and save
2. use a pipe to send the text to your application (here assume your application named "a.out" and in the current directory):
cat input.txt | ./a.out
you'll see the program running correctly.

Why does this getchar() loop stop after one character has been entered?

#include <stdio.h>
int main() {
char read = ' ';
while ((read = getchar()) != '\n') {
putchar(read);
}
return 0;
}
My input is f (followed by an enter, of course). I expect getchar() to ask for input again, but instead the program is terminated. How come? How can I fix this?
The Terminal can sometimes be a little bit confusing. You should change your program to:
#include <stdio.h>
int main() {
int read;
while ((read = getchar()) != EOF) {
putchar(read);
}
return 0;
}
This will read until getchar reads EOF (most of the time this macro expands to -1) from the terminal. getchar returns an int so you should make your variable 'read' into an integer, so you can check for EOF. You can send an EOF from your terminal on Linux with ^D and I think on windows with ^Z (?).
To explain a little bit what happens. In your program the expression
(read = getchar()) !='\n'
will be true as long as no '\n' is read from the buffer. The problem is, to get the buffer to your program, you have to hit enter which corresponds to '\n'.
The following steps happen when your program is invoked in the terminal:
~$\a.out
this starts your program
(empty line)
getchar() made a system call to get an input from the terminal and the terminal takes over
f
you made an input in the terminal. The 'f' is written into the buffer and echoed back on the terminal, your program has no idea about the character yet.
f
f~$
You hit enter. Your buffer contains now 'f\n'. The 'enter' also signals to the terminal, that it should return to your program. Your progam
reads the buffer and will find the f and put it onto the screen and then find an '\n' and immediatley stop the loop and end your program.
This would be standard behaviour of most terminals. You can change this behaviour, but that would depend on your OS.
getchar() returns the next character from the input stream. This includes of course also newlines etc. The fact that you don't see progress in your loop unless you press 'Enter' is caused by the fact that your file I/O (working on stdin) doesn't hand over the input buffer to getchar() unless it detects the '\n' at the end of the buffer. Your routine first blocks then handles the two keystrokes in one rush, terminating, like you specified it, with the appearance of '\n' in the input stream. Facit: getchar() will not remove the '\n' from the input stream (why should it?).
after f you are putting "enter" which is '/n'.
so the loop ends there.
if you want to take another character just keep on putting them one after the other as soon as enter is pressed the loop exits.
You've programmed it so the loop ends when you read a \n (enter), and you then return 0; from main which exits the program.
Perhaps you want something like
while ((read = getchar()) != EOF) {
putchar(read);
}
On nx terminals you can press Control-D which will tell the tty driver to return the input buffer to the app reading it. That's why ^D on a new line ends input - it causes the tty to return zero bytes, which the app interprets as end-of-file. But it also works anywhere on a line.

Resources