This works fine in turbo c++
int i;
scanf("%d",&i);
but on Linux scanf
does not return until we hit enter.
Is there any other way of making scanf
return when the space bar is pressed?
This is intended for reading matrices.
This works fine in turbo c++
int i;
scanf("%d",&i);
but on Linux scanf
does not return until we hit enter.
Is there any other way of making scanf
return when the space bar is pressed?
This is intended for reading matrices.
From this question you can see that
... terminals wait for a newline or EOF to send the input buffer to stdin
So, the reason this behaves differently on Linux and Windows isn't anything to do with your program, but is because the environment which runs your program and sends your keyboard input to it behaves differently.
The simplest solution is to just stop worrying about buffering. Unless your program has to do something interactively (ie, responding visibly as each matrix element is entered) it will be fine to just read one whole row of elements at a time.
If you really need to read each element one at a time, read the linked question, and the man page for tcgetattr
, for the discussion about canonical mode versus raw mode, and input line buffering. Note that this is very platform specific, so it will be required for Linux and won't compile at all on Windows.
A brief note on the how the Linux execution environment is connected to the C stdio calls (just enough to help you read up on it, since it's a large subject).
A portable C program has stdin
, stdout
and stderr
streams which mean something in the context of the platform and environment where it is running. The stdin
stream is what scanf
uses.
On UNIX-like platforms, the interface between the portable C runtime and the operating system uses integer file descriptors to track open files and file-like objects. The unistd.h
header provides STDIN_FILENO
, STDOUT_FILENO
and STDERR_FILENO
: these are the UNIX-specific file descriptors corresponding to the portable stdin
etc. streams.
When a UNIX or Linux program is executed, the parent (whatever other program actually started it for you) is responsible for connecting these file descriptors to something that can provide input and handle output. If you run your program manually from a terminal window, the shell (eg. bash) is this parent process. If you start the program from an IDE, the IDE is the parent process (well, maybe - it could start a shell and get that to do the work).
Let's say I start the program from a terminal. The terminal owns a device called a pseudoterminal which is a software abstraction of a character input/output device created by the kernel. On Linux, you can see your terminal's pseudoterminal by typing
ls -l /proc/$$/fd
lrwx------ 1 uid gid 64 Oct 25 08:34 0 -> /dev/pts/2
lrwx------ 1 uid gid 64 Oct 25 08:34 1 -> /dev/pts/2
lrwx------ 1 uid gid 64 Oct 25 08:34 2 -> /dev/pts/2
0, 1 and 2 are the file descriptor numbers for stdin, stdout and stderr respectively, so you can see they're all connected to the same pseudoterminal device. That means, when your program reads from stdin, it's really asking the pseudoterminal for input, and when you write to stdout, you're really sending bytes to the pseudoterminal.
Now, this pseudoterminal has a load of logic and settings, some associated with line discipline (which was really more relevant when these were physical remote terminals, at the end of a serial cable) and some associated with behaviour like line buffering.
Your issue is to do with the default (canonical) line buffering behaviour: the pseudoterminal simply doesn't send the keyboard input characters to your program until it sees a newline. That means there is nothing your program can portably do, because the problem is outside the portable C runtime environment.