2

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.

balu
  • 55
  • 1
  • 7
  • Dear close-voters, the OP is a new user, hence it would be nice of you to provide assistance and explain, what is wrong with the question, before casting your votes. Please, give OP a chance to improve the question by explaining the reasoning behind your vote. – Eli Korvigo Oct 25 '18 at 23:25

1 Answers1

3

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.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • minor nit: the shell executes the program, but doesn't send input to it. – William Pursell Oct 25 '18 at 12:53
  • ugh, I was hoping to avoid a discussion of pseudoterminals. You are of course correct though. – Useless Oct 25 '18 at 12:54
  • 1
    understood! can you still explain it 3rd paragraph briefly – balu Oct 25 '18 at 12:56
  • I'm afraid I didn't have time to make it briefer - there's just a lot of background information needed to understand the termios solution. This should be enough you can at least roughly understand that, and start reading the man pages. – Useless Oct 25 '18 at 13:22