Язык: C++ Суть проблемы: требуется остановить работу цикла после ввода пользователем...

0 голосов
36 просмотров

Язык: C++ Суть проблемы: требуется остановить работу цикла после ввода пользователем определенной строки. При этом программа не должна после каждой итерации цикла ожидать ее ввода. Пример простейшей программы: #include #include using namespace std; int main() { unsigned long long a=0; for(;;) { ++a; usleep(200000); } cout << a << endl; return 0; } Данная программа постоянно увеличивает значение a с интервалом в 0.2 секунды. Логично, что программа не достигнет вывода числа a. Что требуется: после ввода пользователем строки "Stop" (без кавычек) мы выходим из цикла, но до этого пользователь ничего не вводил и цикл работал в стандартном режиме. Пример Остановка цикла ровно через 0.1 секунду. Вывод: 1 Остановка цикла ровно через 0.2 секунды. Вывод: 1 (для начала следующей итерации не хватает времени: несколько микросекунд на объявление a, ++a, а также ожидание: 0.2 секунды. И, логично, первое ожидание через 0.2 секунды после начала не закончится) Остановка цикла ровно через 1 секунду. Вывод: 5 Остановка цикла ровно через 10 секунд. Вывод: 50 (при дальнейшем увеличении времени, логично, операции будут замедляться и темпы увеличения числа немного замедлятся). Решением будет готовая программа.


Информатика (3.5k баллов) | 36 просмотров
0

Ну начнем с того, что ты потерял инклюды, продолжим тем, что функция usleep только под uxnix хедеры если я правильно помню. Такое лучше указывать, что ты девелопишь именно под юникс-подобную систему.

0

Немного вопросов, по какой причине у тебя цикл for а не while?)Работают они не совсем одинаково и непонятно зачем написано for, если можно оптимизировать через while?

0

На счет примера, он не правильный, если юзер ввел строку "стоп" до того как программа достигла инкремента переменной а, вывод будет 0.Если ты думаешь, что такое не возможно, читай дальше, ниже обьясню как все это будет реализовываться.

0

Итак, как решать, а тут добро пожаловать в мир ассинхронщины. По факту ты не можешь обрабатывать одновременно две задачи:- Ввод пользователем строки "стоп"- Рабобтающий циклТо есть, для того что бы ввод строки пользователем осуществлялся независимо от работы цикла, необходимо разпараллелить эти процессы, то есть пустить их в разных потоках.

0

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

0

Продолжая тему usleep, почитал я в интернетах по больше и как выяснилось, она уже не входит в поставку Unix & POSIX подобных систем, вместо неё лучше использовать обычный sleep.

0

Написал как ты просил, но лучше уточни ещё в коментах.

Дан 1 ответ
0 голосов

Вот собственно программа.

Начнем с инклюдов, у нас в наличии chrono по тому, что мы будем использовать тип данных для милисекунд, вместо обычной функции sleep. Это делаем по тому, что нам нужна точность синхронизации потоков, к томуже по факту механизм схож, но уже из стандарта C++0x, как и потоки. Если сильно хочется использовать sleep, пожалуйста, тогда инклюдим так:

#ifdef _WIN32

#include

#else

#include

#endif

Инклюд через иф дефайны для того, что реализацию функции sleep на разных платформах предоставляют разные хедеры.

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

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

Если есть вопросы - пиши в коменты.

Буду благодарен за отметку решения как "лучшее" и нажатую кнопочку "спасибо" тут и в моем профиле.

(172 баллов)
0

И уточню: у меня линуксовая машина (добавлены iostream и unistd.h

0

sleep не подходит т.к. в той программе, для которой я это выясняю требуется иньервал в десятые доли секунды

0

Ну результатом - программа, а знания не позволяют дестрибьютить бинарники - компилируйте)Как распаралелить - написано в коде программы, вы создаете дополнительный поток, который занимается только обработкой ввода пользователя, и не мешает при этом работе цикла.

0

К слову говоря, по хорошему тут должен быть ещё и мьютекс, но это уже дебри паралельщины. Добавить его - НАДО, но для начала разберитесь с этим.В данной реализации нет необходимости знать под какую ось компилируете, везде будет работать одинаково.

0

Тут используется тип данных из хроно - милисекунды, вам хватит с головой (:

0

Понял, принял. Попробую разобраться, потом оценю. Ну и еще раз уточню: в примере выводом может быть 0, но я не уточнял. Минимальное время в примере - 0.1 с, но первый инкремент выполняется гораздо быстрее. А дальнейшие примеры были уже основаны на ручном вычислении. Цикл for был использован вместо цикла while из-за того, что еще не было идей, как это реализовать.

0

ну в общем тут я использовал как ты видешь только while и do while. for тебе может быть нужен только тогда когда нужна работа с индексом, а иначе зачем загружать asm командами проц?

0

На счет ручных вычеслений - не гони, просто же разделить 10 секунда на 0.2 секунда и получить 50) Ты бы не смог с точностью до одной пятой секунды вводить stop)

0

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