Here is a loop that repeatedly gets two characters from stdin and outputs them.
char buf[2];
while (1)
{
printf("give me two characters: ");
fflush(stdout);
read(0, buf, 2);
printf("|%c%c|\n", buf[0], buf[1]);
}
The problem is that when the ENTER key is struck on the terminal, a newline character is inserted and remains in the stdin buffer, and will be grabbed on the next call to read. Ideally, I would like to have a clear stdin buffer ever time I call read, with none of the previous garbage left over. Can you recommend a good solution to this?
I have tried various library calls such as fgets, however they encounter the same issue. I was considering using fpurge to clear the buffer manually, but I was told this was not a good solution.
The issue here is that leftover input should be treated as garbage, and thrown away. However when I make the next call to read I have no way of distinguishing the leftover input from the new input.
Thanks for the input.
You can add getchar(); to read the more '\n':
#include <stdlib.h>
#include <stdio.h>
char buf[2];
main() {
while (1)
{
printf("give me two characters: ");
fflush(stdout);
read(0, buf, 2);
getchar();
printf("|%c%c|\n", buf[0], buf[1]);
}
}
give me two characters: ab
|ab|
give me two characters: xy
|xy|
Related
I wanna reproduce the terminal behavior when the input is just a new line (keeps printing the same string), but don't know how to do it.
Example: When the user just inputs a new line, the terminal keeps printing the directory, until a real command is inserted
int main()
{
char userInput[1024];
while (1)
{
printf("directory »» ");
scanf("%[^\n]" , userInput); // This scanf doesn't work
while (userInput[0] == '\n') // If the input is only a new line char, keep asking for more inputs and printing the directory
{
printf("directory »» ");
scanf(" %[^\n ]" , userInput); // This scanf doesn't work
}
//Input isn't a NewLine, process the input
process_Input_Function(userInput); //Isn't empty, search for my created commands
}
}
At the first enter press, it enters the loop, reproduce 1 time, and then the scanf doesn't detect new lines anymore, it just skips and waits to a real string.
What can i type inside of the scanfto detect a new line input and keep printing that string till a real command is inserted?
I tried with scanf("%c"...) but the problem with a char, is that i can't process the whole string command, if isn't empty
First of all, your two scanf calls are different. The first one is
scanf("%[^\n]", userInput);
which looks for anything that's not a newline, as you wish to do.
But the second one is
scanf(" %[^\n ]", userInput);
which is also looking for a space before the input, followed by any character that is also not a newline or a space. Thus, scanf is waiting for the space.
IMHO, the best way to recreate this behavior is going to be in the parsing step, after you have gotten the command from the command line. Essentially, your command input loop would look like this:
char *userInput = NULL;
size_t n = 0;
while (true) {
// print the prompt
printf(">");
// get the line
ssize_t userInputLength = getline(&userInput, &n, &stdin);
// parse the input, using a function you wrote elsewhere
parse(userInputLength, userInput);
}
(Note the use of POSIX getline() instead of scanf. This is a more recent standard library function that does exactly the task of getting a line of user input, and also allocates the buffer using malloc and realloc so that you don't have to care about buffer overflows or even sizing the buffer at all.)
The user input function wouldn't care that the userInput portion was blank. The function that would care is the parse function, which will simply interpret a blank userInput string as "do nothing" and continue on its merry way.
Hmm, the code I gave pretty much does that with one exception, it doesn't display a prompt each time...
Is this what you mean:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // For the memset()
int main() {
char userInput[1024];
while (1) {
printf("»»» ");
fgets(userInput, 1024, stdin);
while (userInput[0] == '\n')
{
printf(">>> ");
memset(userInput, '\0', 1024);
fgets(userInput, 1024, stdin);
}
// Your command can be accessed from here //
printf("Command entered: %s\n", userInput);
printf("Input isn't a NewLine\n");
}
}
I changed the scanf() to fgets() to read from stdin so that we don't overwrite the buffer.
so I was messing with the read functions fgets and scanf and with the printing functions write and printf with the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
printf("Enter an integer: ");
int n = 0; scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
char buffer[200];
read(0,buffer,200);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
fgets(buffer,200,stdin);
write(1,buffer,200);
return 0;
}
I would get these errors:
1-After the first scanf, it won't just show me the message to input the string.
2-What I write now it's what it's going to be saved in the string.
3-It will skip the last fgets...
An example of output:
Which doesn't make any sense at all; I would like to get an output like this:
Enter an integer: 15
The input number is: 15
Please enter a string now: This is the message1
The input string is: This is the message1 which is: This is the message1
Now please enter another message: This is the message2
This is the message2
Thanks for your help!
Interesting question. Mixing standard I/O (scanf(), fgets()) and file descriptor I/O (read()) on the same underlying file descriptor (0 aka standard input; stdin as a file stream) is at best problematic. You will get odd-ball effects.
At the file stream level, there is some synchronization between stdin and stdout when the input comes from a terminal; pending output on stdout is often flushed by the library. When you use read(), there is no such synchronization. That's why the prompt doesn't appear until after you hit return.
When you type 1 for the number, you also supply a newline. Standard I/O buffers the newline; it is kept so that the next file stream operation can read it. Then you read a line with read(). This does not know about the standard I/O buffer, so it waits for a new line of input from the terminal. You need to capture how much data was read because the input was not null terminated; that's a service provided by the standard I/O library, not the low-level read() function.
When you then call fgets(), it reads the newline that was buffered (not processed by scanf() when reading the integer) and returns with the empty line.
Note that if you had any buffered output waiting on standard output (e.g. you had used printf("Beginning of line: "); with no newline), then the output from write() would appear before the information buffered on stdout.
Using fread() and fwrite() would give you direct binary I/O (no null termination, for example), but would use the same I/O buffers as functions such as printf() and fgets(). You get hybrid behaviour when using these — it is normally best to use either fread()/fwrite() or the text I/O functions on a single file stream, and not both, but mixing them is permissible, relatively simple to understand, and occasionally useful.
So, what you see is all explainable, but it is hard work doing the explaining. It is also a clear indication of why you should not, in general, mix file stream and file descriptor I/O on the same underlying file descriptor — especially not standard input.
Why not use scanf with some better formatting:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
int n, i;
char buffer[200], ch;
printf("Enter an integer: ");
scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
scanf(" %[^\t\n]s",buffer);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
scanf(" %[^\t\n]s",buffer);
printf("%s", buffer);
return 0;
}
read(0,buffer,200);
reads up to 200 characters but it won't add a terminating null character to buffer. Hence the following call to printf results in undefined behavior.
You need to add code to capture the return value of the function and make sure to null terminate the string.
int n = read(0, buffer, 199); // Leave one for the terminating null character
if ( n == -1 )
{
// Deal with the error.
}
else
{
// null terminate the string.
buffer[n] = '\0';
}
I was always bad at inputting characters in C and this is another example. Though I understood (maybe) what's happening but I can't figure out the solution.
I have the following code
scanf("%ld %ld",&n,&m);
for(i=0;i<n;i++)
scanf("%ld",&array[i]);
for(i=0;i<m;i++)
{
fflush(stdin);
//inputting a character 'R' but it is picking '\n' from past buffer
scanf("%c",&query);
//As a result of above problem, it is also acting wierd for same reason
scanf("%ld",&d);
printf("%c %ld",query,d);
printf("\nI=%ld\n",i);
}
Please help me figure out the reason why its happening and what is the solution.
Using scanf with %d (or %ld) only extracts the number from the input stream; it leaves the newline in the stream.
So when you write scanf("%c", it reads that newline.
To fix this (if your intent is that scanf("%c" reads the first character of the next line), you need to flush the input of the previous line. One way to do that is:
int ch; while ( (ch == getchar()) != EOF && ch != '\n' ) { }
Your line fflush(stdin); causes undefined behaviour - don't do that. The fflush function is only for output streams.
Also , it is a really good idea to check the return value of scanf. If it was not what you expected then you may wish to take some action, instead of pretending that a number was entered.
Since you are tired of input issues, I can give you a method that can help to simplify your live.
I can observe that:
You have problems in handling end-of-lines.
Sometimes you need to input numbers and sometimes you need characters or another kind of input. So, you (think that you) are forced to use formatted input.
My advice is that you separate the issue of reading input from the issue of interpreting data entered from input.
The standard C brings only a few functions to handle input/output operations, in the standard header <stdio.h>.
If you are not interested in very sofisticated I/O results, the standard library is enough.
However, the functions of <stdio.h> usually have the effect that input is read one line at the time, which includes the end-of-line character: '\n'.
What you can do, then, it's what follows:
Read a line with fgets(..., stdin) and put the result in a buffer (not so long), used only for this purpose.
Once you have read an entire line, no more issues with end-of-line will bother you.
Then, re-read this line, that it's held in a buffer, and apply to it all the formatted input that you need.
A short example:
#include <stdio.h>
int main(void) {
char buffer[200] = ""; // Initialize array to 0's
long int n, m;
char c;
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%ld %ld",&n,&m);
// Now you have processed the "integer number" input,
// read input characters again, withou any "flushes" and extrange things:
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%c", &c);
fgets(buffer, sizeof(buffer), stdin);
// and so on...
}
Thus, every time you need to separate a section of input from a previous one, just do a new line reading with fgets(..., stdin), which stores the input in buffer, and then process the buffer with sscanf(), which applies the format string to the buffer instead of the input itself (in its flesh).
Note: This method can have a little problem: If the string input has more than sizeof(buffer) characters (in the example: 200), the line is not completely read. This situation can be handled by checking if the character before last in buffer is not equal to '\n' nor '\0'. In such a case, you would make automatically some kind of "flushing input" operation (reading and discarding characters till the next end-of-line is found).
First off, I am not familiar with c at all. It would be great if you treated me like a total beginner, which I am.
So, the problem I have is that I don't seem to be able to make it so that the program only takes the information of one number, uses it, then disregards any other information.
At the moment I have something similar to this:
#include <stdio.h>
#include <string.h>
int main(){
int i, ret;
char c, type;
do
{
printf("Convert ASCII # to character\n");
printf("q: Quit.\n");
scanf("%c", &type);
/* I use the " if(type== 'n'); " a number of times. */
/* I left the others out to simplify what my problem is. */
if(type=='1'){
printf("ASCII NUMBER -> CHAR \n");
printf("\t Please input one ASCII code \n");
int ret = scanf("%d", &i);
/* My aim here is to get the amount of integers the user inputs,*/
/* and use that to categorize, but I think I am failing to do so. */
if(ret==1){
printf("\t The character for ASCII code %d is -> '%c' \n\n", i, i);
break;
}
else{
printf("Please input one number./n/n");
break;
}
}
}
while(type=='q');
return 0;
/* A problem I face a lot is where the program would terminate*/
/* even when the while conditions weren't met. */
}
I hope you could understand what I'm trying to do by looking at the code above.
Any help would be greatly appreciated!
the program ends because of the character [enter] left in the input buffer.
You give input value for type then for i and press [enter]. this [enter] is a character left in the input buffer which will be read by next
scanf("%c",type);
so the loop exits. Therefore use getchar() after
int ret = scanf("%d", &i);
To clear the input buffer. and the loop will not end unexpectedly.
Make these changes,
printf("\t Please input one ASCII code \n");
int ret = scanf("%d", &i);
getchar(); //this will read the [enter] character in input buffer
/* My aim here is to get the amount of integers the user inputs,*/
/* and use that to categorize, but I think I am failing to do so. */
if(ret==1){
In general, I find it better to use fgets() (alternatively, if you are using C99, gets_s() -- although I still prefer fgets() for maximum portability to older compiler environments) for all user-based input, then if necessary use sscanf(), strtol(), and the like to convert the string into other data types, as this will read data by line in a way that is buffer-safe and you won't have to worry about things left in the input buffer. This is especially true for user-based input which is never well-formed (due to typos, etc). scanf() really only works well when reading from well-formed input files.
See the comp.lang.c FAQ which describes some of the problems that often occur when using scanf() in detail, including the problem you are seeing above, where inputs seem to be getting skipped:
http://c-faq.com/stdio/scanfprobs.html
http://c-faq.com/stdio/scanfhang.html
http://c-faq.com/stdio/scanfinterlace.html
http://c-faq.com/stdio/scanfjam.html
To find out more about any C standard library function, at a linux command prompt (or Google) type: man 3 fgets and so on.
fgets: http://linux.die.net/man/3/fgets
sscanf: http://linux.die.net/man/3/sscanf
strtol: http://linux.die.net/man/3/strtol
Example:
char buffer[256], type;
fgets( buffer, sizeof(buffer), stdin );
if( sscanf( buffer, "%c", &type ) == 1 ) {
// Was able to read a char from the buffer, now you can use it.
}
else {
// Wasn't able to read a char from the buffer. handle it if required.
}
If I want to receive a one character input in C, how would I check to see if extra characters were sent, and if so, how would I clear that?
Is there a function which acts like getc(stdin), but which doesn't prompt the user to enter a character, so I can just put while(getc(stdin)!=EOF);? Or a function to peek at the next character in the buffer, and if it doesn't return NULL (or whatever would be there), I could call a(nother) function which flushes stdin?
Edit
So right now, scanf seems to be doing the trick but is there a way to get it to read the whole string, up until the newline? Rather than to the nearest whitespace? I know I can just put "%s %s %s" or whatever into the format string but can I handle an arbitrary number of spaces?
You cannot flush the input stream. You will be invoking undefined behavior if you do. Your best bet is to do:
int main() {
int c = getchar();
while (getchar() != EOF);
return 0;
}
To use scanf magic:
#include <stdio.h>
#include <stdlib.h>
#define str(s) #s
#define xstr(s) str(s)
#define BUFSZ 256
int main() {
char buf[ BUFSZ + 1 ];
int rc = scanf("%" xstr(BUFSZ) "[^\n]%*[^\n]", buf);
if (!feof(stdin)) {
getchar();
}
while (rc == 1) {
printf("Your string is: %s\n", array);
fflush(stdout);
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getchar();
}
}
return 0;
}
You can use getline to read a whole line of input.
Alternatively (in response to your original question), you can call select or poll on stdin to see if there are additional characters to be read.
I had a similar problem today, and I found a way that seems to work. I don't know the details of your situation, so I don't know if it will work for you or not.
I'm writing a routine that needs to get a single character from the keyboard, and it needs to be one of three specific keystrokes (a '1', a '2', or a '3'). If it's not one of those, the program needs to send and error message and loop back for another try.
The problem is that in addition to the character I enter being returned by getchar(), the 'Enter' keystroke (which sends the keystroke to the program) is saved in an input buffer. That (non-printing) newline-character is then returned by the getchar() facility in the error-correction loop, resulting further in a second error message (since the newline-character is not either a '1', a '2', nor a '3'.)
The issue is further complicated because I sometimes get ahead of myself and instead of entering a single character, I'll enter the filename that one of these options will request. Then I have a whole string of unwanted characters in the buffer, resulting in a long list of error messages scrolling down the screen.
Not cool.
What seems to have fixed it, though, is the following:
c = getchar(); // get first char in line
while(getchar() != '\n') ; // discard rest of buffer
The first line is the one that actually uses the character I enter. The second line disposes of whatever residue remains in the input buffer. It simply creates a loop that pulls a character at a time from the input buffer. There's no action specified to take place while the statement is looping. It simply reads a character and, if it's not a newline, goes back for the next. When it finds a newline, the loop ends and it goes on to the next order of business in the program.
We can make a function to clear the keyboard buffer, like this:
#include <stdio.h>
void clear_buffer(){
char b;
//this loop take character by character in the keyboard buffer using
//getchar() function, it stop when the variable "b" was
//enter key or EOF.
while (((b = getchar()) != '\n') && (b != EOF));
}
int main()
{
char input;
//get the input. supposed to be one char!
scanf("%c", &input);
//call the clearing function that clear the buffer of the keyboard
clear_buffer();
printf("%c\n",input); //print out the first character input
// to make sure that our function work fine, we have to get the
// input into the "input" char variable one more time
scanf("%c", &input);
clear_buffer();
printf("%c\n",input);
return 0;
}
Use a read that will take a lot of characters (more than 1, maybe 256), and see how many are actually returned. If you get more than one, you know; if you only get one, that's all there were available.
You don't mention platform, and this gets quite tricky quite rapidly. For example, on Unix (Linux), the normal mechanism will return a line of data - probably the one character you were after and a newline. Or maybe you persuade your user to type ^D (default) to send the preceding character. Or maybe you use control functions to put the terminal into raw mode (like programs such as vi and emacs do).
On Windows, I'm not so sure -- I think there is a getch() function that does what you need.
Why don't you use scanf instead of getc, by using scanf u can get the whole string.