зсапЕ ( "% d", & переменная);не останавливает даже нажатый spacbar, пока вся программа работает правильно после того, как я нажму Enter после некоторых пробелов - PullRequest
0 голосов
/ 25 октября 2018

Это прекрасно работает в turbo c ++

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

, но в Linux scanf не возвращается, пока мы не нажмем Enter.

Есть ли другой способ заставить scanf возвращаться, когданажата пробел?

Предназначен для чтения матриц.

1 Ответ

0 голосов
/ 25 октября 2018

Из этого вопроса вы можете видеть, что терминалы

... ждут новой строки или EOF для отправки входного буфера в stdin

Таким образом, причина того, что это ведет себя по-разному в Linux и Windows, не имеет ничего общего с вашей программой, а в том, что среда, которая запускает вашу программу и отправляет на нее ввод с клавиатуры, ведет себя по-разному.

Самое простое решениеэто просто перестать беспокоиться о буферизации.Если ваша программа не должна что-то делать в интерактивном режиме (т. Е. Реагировать визуально при вводе каждого матричного элемента), будет хорошо просто читать по одной строке за раз.

Если выдействительно нужно читать каждый элемент по одному, читать связанный вопрос и справочную страницу для tcgetattr, чтобы обсудить канонический режим по сравнению с необработанным режимом и буферизацию строки ввода.Обратите внимание, что это очень для конкретной платформы, поэтому он потребуется для Linux и вообще не будет компилироваться в Windows.


A краткое примечание ккак среда выполнения Linux связана с вызовами C stdio (достаточно, чтобы помочь вам прочитать об этом, поскольку это большой вопрос).

Переносимая программа на C имеет stdin, stdout иstderr потоков, что означает что-то в контексте платформы и среды, в которой оно работает.Поток stdin - это то, что scanf использует.

На UNIX-подобных платформах интерфейс между переносимой средой выполнения C и операционной системой использует целочисленные файловые дескрипторы для отслеживания открытых файлов и файловоподобных объектов.Заголовок unistd.h предоставляет STDIN_FILENO, STDOUT_FILENO и STDERR_FILENO: это специфичные для UNIX файловые дескрипторы, соответствующие переносимым потокам stdin и т. Д.

Когда программа UNIX или Linuxвыполняется, родитель (независимо от того, какая другая программа фактически запускала его для вас) отвечает за соединение этих файловых дескрипторов с чем-то, что может обеспечить ввод и обработку вывода.Если вы запускаете вашу программу вручную из окна терминала, оболочка (например, bash) является родительским процессом.Если вы запускаете программу из IDE, IDE является родительским процессом (ну, может быть - он может запустить оболочку и получить ее для выполнения этой работы).

Допустим, я запускаю программу из терминала.Терминал владеет устройством, называемым псевдотерминалом, которое является программной абстракцией устройства ввода / вывода символов, созданного ядром.В 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 соответственно, так что вы можете видеть, что все они подключены к одномупсевдотерминальное устройство.Это означает, что когда ваша программа читает из stdin, она действительно запрашивает ввод у псевдотерминала, а когда вы пишете в stdout, вы действительно отправляете байты в псевдотерминал.

Теперь этот псевдотерминал загружен логикойи настройки, некоторые из которых связаны с линейной дисциплиной (которая была действительно более актуальной, когда это были физические удаленные терминалы, в конце последовательного кабеля), а некоторые - с поведением, таким как буферизация линии.

Ваша проблема связана сстандартное (каноническое) поведение буферизации строк: псевдотерминал просто не отправляет символы ввода с клавиатуры в вашу программу, пока не увидит новую строку.Это означает, что ваша программа ничего не может переносить , потому что проблема не в переносимой среде выполнения C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...