首页 > 解决方案 > scanf("%d",&variable); 在我在一些空格键后单击输入后,整个程序正常运行时,即使按下空格键也不会停止

问题描述

这在 turbo c++ 中运行良好

int i;
scanf("%d",&i);

但在 Linuxscanf上,直到我们按 Enter 后才会返回。

scanf按下空格键时还有其他方法可以返回吗?

这是为了读取矩阵。

标签: clinuxterminal

解决方案


这个问题可以看出

...终端等待换行符或 EOF 将输入缓冲区发送到标准输入

因此,这在 Linux 和 Windows 上表现不同的原因与您的程序没有任何关系,而是因为运行您的程序并将您的键盘输入发送给它的环境的行为不同。

最简单的解决方案是停止担心缓冲。除非您的程序必须以交互方式执行某些操作(即,在输入每个矩阵元素时明显响应),否则一次只读取一整行元素就可以了。

如果您确实需要一次阅读每个元素,请阅读链接的问题和手册页tcgetattr,以讨论规范模式与原始模式以及输入行缓冲。请注意,这是非常特定于平台的,因此 Linux 需要它并且在 Windows 上根本无法编译。


关于 Linux 执行环境如何连接到 C stdio 调用的简要说明(足以帮助您阅读它,因为它是一个很大的主题)。

一个可移植的 C 程序有stdin,stdout和流,它们在它运行的平台和环境的上下文中stderr意味着某些东西。stdin就是scanf用途。

在类 UNIX 平台上,可移植 C 运行时和操作系统之间的接口使用整数文件描述符来跟踪打开的文件和类文件对象。标unistd.h头提供STDIN_FILENO,STDOUT_FILENO和: 这些是与可移植等流STDERR_FILENO相对应的 UNIX 特定文件描述符。stdin

当执行 UNIX 或 Linux 程序时,父程序(无论其他程序实际为您启动它)负责将这些文件描述符连接到可以提供输入和处理输出的东西。如果您从终端窗口手动运行程序,shell(例如 bash)就是这个父进程。如果您从 IDE 启动程序,则 IDE 是父进程(嗯,也许 - 它可以启动一个 shell 并让它完成工作)。

假设我从终端启动程序。终端拥有一个称为伪终端的设备,它是由内核创建的字符输入/输出设备的软件抽象。在 Linux 上,您可以通过键入来查看终端的伪终端

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 和 2 分别是 stdin、stdout 和 stderr 的文件描述符编号,因此您可以看到它们都连接到同一个伪终端设备。这意味着,当您的程序从标准输入读取时,它实际上是在向伪终端询问输入,而当您写入标准输出时,您实际上是在向伪终端发送字节。

现在,这个伪终端有大量的逻辑和设置,一些与线路规范相关(当这些是物理远程终端时,这真的更相关,在串行电缆的末端),还有一些与线路缓冲等行为相关。

您的问题与默认(规范)行缓冲行为有关:伪终端在看到换行符之前不会将键盘输入字符发送到您的程序。这意味着您的程序无法便携地做任何事情,因为问题出在便携的 C 运行时环境之外。


推荐阅读