Equivalent to Windows getch() for Mac/Linux crashes - c

I am using getch() and my app crashes instantly. Including when doing:
int main()
{
getch();
}
I can't find the link but supposedly the problem is that it needs to turn off buffering or something strange along those lines, and I still want cout to work along with cross platform code.
I was told to use std::cin.get(), but I'd like the app to quit when a key is pressed, not when the user typed in a letter or number then press enter to quit.
Is there any function for this? The code must work under Mac (my os) and Windows.
Linking/compiling is not an issue; I include <curses.h> and link with -lcurses in XCode, while Windows uses <conio.h>.

Have you looked in <curses.h> to see what the getch() function does?
Hint: OSX and Linux are not the same as Windows.
Specifically, as a macro in <curses.h>, we find:
#define getch() wgetch(stdscr)
Now, there appears, on your system, to be an actual function getch() in the curses library, but it expects stdscr to be set up, and that is done by the curses initialization functions (initscr() and relatives), and that is signally not done by your code. So, your code is invoking undefined behaviour by calling curses routines before the correct initialization is done, leading to the crash.
(Good hint from dmckee - it helped get the link line out of acidzombie24, which was important.)
To get to a point where a single key-stroke can be read and the program terminated cleanly, you have to do a good deal of work on Unix (OSX, Linux). You would have to trap the initial state of the terminal, arrange for an atexit() function - or some similar mechanism - to restore the state of the terminal, change the terminal from cooked mode into raw mode, then invoke a function to read a character (possibly just read(0, &c, 1)), and do your exit. There might be other ways to do it - but it certainly will involve some setup and teardown operations.
One book that might help is Advanced Unix Programming, 2nd Edn by Mark Rochkind; it covers terminal handling at the level needed. Alternatively, you can use <curses.h> properly - that will be simpler than a roll-your-own solution, and probably more reliable.

You have not exhibited a
#include <stdio.h>
or
#include <curses.h>
or similar line. Are you sure that you are linking against a library that includes getch()?

Use the cin.get() function for example:
#include <iostream>
using namespace std;
int main()
{
char input = cin.get();
cout << "You Pressed: " << input;
}
The program would then wait for you to press a key.
Once you have, the key you pressed would be printed to the screen.

The getch function is not available on Unix-like systems, but you can replace it with console commands through your compiler with the system function.
Usage:
In Windows you can use system("pause");
In Unix-like systems (such as OSX) you can use system("read -n1 -p ' ' key");
Note: system is declared in <stdlib.h>.

Related

the linux and windows about the color

Recently, I've been having a problem.
#include <stdio.h>
#include <stdlib.h>
void main()
{
system("color 1F");
}
This can be printed Windows, but not in the Linux. Why?
Nothing to do with c, you're performing a system call on a command that doesn't necessarily exist.
color exists in the Windows shell, but doesn't on Linux. Your code is just not portable on Linux as-is.
Linux has its own way of doing it. You should check which OS you're running on and call the setterm instead for instance if you detect Linux (or at compilation time), so you already have Windows & Linux covered.
As a portable alternative, standard ANSI escape sequences are also widely available on a lot of OSes (For Windows, you need Windows 10, though)

alternative to the fscanf()/vscanf() functions family for using an alternative validation key or how to create a custom language layout?

I am rather knew in C. And the only way I know for setting a variable from stdin is by using thefscanf()/vscanf()functions family.
DOS operating systems are seeing a resurgence in the embedded market. The device which I am using is programmatically compatible with DOS and use a NEC V30Mx which feature the 80286 instruction set.
The problem is the built-in keyboard doesn’t feature the enter key and instead use the EXE key which enter the 0x1C00 key code (Alt enter).
So when I write a program like this :
#include <stdio.h>
#include <dir.h>
#include <dos.h>
int main(void) {
int res, number = 0;
printf("int value?");
res = scanf("%d", &number);
printf("The value is %d", number);
return;
}
scanf()is called and "int value?" is displayed on the screen. I can write numbers and upercase letters. but I can’t validate the output since nothing feature the 0x1C0D key code, and the EXE key use a different keycode.
Of course C has no knowledge of keyboard but the C standard library binaries look for the 0x1C0D key code for entering a\n.
So is there an alternative to thefscanf()/vscanf()functions family which is part of the C standard library?
Update :
I thought most C standard libraries under dos use software implementation for doing this.
I saw a DOS call for reading files and of course, using the number 0 cause to read from stdin.
So I assembled this example, loaded it on the calculator and find myself surprised the manufacturer preferred handling the issue in it’s built-in software rather than fixing the OS... :-( (I got the the same previous result)
Update
I didn’t thought about it but thanks to the comments, I forgot keyboard languages do key code remapping.
So, creating a custom mapping for the qwerty keyboard would be an another way to solve the problem.
The problem is scanf does not read past the bytes present in stdin that represent the EXE key.
Can you investigate to see what actual characters are read by getchar() when you press the EXE key, and write a function hasexe() that skips these if present. Call this function before or after the scanf().
Also check scanf() return value and check for EOF.
The only way to solve such a problem with standard C library is to use getchar() (or fgetc() on stdin) to get a character one at a time, detect the EXE key yourself, NUL terminate the string and pass it to sscanf().

Simulating shell like behavior

So what I want is when the user presses the up button, I want to instantly display the command and not show the ^[[A I already know how to identify up and down from the keyboard, and I know termios might be the solution, but coming from a java background, I don't quite know how to do this. Ncurses is not an option, due to certain constraints. If you can, please help.
What I expect to happen is, when the user presses the up button, I want to instantly do a printf on the same line
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char input[100];
char *history[5];
int currentHistory=0;
int historyCount=5;
history[0]="hi";
history[1]="bye";
history[2]="computer";
history[3]="science";
history[4]="Yo";
while(input[0]!='Q')
{
if(input[0]==LEFT_ARROW;
}
}
You'll find this functionality, and more, in either the GNU readline or the BSD editline libraries. They offer largely the same functionality, however the GNU readline library is under a GPL license, and editline is under a BSD license.
It isn't clear if you want to handle your input better, or your terminal handling better.
If you want to handle input better, I suggest wrapping your character recogonition into a function that returns an integer, which has defines for each "handled" key. That way your input looks more like
int char = readChar(input);
if (char == KEY_UP_ARROW) {
...
}
where readChar detects if the first key is an escape and then "peeks" to see if there is extra information available (to differentiate between a stand alone escape and the arrow keys).
If you intend to handle the screen side of things better, and your intent is to drive the terminal with your own wrapped terminal handling software, you need to reference the VT100 terminal reference (assuming that your xterm emulates VT100 (which many do)). The VT100 codes are described here.
Note that the operating system does some extra processing on input (to combine key combinations, making programs easier to differentiate between deadkey keyboard setups, etc.), so you might to disable this in-terminal processing by putting the terminal in a different "mode". Typical modes include "cooked", and "raw", where "raw" provides you with key codes that are not combined for simplicity.

debugging C with eclipse and cygwin

I am trying to debug the following C code with eclipse-Juno-CDT, and cygwin-gcc (cygwin version=1.7.16, gcc version=3.4.4, gdb version=7.5.50), on 64bit windows. The code works fine in normal mode. Initially debugger was not running, because the source file was not found. Then I searched around and added the path mapping information (from /cygdrive/c to C:\). Now it is running but with the following problems:
I have put a breakpoint before the "hello c 1" line, and then single stepping. But nothing gets printed on the console.
after single stepping on the last line ("exit"), I get the error: "No source available for _cygwin_exit_return() at ..."
// stdio.h and stdlib.h are included, but when I put a #include the code
// they dont show up, so I deleted those lines in this code fragment.
int main(void) {
int a=10;
int b=5; // breakpoint on this line, single step after this
printf("hello c 1\n"); // these outputs are not printed in console
// fflush(stdout);
printf("A=%d, B=%d\n", a, b); // but debugger shows the correct values in data window
// fflush(stdout);
return EXIT_SUCCESS; // error on this line
}
Added later: After some more debugging, I figured that even after the exit-error, if I do a "continue", then I am getting the lines on the console after the program terminates. So I added extra "fflush(stdout)" lines, and now I can see the outputs when they are being printed.
But how to fix the exit-error problem? Also, editing the file to add fflush to see debug outputs is a pain - is there a way to avoid this? Can somebody help me with this very basic problem, or point me to a place where the solution is given? Thanks in advance.
While logically a C program begins at int main() and ends when that function returns, environments (like Windows or Cygwin) frequently add pre- and post-code, for initializing / breaking down memory management, opening / closing standard streams, and other such bookkeeping. An executable compiled with Cygwin, after returning from int main(), switches to a cleanup function _cygwin_exit_return(), provided by the Cygwin runtime - for which you don't have sources, so your debugger complains.
As for getting the output immediately, you could use an unbuffered output stream.
Option one, use fprintf( stderr, ... ) (since stderr is by definition unbuffered). This, however, also affects the non-debugging behaviour of your program.
Option two:
int main()
{
// Using NDEBUG as also used by <assert.h>; feel free to use a different define
#ifndef NDEBUG
// For debugging, set stdout to unbuffered
setbuf( stdout, NULL );
#endif
....
Back when I was learning multithreading I was curious if threads were any faster than processes, and iirc I had to fflush even stderr/stdout on windows.
Memories aside, you can wrap those printf() in a function that calls fflush, or call setvbuf() to disable buffering.
About the exit: "no source available" only means that a part of your program lacks the info for debugging, so it's not a real error -- unless you build cygwin yourself, I guess the cygwin dll is stripped of debug symbols. Or maybe you want to debug cygwin's exit()?
EDIT: crap, concurrent answers :)

Unbuffered I/O in ANSI C

For the sake of education, and programming practice, I'd like to write a simple library that can handle raw keyboard input, and output to the terminal in 'real time'.
I'd like to stick with ansi C as much as possible, I just have no idea where to start something like this. I've done several google searches, and 99% of the results use libraries, or are for C++.
I'd really like to get it working in windows, then port it to OSX when I have the time.
Sticking with Standard C as much as possible is a good idea, but you are not going to get very far with your adopted task using just Standard C. The mechanisms to obtain characters from the terminal one at a time are inherently platform specific. For POSIX systems (MacOS X), look at the <termios.h> header. Older systems use a vast variety of headers and system calls to achieve similar effects. You'll have to decide whether you are going to do any special character handling, remembering that things like 'line kill' can appear at the end of the line and zap all the characters entered so far.
For Windows, you'll need to delve into the WIN32 API - there is going to be essentially no commonality in the code between Unix and Windows, at least where you put the 'terminal' into character-by-character mode. Once you've got a mechanism to read single characters, you can manage common code - probably.
Also, you'll need to worry about the differences between characters and the keys pressed. For example, to enter 'ï' on MacOS X, you type option-u and i. That's three key presses.
To set an open stream to be non-buffered using ANSI C, you can do this:
#include <stdio.h>
if (setvbuf(fd, NULL, _IONBF, 0) == 0)
printf("Set stream to unbuffered mode\n");
(Reference: C89 4.9.5.6)
However, after that you're on your own. :-)
This is not possible using only standard ISO C. However, you can try using the following:
#include <stdio.h>
void setbuf(FILE * restrict stream, char * restrict buf);
and related functions.
Your best bet though is to use the ncurses library.

Resources