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.
Related
#include <stdio.h>
int main(void)
{
char ch;
setbuf(stdout, NULL);
while ( (ch = fgetc(stdin) ) != '\n' && ch != EOF){
fputc(ch, stdout);
fflush(stdout);
};
return 0;
}
Why I see is not a character to enter a character on the console, but in the press the Enter key together after all the output, the key is that I close the output buffer and refresh the output buffer.
By default, terminals are in canonical mode, where the input is passed to the program only when a line delimiter (newline, end of input at the start of a line, and so on) is typed.
The way to manipulate the terminal -- for example, to get keypresses immediately when they occur -- varies between operating systems. The Curses libraries (PDCurses for Windows, ncurses for just about all others) hide the differences under a single interface, so you might wish to look into that.
I have a C console application under Linux (Raspbian - Raspberry Pi). The program has some character animation - it prints out messages character by character. For example, the text
Please give me your name!
is printed out completely after 5 seconds (char by char).
Afterwards, the user is asked to type in their name, which works just fine if the user waits for the message to be printed out. However, if the user is impatient and hits the keys on the keyboard randomly, the input request later is compromised.
Imagine the user types in
abc\nefgh\n
while the above text is being echoed ('\n' means new line - enter). If that happens, the user will not be asked to properly type in his/her name, but the array of characters 'abc' will be accepted as input and gets validated.
My question is how to disable input (buffering) temorarily (on Linux). I have tried several methods and read numerous posts about doing so, but none of them worked for my purpose.
The function that is responsible for asking for input is as follows:
int getLine(char *s, int length)
{
int i;
char c;
for (i = 0; i < length && (c = getchar()) != EOF && c != '\n'; i++)
{
if (c == '\0')
{
i--;
}
else
{
s[i] = c;
}
}
s[i] = '\0';
while (c != EOF && c != '\n')
{
c = getchar();
}
return i;
}
Empty lines are eliminated with the help of a while loop in the function calling the one above so enter inputs are considered invalid.
I tried closing stdin, but could not reopen it:
fclose(stdin);
and emptying buffer before the getLine:
char buf[BUFSIZ];
while (c = fgets(buf, BUFSIZ, stdin) != NULL);
Unfortunately, it did not work as it does with text files.
fflush(stdin); did not work either and is not pretty anyway.
My goal is to prevent users from typing in anything while the text is being written out and to ignore/close input buffering (stdin) temporarily. Also, it would be great to disable outputting (flushing) user inputs during printing as it gets displayed on Linux terminal.
You may do this by interacting with TTY directly. Look into source code of passwd or similar utilities for inspiration.
Function below clears TTY input buffer (error handling omitted). You need to call it just before reading user input.
#include <sys/ioctl.h>
#include <termios.h>
void clear_user_input() {
if (isatty(STDIN_FILENO)) {
int fd = open(ttyname(STDIN_FILENO), O_RDONLY);
ioctl(fd, TCFLSH, TCIFLUSH);
close(fd);
}
}
I want to read input from user. After the user typed the sequence ::, the rest of the input should be asterisks.
For example: let's say user typed: Alex::vn800. On the screen, the output should be: Alex::*****.
I have a function that reads input from user and display * on screen, but I didn't managed to use it in a middle of reading line.
I tried to manipulate functions getchar() and scanf() to stop reading line after detecting a sequence of ::, and then call the function but nothing worked.
What can I do?
Update: Hey! thanks for the answers.
I fainlly solved the problem by using the library conio.h - like in any other simple get-password code, just that I saprated it for cases according to what I want the screen will show and not just '*' for any case.
If it's not strictly necessary to have both username and password in the same line, I would suggest simply getting the username first and then using the getpass() function, like here.
I've tried ataman's method, but it didn't work on OSX 10.9.
Here's a modified version, following goldPseudo's approach:
#include <stdio.h>
#include <stdlib.h>
int main() {
int readChar;
int status = 0;
int semicolonCount = 0;
system ("/bin/stty raw"); // disable buffering and other stuff
while ((readChar = getchar()) && (readChar != 13 /* ENTER keycode */))
{
if (status == 0)
{
printf("%c", readChar);
if (readChar == ':')
{
semicolonCount++;
} else {
semicolonCount = 0;
}
if (semicolonCount == 2)
{
status = 1;
}
} else {
printf("*");
}
}
printf("\r\n"); // print new line
system ("/bin/stty cooked"); // reenable buffering, might not be the original mode the terminal was in
return 0;
}
The problem with this approach is that, since you are in "raw mode", special characters, like BACKSPACE, ENTER, Ctrl+D and even Ctrl+C, are not processed.
You would have to implement the behaviour for those characters yourself.
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.
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.