How to ignore arrow keys in C reading from stdin? - c

I'm reading from the standard input using the read() system call but there's a tiny thing that bothers me. I can't use the arrow keys... What I really wanted to do was to use arrow keys to go back and forth within the typed text but I think that's not that easy... So, what I at least want to do, is to ignore them.
Right now, pressing any of the arrow keys produces strange output and I want to prevent anything from being written to the standard output (consequently read from the standard input in my read() system call).
Is this easily possible to achieve or it's not that easy?

In order to interpret the arrow keys the way you would ideally like to (i.e. to move back and forth and edit the input), you generally need to use a library. For Linux, the standard is GNU Readline. Hopefully someone else can say what you would normally use for a Windows CLI app.

The answer ultimately depends on where the keys come from. I ran this program under Cygwin:
int main(void)
{
int c=0;
while( c != 'X' ) {
c = getchar();
printf("\nc=%d", c);
}
}
Every time a cursor key comes along, I see escape (27), a bracket, plus another character.
So, if you get results like that, you can skip 3 keys every time you see a 27. You could also look at them and make use of them!
As mentioned, YMMV, especially for the O.S., and the actual key-getting function you call.

Related

How to definitely solve the scanf input stream problem

Suppose I want to run the following C snippet:
scanf("%d" , &some_variable);
printf("something something\n\n");
printf("Press [enter] to continue...")
getchar(); //placed to give the user some time to read the something something
This snippet will not pause! The problem is that the scanf will leave the "enter" (\n)character in the input stream1, messing up all that comes after it; in this context the getchar() will eat the \n and not wait for an actual new character.
Since I was told not to use fflush(stdin) (I don't really get why tho) the best solution I have been able to come up with is simply to redefine the scan function at the start of my code:
void nsis(int *pointer){ //nsis arconim of: no shenanigans integer scanf
scanf("%d" , pointer);
getchar(); //this will clean the inputstream every time the scan function is called
}
And then we simply use nsis in place of scanf. This should fly. However it seems like a really homebrew, put-together-with-duct-tape, solution. How do professional C developers handle this mess? Do they not use scanf at all? Do they simply accept to work with a dirty input stream? What is the standard here?
I wasn't able to find a definite answer on this anywhere! Every source I could find mentioned a different (and sketchy) solution...
EDIT: In response to all commenting some version of "just don't use scanf": ok, I can do that, but what is the purpose of scanf then? Is it simply an useless broken function that should never be used? Why is it in the libraries to begin with then?
This seems really absurd, especially considering all beginners are taught to use scanf...
[1]: The \n left behind is the one that the user typed when inputting the value of the variable some_variable, and not the one present into the printf.
but what is the purpose of scanf then?
An excellent question.
Is it simply a useless broken function that should never be used?
It is almost useless. It is, arguably, quite broken. It should almost never be used.
Why is it in the libraries to begin with then?
My personal belief is that it was an experiment. It tries to be the opposite of printf. But that turned out not to be such a good idea in practice, and the function never got used very much, and pretty much fell out of favor, except for one particular use case...
This seems really absurd, especially considering all beginners are taught to use scanf...
You're absolutely right. It is really quite absurd.
There's a decent reason why all beginners are taught to use scanf, though. During week 1 of your first C programming class, you might write the little program
#include <stdio.h>
int main()
{
int size = 5;
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++)
putchar('*');
putchar('\n');
}
}
to print a square. And during that first week, to make a square of a different size, you just edit the line int size = 5; and recompile.
But pretty soon — say, during week 2 — you want a way for the user to enter the size of the square, without having to recompile. You're probably not ready to muck around with argv. You're probably not ready to read a line of text using fgets and convert it back to an integer using atoi. (You're probably not even ready to seriously contemplate the vast differences between the integer 5 and the string "5" at all.) So — during week 2 of your first C programming class — scanf seems like just the ticket.
That's the "one particular use case" I was talking about. And if you only used scanf to read small integers into simple C programs during the second week of your first C programming class, things wouldn't be so bad. (You'd still have problems forgetting the &, but that would be more or less manageable.)
The problem (though this is again my personal belief) is that it doesn't stop there. Virtually every instructor of beginning C classes teaches students to use scanf. Unfortunately, few or none of those instructors ever explicitly tell students that scanf is a stopgap, to be used temporarily during that second week, and to be emphatically graduated beyond in later weeks. And, even worse, many instructors go on to assign more advanced problems, involving scanf, for which it is absolutely not a good solution, such as trying to do robust or "user friendly" input validation.
scanf's only virtue is that it seems like a nice, simple way to get small integers and other simple input from the user into your early programs. But the problem — actually a big, shuddering pile of 17 separate problems — is that scanf turns out to be vastly complicated and full of exceptions and hard to use, precisely the opposite of what you'd want in order to make things easy for beginners. scanf is only useful for beginners, and it's almost perfectly useless for beginners. It has been described as being like square training wheels on a child's bicycle.
How do professional C developers handle this mess?
Quite simply: by not using scanf at all. For one thing, very few production C programs print prompts to a line-based screen and ask users to type something followed by Return. And for those programs that do work that way, professional C developers unhesitatingly use fgets or the like to read a full line of input as text, then use other techniques to break down the line to extract the necessary information.
In answer to your initial question, there's no good answer. One of the fundamental rules of scanf usage (a set of rules, by the way, that no instructor ever teaches) is that you should never try to mix scanf and getchar (or fgets) in the same program. If there were a good way to make your "Press [enter] to continue..." code work after having called scanf, we wouldn't need that rule.
If you do want to try to flush the extra newline, so that a later call to getchar might work, there are several questions here with a bunch of good answers:
scanf() leaves the newline character in the buffer
Using fflush(stdin)
How to properly flush stdin in fgets loop
There's one more unrelated point that ends up being pretty significant to your question. When C was invented, there was no such thing as a GUI with multiple windows. Therefore no C programmer ever had the problem of having their output disappear before they could read it. Therefore no C programmer ever felt the need to write printf("Press [enter] to continue..."); followed by getchar(). I believe (another personal belief) that it is egregiously bad behavior for any vendor of a GUI-based C compiler to rig things up so that the output disappears upon program exit. Persistent output windows ought to be the default, for the benefit of beginning C programmers, with some kind of non-default option to turn that behavior off for those who don't want it.
Is scanf broken? No it is not. It is an excellent input function when you want to parse free form input data where few errors are to be expected. Free form means here that new lines are not relevant exactly as when you read/write very long paragraphs on a normal screen. And few errors expected is common when you read from files.
The scanf family function has another nice point: you have the same syntax when reading from the standard input stream, a file stream or a character string. It can easily parse simple common types and provide a minimal return value to allow cautious programmers to know whether all or part of all the expected data could be decoded.
That being said, it has major drawbacks: first being a C function, it cannot directly control whether the programmer has passed types meeting the format specifications, and second, as beginners are not consistenly hit on their head when they forget to control its return value, it is really too easy to make fully broken programs using it.
But the rule is:
if input is expected to be line oriented, first use fgets to get lines and then sscanf testing return values of both
only if input is expect to be free form (irrelevant newlines), scanf should be used directly. But never without testing its return value except for trivial tests.
Another drawback is that beginners hope it to be clever. It can indeed parse simple input formats, but is only a poor man's parser: do not use it as a generic parser because that is not what it is intended for.
Provided those rules are observed, it is a nice tool consistent with most of C language and its standard library: a simple tool to do simple things. It is up to programmers or library implementers to build richer tools.
I have only be using C language for more than 30 years, and was never bitten by scanf (well I was when I was a beginner, but I now know that I was to blame). Simply I have just tried for decades to only use it for what it can do...

Scan all characters entered until see a tab char

I want to autocomplete on a command line application a but like in bash you can use tab key which will complete the command. But getchar() seems to wait until a newline char is received before it starts reading any characters.
scanf seems to work the same way.
Is there any way I can scan characters one at a time no matter if they are whitespace or control characters?
I want to be able to read char by char as entered building up a command and then as soon as tab char received I will attempt to lookup how to complete and print full command in my application.
Don't reinvent the wheel.
Use what other projects use to build command lines: Libraries that implement that job for you.
Many CLI prompts depend on GNU readline, which I think is fine, if a bit cluttered and heavy. Also, it's GPL, so depends on whether you like that or not.
I'd look into linenoise. It's very lightweight, and if you decide you really want to implement user interface yourself rather than including one or two files, OK, do that, but look at the rather concise reference implementation that seems to be. Caveat: haven't used it myself, so far. The API is pretty simple, though, as can be seen in their example.
A popular alternative is libedit/editline.
You need the GNU Readline Library. Use the rl_bind_key() function to add a filename-completion processing function whenever the users presses a key ('\t', in your case).
You are in for a world of hurt if you try to roll your own readline style function.
(If you are on Windows.)

Would scanf,gets, or getchar be a better option for taking input by a certain format in C?

So I can't seem to understand which would be better to use, scanf,gets, or getchar because really they do the same thing for me at least. The input is as follows /file/file-name/file_name/file.txt and I need to capture each directory and file individually (The / is the indicator for separation). I know how to catch each individually, conceptually there's no problem here. My question is, which C function would be a better option to go with here? What are the limits of each function and what are the benefits of each?

Is it possible to capture Enter keypresses in C?

I want to write a C program that tokenizes a string and prints it out word by word, slowly, and I want it to simultaneously listen for the user pressing Enter, at which point they will be able to input data. Is this possible?
Update: see #modifiable-lvalue 's comment below for additional helpful information, e.g., using getchar() instead of getch(), if you go that route.
Definitely possible. Just be aware that gets() may not be entirely helpful for this purpose, since gets() interprets enter not as enter per se, but as "now, I the user, have entered as much string as I want to". So the input gathered by gets() from pressing just an enter will appear as an empty string (which might be workable for you).
See: http://www.cplusplus.com/reference/cstdio/gets/.
But there are other reasons not to use gets()--it does not let you specify a maximum to read in, so it's easy to overflow whatever buffer you are using. A security and bug nightmare waiting to happen. So you want fgets(), which allows you to specify a maximum size to read in. fgets() will place a newline in the string when an enter is pressed. (BTW, props to #jazzbassrob on fgets()).
You could also consider something like getch()--which really deals with individual key-presses (but it gets a bit complicated handling keys that have non-straightforward scan-codes). You may find this example helpful: http://www.daniweb.com/software-development/cpp/code/216732/reading-scan-codes-from-the-keyboard. But because of the scancodes issues, getch() is subject to platform details.
So if you want a more portable approach, you may need to use something heavier weight, but fairly portable, such as ncurses.
I suspect you can do what you want with either fgets(), keeping in mind that enter will give you a string with just a newline in it, or getch().
I just wanted you to be aware of some of the implementation/platform issues that can arise.
C can absolutely do this, but it's a little more complicated than one might guess at first attempt. That's because terminal input is, historically, very platform dependent.
Check out the conio.h library and its use in game making. You can compile with Borland. That was my first experience in unbuffered input and listening for keypresses in real time. There are certainly other ways though.

Clearing output of a terminal program Linux C/C++

I'm interested in clearing the output of a C program produced with printf statements, multiple lines long.
My initial guess was to use
printf("output1\n");
printf("output2\n");
rewind(stdout);
printf("output3\n");
printf("output4\n");
but this produces
output1
output2
output3
output4
I was hoping it would produce
output3
output4
Does anyone know how to get the latter result?
You can have the desired result both for terminal and pipes if you remember to remove the control characters as well. This is hardcoded for two lines.
#include <stdio.h>
int
main ()
{
fputs("output1\n",stdout);
fputs("output2\n",stdout);
fputs("\033[A\033[2K\033[A\033[2K",stdout);
rewind(stdout);
ftruncate(1,0); /* you probably want this as well */
fputs("output3\n",stdout);
fputs("output4\n",stdout);
return 0;
}
Most terminals support ANSI escape codes. You can use a J (with parameter 2) to clear the screen and an H (with parameters 1,1) to reset the cursor to the top-left:
printf("\033[2J\033[1;1H");
Alternatively, a more portable solution would be to use a library such as ncurses, which abstracts away the terminal-specific details.
Once you print something to the terminal you can't easily remove it. You can clear the screen but exactly how to do that depends on the terminal type, and clearing the screen will remove all of the text on the screen not just what you printed.
If you really want fine control over the screen output use a library like ncurses.
You can also try something like this, which clears the entire screen:
printf("\033[2J\033[1;1H");
You can include \033[1;1H to make sure if \033[2J does not move the cursor in the upper left corner.
More specifically:
033 is the octal of ESC
2J is for clearing the entire console/terminal screen (and moves cursor to upper left on DOS ANSI.SYS)
1;1H moves the cursor to row 1 and column 1
As far as C is concerned, stdout is nothing more than a byte stream. That stream could be attached to a CRT (or flat screen), or it could be attached to a hardcopy device like a teletype or even a sheet-fed printer. Calling rewind on the stream won't necessarily be reflected on the output device, because it may not make any sense in context of that device; think about what rewinding would mean on a hardcopy terminal or a sheet-fed printer.
C does not offer any built-in support for display management, so you'll have to use a third-party library like ncurses.
One way, is to do a exec('clear').
In fact, when you capture/redirect your stdout (./program > output.file), there is no way how to remove contents of that file, even printf("\033[2J\033[1;1H"); just adds this sequence of characters into it.

Resources