В программе необходимо обеспечить прекращение ввода как только входной поток иссякнет

Ну, я много искал в Google и здесь о том, как правильно очистить входной поток. Все, что я слышу, — это смешанные аргументы о том, что fflush () не определен для входного потока, и некоторые говорят, просто делайте это таким образом, а другие просто говорят, что не делайте этого, мне не очень повезло с поиском четкого эффективного / правильный способ сделать это, с которым согласны большинство людей . Я новичок в программировании, поэтому я еще не знаю всех синтаксисов / трюков языка, поэтому мой вопрос, какой способ является наиболее эффективным / правильным решением для очистка входного потока C ??

  1. Дважды использовать getchar() , прежде чем я попытаюсь получить дополнительную информацию?
  2. Просто использовать функцию fflush() на входе? или
  3. Вот как я думал, что должен это делать.

void clearInputBuf(void); void clearInputBuf(void) < int garbageCollector; while ((garbageCollector = getchar()) != ‘n’ garbageCollector != EOF) <>>

Итак, всякий раз, когда мне нужно прочитать новый scanf () или использовать getchar (), чтобы приостановить программу, я просто вызываю clearInputBuf. Итак, что было бы лучшим выходом из трех решений или есть еще лучший вариант?

Разработка приложений с помощью WinAPI. Урок 13. Введение в многопоточность. Вводвывод

Programming_n00b 4 Дек 2016 в 14:49

4 ответа

Лучший ответ

Все, что я слышу, это смешанные аргументы о том, что fflush () не определен для входного потока.

Правильно. Не используйте fflush() для очистки входного потока.

(A) будет работать для простых случаев, когда вы оставляете один символ во входном потоке (например, scanf() , оставляя новую строку).

(B) Не используйте. Это определено на некоторых платформах. Но не полагайтесь на то, что стандарт вызывает неопределенное поведение .

(C) Очевидно, лучший из трех вариантов, поскольку он может «сбрасывать» любое количество символов во входном потоке.

Но если вы читаете строки (например, используя fgets() ), вам, вероятно, будет гораздо меньше нужно очищать входные потоки.

usr 4 Дек 2016 в 11:54

Оказывается, это зависит от платформы.

fflush() не может иметь входной поток в качестве параметра, потому что в соответствии со стандартом c ЭТО НЕОПРЕДЕЛЕННОЕ ПОВЕДЕНИЕ, поскольку поведение нигде не определено.

  • В Windows существует определенное поведение для fflush() , и он делает то, что вам нужно.
  • В Linux есть fpurge(3) , который что ты тоже хочешь.

Лучший способ — просто прочитать все символы в цикле, пока

  1. Обнаружен символ новой строки.
  2. EOF возвращается из getchar() .

Как ваша функция clearInputBuf() .

Обратите внимание, что очистка выходного потока означает запись всех незаписанных данных в поток, данных, которые все еще находятся в буфере, ожидающих очистки. Но чтение всех непрочитанных байтов из потока не имеет того же значения.

Вот почему нет смысла использовать fflush() входной поток. С другой стороны, fpurge() разработан специально для этого, и его имя — лучший выбор, потому что вы хотите очистить входной поток и начать все заново. Проблема в том, что это не стандартная функция.

Уроки C# – Потоки, Thread, Invoke, Action, delegate, Parallel.Invoke – C#

Прочитав fpurge(3) , вы должны понять, почему > является неопределенным поведением, и почему реализация, подобная той, что есть в Windows, не имеет смысла, потому что она заставляет fflush() вести себя по-разному с разными входными данными. Это как сделать c совместимым с PHP.

Iharob Al Asimi 4 Дек 2016 в 12:03

Проблема более тонкая, чем кажется:

  • В системах со сложными терминальными устройствами, такими как unix и OS / X, ввод с терминала буферизируется на 2 отдельных уровнях: системный терминал использует буфер для обработки редактирования строки, от простого исправления ввода с помощью возврата до полного редактирования строки с помощью курсора и клавиши управления. Это называется режимом готового . Полная строка ввода буферизуется в системе до тех пор, пока не будет набрана клавиша ввода или не будет введена комбинация клавиш конца файла.
  • Функции FILE выполняют свою собственную буферизацию, которая по умолчанию буферизуется по строкам для потоков, связанных с терминалом. Размер буфера по умолчанию установлен на BUFSIZ , и байты запрашиваются у системы, когда буферизованное содержимое израсходовано. Для большинства запросов полная строка будет считана из системы в буфер потока, но в некоторых случаях, например, когда буфер заполнен, только часть строки будет считана из системы при возврате scanf() . Вот почему отбрасывания содержимого буфера потока не всегда бывает достаточно.
Читайте также:
Антор программа для логистики отзывы

Очистка входного буфера может означать разные вещи:

  • отбрасывание лишнего ввода, включая символ новой строки, который был введен пользователем в ответ на запросы ввода, такие как getchar() , fgets() или scanf() . Необходимость сброса этого ввода особенно очевидна в случае scanf() , потому что большинство строк форматирования не приводят к использованию новой строки.
  • отбрасывание любого ожидающего ввода и ожидание нажатия клавиши пользователем.

Вы можете реализовать переносимость функции fluch для первого случая:

int flush_stream(FILE *fp)

И это именно то, что ваша функция clearInputBuf() делает для stdin .

Для второго случая нет переносимого решения, а системные методы нетривиальны.

chqrlie 4 Дек 2016 в 12:33

Это зависит от того, что вы думаете о «очистке входного потока».

Для выходных потоков операция сброса гарантирует, что все данные, которые были записаны в поток, но хранились в буфере в памяти, были сброшены в основной файл файловой системы. Это очень четко определенная операция.

Для входных потоков не существует четко определенной операции очистки потока. Я бы сказал, что в этом нет никакого смысла.

Некоторые реализации стандартной библиотеки C переопределяют значение слова «flush» для входных потоков, чтобы означать «очистить остальную часть текущей строки, которая еще не была прочитана». Но это совершенно произвольно, и другие реализации предпочитают ничего не делать.

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

Итак, пожалуйста, непременно продолжайте и реализуйте вашу функцию clearInputBuf () так, как вы это делали, но не думайте об этом как о «очистке входного потока». Нет такого.

Источник: question-it.com

Составление программ для обработки потока данных

Часто требуется обрабатывать одинаковым образом данные, поступающие последовательно друг за другом. Возможны два случая:

· количество данных известно до начала выполнения программы. Тогда это значение используется в качестве верхней границы счетчика цикла (см. пример 2.21);

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

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

Читайте также:
Что такое преамбула в программе

Следующие примеры иллюстрируют эти приемы.

Пример 2.23. Определить средний рост учеников класса (в классе n учеников). В цикле будем вводить в переменную r рост очередного ученика и прибавлять его к сумме s. После выхода из цикла разделим суммарный рост на количество учеников (программа составлена для n = 5).

double sr, r, s = 0;

Console.WriteLine(«Введите рост ученика»);

Пример 2.24. Определить средний рост 14-летних подростков, проходящих диспансеризацию (количество заранее неизвестно).

Чтобы определить средний рост, будем в цикле вводить в переменную r рост очередного подростка и прибавлять его к сумме s, а количество подростков n увеличивать на 1. После выхода из цикла разделим суммарный рост на количество подростков.

Используем цикл do…while, для выхода из цикла будем использовать специальное значение, вводимое в r (например, 0):

Источник: studopedia.su

2. Потоки ввода-вывода

В соответствии с названием заголовочного файла iostream.h (stream — поток; «i» — сокращение от input — ввод; «o» — сокращение от output — вывод) описанные в этом файле средства ввода-вывода обеспечивают программиста механизмами для извлечения данных из потоков и для включения (внесения) данных в потоки. Поток определяется как последовательность байтов (символов) и с точки зрения программы не зависит от тех конкретных устройств (файл на диске, принтер, клавиатура, дисплей, стример и т.п.), с которыми ведется обмен данными. При обмене с потоком часто используется вспомогательный участок основной памяти — буфер потока (рисунок 1- буфер вывода, рисунок 2 — буфер ввода).

Рис.1. Буферизированный выходной поток

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

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

Рис.2. Буферизированный входной поток

Используемые в программах потоки логически делятся на три типа:

входные, из которых читается информация;

выходные, в которые вводятся данные;

двунаправленные, допускающие как чтение, так и запись.

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

В соответствии с особенностями «устройства», к которому «присоединен» поток, потоки принято делить на

Из перечисленных потоков мы не будем рассматривать только консольные потоки. Причин для этого несколько. Во-первых, консольные потоки отсутствовали в классических реализациях библиотеки потокового ввода-вывода. Во-вторых, консольные потоки несовместимы с операционной средой Microsoft Windows и могут использоваться только при разработке программ, работающих под управлением MS-DOS.

Консольные потоки поддерживаются классом constream и обеспечивают удобный доступ к терминалу. В них есть возможности работы с клавиатурой и средства манипуляции с участками экрана и с экраном в целом.

Если символы потока в совокупности образуют символьный массив (строку) в основной памяти, то это строковый поток. Если при использовании потока его символы размещаются на внешнем носителе данных (например, на диске или на магнитной ленте), то говорят о файловом потоке или просто о файле.

Читайте также:
Реферальные программы банков как заработать

Стандартные и консольные потоки соответствуют передаче данных от клавиатуры и к экрану дисплея. До сих пор во всех программах выполнялся обмен только со стандартными потоками. Рассмотрим их возможности подробнее. Однако предварительно остановимся на некоторых принципиальных особенностях потоковой библиотеки ввода-вывода языка С++.

В отличие от стандартной библиотеки (в которой находятся средства, например, для работы со строками, или математические функции), унаследованной компиляторами языка С++ от языка С, библиотека ввода-вывода С++ является не библиотекой функций, а библиотекой классов. Это первая «промышленная» библиотека классов, разработанная для распространения совместно с компиляторами.

Именно эту библиотеку рекомендуют изучать, начиная знакомиться с принципами объектно-ориентированного программирования. Одним из базовых принципов ООП является предположение о том, что объекты «знают», что нужно делать при появлении обращения (сообщения) определенного типа, т.е. для каждого типа адресованного ему обращения объект имеет соответствующий механизм обработки. Если мы используем объект cout, представляющий выходной поток, то как уже неоднократно показано на примерах, для каждого из базовых типов (int, long, double, . ) этот объект cout выбирает соответствующую процедуру обработки и выводит значение в соответствующем виде. Объект cout не может перепутать и вывести, например, целое число в формате с плавающей точкой. От таких ошибок, которые были возможны в языках С или FORTRAN, когда программист сам определял форму внешнего представления, библиотека классов ввода-вывода хорошо защищена.

Библиотека потоковых классов построена на основе двух базовых классов: ios и streambuf. Класс streambuf обеспечивает буферизацию данных во всех производных классах, которыми явно или неявно пользуется программист. Обращаться к его методам и данным из прикладных программ обычно не нужно. Класс streambuf обеспечивает взаимодействие создаваемых потоков с физическими устройствами.

Он обеспечивает производные классы достаточно общими методами для буферизации данных. Класс ios и производные классы содержат указатель на класс streambuf, но об этом можно до времени не вспоминать. Методы и данные класса streambuf программист явно обычно не использует. Этот класс нужен другим классам библиотеки ввода-вывода.

Он доступен и программисту-пользователю для создания новых классов на основе уже существующего класса из iostream. Однако необходимость в построении таких производных классов возникает достаточно редко, и мы не будем рассматривать класс streambuf. Класс ios содержит компоненты (данные и методы), которые являются общими, как для ввода, так и для вывода.

При работе с потоковой библиотекой ввода-вывода программист обычно достаточно активно использует следующие классы:

ios — базовый потоковый класс;

istream — класс входных потоков;

ostream — класс выходных потоков;

iostream — класс двунаправленных потоков ввода-вывода;

istrstream — класс входных строковых потоков;

ostrstream — класс выходных строковых потоков;

strstream — класс двунаправленных строковых потоков (ввода-вывода);

ifstream — класс входных файловых потоков;

ofstream — класс выходных файловых потоков;

fstream — класс двунаправленных файловых потоков (ввода-вывода);

constream — класс консольных выходных потоков.

Диаграмма взаимозависимости перечисленных классов изображена на рисунке 1. Следует отметить, что эта диаграмма потоковых классов упрощена. В реальной схеме присутствуют промежуточные классы и реализовано более сложное множественное наследование. Кроме того, программист, как упоминалось, обычно не учитывает наличия второго базового класса streambuf, и он не показан на схеме.

Источник: studfile.net

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru