Avoid pressing enter with getch() on Linux ( GCC ) "No-echo" - c

In the next code: I don't have to press Enter to get the character with getch() and this is only applicable on Windows (mingw) . I am programming a simple stopwatch which reacts if a keyboard-key is pressed without the need to press ENTER, but the same thing doesn't work on Linux ( GCC ). And I have to find a solution only using getch() with no echo. I've been Googling around with no luck. Thank you in advance.
PS: I am a c/c++ beginner.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
printf("\n\t\tStopwatch \n\n \t Press S to start \n\n");
time_t start;
char c ;
struct tm tm ;
do {
c=getch(); /*get the Character without pressing ENTER*/
if (c!= 'S' && c!= 's') printf("\nWrong key. Please press'S' to Start\n");
} while(c!= 'S' && c!= 's');
start=time(NULL);
tm = *localtime(&start);
printf("\n Starting time :: %d:%d:%d \n", tm.tm_hour, tm.tm_min, tm.tm_sec);
return 0;
}

Unix (and so Linux) have a concept of terminal (TTY) which can be pretty complicated.
Every process can be associated with a terminal (and lot actually are).
This terminal has different options like the ECHO you mentioned and the LINE BUFFER (which is the enter problem which you reported).
To set a terminal the low level APIs are termios (see "man termios").
Another more friendly API is ncurses (see "man ncurses"). For instance at https://www.mkssoftware.com/docs/man3/curs_inopts.3.asp you can see some function for different settings.
An easy example with ncurses (you can compile with "gcc -O2 source.c -o output -lncurses"):
#include <stdio.h>
#include <ncurses.h>
int main(void)
{
initscr();
cbreak();
noecho();
int n = getch();
printf("%d %c\n", n, n);
}

Related

libreadline - fgetc returns different values for the enter key

fgetc returns a different value for the enter key after
calling libreadline's rl_callback_handler_install(). It changes from line feed (\n) to carriage return (\r).
How is this possible? I've read the source but could not figure out what mechanism is used to achieve this.
Also, but less important, is this feature or a bug?
// compile with gcc -o main.o main.c -lreadline
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
static void foo_rl_callback(char *line)
{
// do stuff
}
static void get_enter_key(void)
{
printf("press enter!\n");
printf("fgetc=%d\n", fgetc(stdin));
}
int main(int argc, char *argv[])
{
printf("readline: %s\n", rl_library_version);
get_enter_key();
rl_callback_handler_install(NULL, foo_rl_callback);
get_enter_key();
rl_callback_handler_remove();
get_enter_key();
return 0;
}
output (assuming user only presses the enter key):
readline: 8.1
press enter!
fgetc=10
press enter!
fgetc=13
press enter!
fgetc=10
I'm not 100% sure but I believe this is being done by prepare_terminal_settings (there are several versions of that function; the link goes to the version that should be being used on any system shipped in the past 15 years or so).
This function uses tcsetattr to twiddle a whole bunch of flags that control the behavior of a Unix terminal or pseudo-terminal. In particular, it turns the ICANON bit off, which means, among many other things, that U+000D CARRIAGE RETURN coming down the serial line is not converted to U+000A LINE FEED anymore.
While readline is active, you should be using only the readline API to interact with the terminal, not fgetc(stdin).

scanf keeps running nonstop

I have been trying to run the scanf() on my mac, but it never worked (took forever to run the program). Everything else like the printf works fine!
#include <stdio.h>
#include <stdlib.h>
int main(){
char name[20];
printf("What is your name? \n");
scanf("%19s", name);
return 0;
}
terminal
[Running] cd "/Users/yiminghuang/Documents/C/" && gcc scanf4.c -o scanf4 && "/Users/yiminghuang/Documents/C/"scanf4
[Done] exited with code=null in 8.611 seconds
[Running] cd "/Users/yiminghuang/Documents/C/" && gcc scanf4.c -o scanf4 && "/Users/yiminghuang/Documents/C/"scanf4
[Done] exited with code=null in 10.384 seconds
[Running] cd "/Users/yiminghuang/Documents/C/" && gcc scanf3.c -o scanf3 && "/Users/yiminghuang/Documents/C/"scanf3
[Done] exited with code=null in 15.999 seconds
I am new to C programming, so please excuse me if I fail to answer your question correctly!
Now, the program you wrote works perfectly fine but as soon as you enter a string separated by a space, it only takes the characters before the space.
To solve this problem, you can use fgets() function of C.
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int main(){
char name[MAX];
printf("What is your name? \n");
fgets(name, MAX, stdin);
printf("String = %s", name);
return 0;
}
//i have used fgets() here for getting the input
//it is a better option than gets()
//since it bounds your array and prevents buffer overflow
I have also added a printf() to check if the string is stored correctly.
IMPORTANT: fgets() also consider the newline character i.e. '\n' as a part of your string. So better to keep that in mind.
Check this question to know more about fgets()
Regards!

How to use `getch` function of c in Linux?

I had installed ncurses library in Linux mint and still I can't use getch function in c. I am using Linux mint 18.2.
Here is my program:
#include <stdio.h>
#include <curses.h>
int main() {
char k;
printf("how are you");
k = getch();
printf("%c",k);
}
and here is the output:
ram#ram$ gcc-7 test.c -lcurses
ram#ram$ ./a.out
how are you�ram#ram$
It does't wait for me to press any key and terminate to quickly. I don't want to install conio.h for Linux. How can I use getch and getche function in Linux? Please don't tell me to make my own function. I am still a noob. Or there must be alternatives.
Here's a "corrected" version, explaining what's wrong in the comments:
#include <curses.h>
#include <stdio.h>
int main(void)
{
// use the correct type, see https://linux.die.net/man/3/getch
int k;
// init curses:
initscr();
// in curses, you have to use curses functions for all terminal I/O
addstr("How are you?");
k = getch();
// end curses:
endwin();
printf("You entered %c\n", k);
return 0;
}
This still isn't good code, you should at least check whether you got a valid character from getch().
It's also important to note that getch() isn't a "function of C". It's part of curses, a well-known platform-independent API for console/terminal control, with implementations e.g. for *nix systems (ncurses) and Windows (pdcurses). It's not part of the language C.

Cannot run program

I started learning C programming with C Programming Language by Denis M Ritchie I am trying to execute program from that book
#include <stdio.h>
/* count lines in input */
main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
getchar();
}
However all I get is blank console and when I type text and press enter,no value is displayed.
I am using Visual Studio 2013 IDE.
The program you posted here is for counting number of lines.
Q. However all I get is blank console and when I type text and press
enter,no value is displayed
A. Yes it shows nothing because while ((c = getchar()) != EOF) waits until you enter EOF (use ctrl + z then you will get number for lines).
getchar(c);
See declaration of getchar.
int getchar(void)
It doesn't take any parameter. Didn't it gave you error.
And main should be int main.
There are several issues. First, main has to have a type, usually int
- main()
+ int main()
and your program should return an exit status
Secondly getchar takes no arguments, and returns the input
http://www.tutorialspoint.com/c_standard_library/c_function_getchar.htm
- getchar(c)
+ c = getchar()
You can compile your program by calling
gcc -Wall test.c -o test
Where test.c is your code, and test is the binary. -Wall will show all the "warning" (errors that don't interfere with the program execution)
I believe that you use Windows, it's better to add:
system("pause");
Moreover to use system("pause"), only in Windows, you need to include another library:
#include <stdlib.h>
You can see your results but the problem here, is that you have an infinite loop. Yo need to check the \n, count and when you have a specific number, you leave from the loop.

EOF function in c++ |c

for example there is code
#include <algorithm>
#include <stdio.h>
#include <iostream>
int intcomp(int *x,int *y) { return *x-*y;};
int a[10000];
int main(void){
int i; int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
qsort(a,n,sizeof(int),intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
how tell computer that EOF is reached?
You mean when entering input interactively?
In a windows shell, ctrl+z on a line on its own. In a *nix shell, ctrl+d. Or just put your input in a file and pipe it, then not only will eof be detected at the appropriate time but also you can automate your testing.
You should use CTRL+Z combination (or somehow input character with code 26, for example, by pressing ALT+2+6 on additional keyboard)

Resources