Форум сайта python.su
0
Всем доброго времени суток.
Только начинаю изучать питон, столкнулся на днях с интересной проблемой. Сразу оговорюсь, что гуглом пользовался, поиском по форуму тоже 
Писал прогу, которая должна проверять последовательность скобок на корректность. Пока решил ограничиться одним видом скобок.
Считывание решил сделать посимвольное с консоли, чтобы не вся последовательность сразу читалась, скажем, в массив, а считывалось по одному элементу и сразу обрабатывалась в алгоритме. В принципе, если читать сразу весь вход в массив и работать с ним, то ниже описанной пробемы не будет, но раз уж я с ней столкнулся, хочется разобраться.
С самим алгоритмом проблем нет, все прекрасно заработало. Проблемы начались после того, как решил все это обернуть в цикл, чтобы при вводе новой последовательности не надо было заново запускать программу, а выход сделать по заранее придуманной команде.
Собственно, сама проблема - если в какой-то момент обработки становится понятно, что последовательность некорректная (например, “(()))((())”), то происходит возврат из функции проверки, но вместо того, чотбы ожидать новую последовательность она пордолжает обрабатывать старую, с того момента, на котором произошел выход. Довольно быстро стало понятно, что проблема в том, что не происходит очистки буфера stdin.
Что предпринималось:
-sys.stdin.flush()
-попытка восстановить исходное состояние буфера при помощи буфера sys.__stdin__
-termios.tcflush(sys.stdin,termios.TCIFLUSH)
Все это оказалось безразультатно. Помогло только насильное досчитывание остатка буфера перед возвратом из функции, но похоже, что это костыль
)
А еще есть просьба следующего содержания. Основная проблема сайтов с курсами и прогами в том, что они говорят только о правильности работы кода, но ничего не говорят о его качестве и читаемости. Поэтому хочется, чтобы более опытные коллеги критично оценили сам код, стиль написания.
Заранее спасибо.
#!/usr/bin/python3.4
import sys
#объявление класса Стек
class Stack:
def __init__(self):
self.items = []
#интерфейс
#проверка на пустоту
def isEmpty(self):
return self.items == []
#добавление нового элемента
def push(self, item):
self.items.append(item)
#извлечение элемента с вершины стека
def pop(self):
return self.items.pop()
#просмотр элемента на вершине стека
def peek(self):
return self.items[len(self.items)-1]
#узнать рамер стека
def size(self):
return len(self.items)
def check():
stack=Stack()
while True:
c = sys.stdin.read(1)
if c == 'e':
print('stopped')
exit(0)
if c == '\n':
break
if c == '(':
stack.push(c)
elif c == ')':
if stack.isEmpty():
sys.stdin.read()
return False
elif stack.peek() == "(":
stack.pop()
if stack.isEmpty():
return True
else:
return False
print('enter \'e\' for exit')
while True:
print(check())
Отредактировано Donald522 (Авг. 26, 2015 12:17:17)
Прикреплённый файлы:
stack_braces.py (1,1 KБ)
Офлайн
568
Есть же стандартные функции input для python3 и raw_input для python2, зачем напрямую с stdout работать, в чем профит?
Офлайн
857
Donald522Это всё неправильно.
Что предпринималось:
-sys.stdin.flush()
-попытка восстановить исходное состояние буфера при помощи буфера sys.__stdin__
-termios.tcflush(sys.stdin,termios.TCIFLUSH)
Отредактировано py.user.next (Авг. 26, 2015 12:54:43)
Офлайн
0
py.user.nextПо символу конца строки? У меня же есть в функции check() условие выхода из цикла.
Как ты узнаешь, что две последовательности в потоке - это две последовательности, а не одна?
Офлайн
857
Donald522Вообще, есть понятие “маркер конца последовательности”. Скобочная последовательность может располагаться на множестве строк.
По символу конца строки?
Donald522Прочитать последовательность надо снаружи в буфер, а потом буфер подать в check(). Это в цикле делается, пока есть последовательности. И неправильные последовательности всё равно придётся дочитывать до конца, чтобы читать следующие. А сама check() делается для бесконечной последовательности.
А что, если последовательность будет очень большая, а ошибка будет в начале?
Отредактировано py.user.next (Авг. 26, 2015 13:12:24)
Офлайн
0
py.user.nextПод буфером понимается структура, которая будет объявлена мной внутри программы? Т.е. например список.
Прочитать последовательность надо снаружи в буфер, а потом буфер подать в check(). Это в цикле делается, пока есть последовательности. И неправильные последовательности всё равно придётся дочитывать до конца, чтобы читать следующие. А сама check() делается для бесконечной последовательности.
Офлайн
857
Donald522Да, типа такого.
Под буфером понимается структура, которая будет объявлена мной внутри программы? Т.е. например список.
>>> import io >>> >>> def f(stream): ... block = True ... while block: ... block = stream.read(10) ... if block: ... if not g(block): ... break ... >>> def g(s): ... print(s * 2) ... return 'r' not in s ... >>> f(io.StringIO('abcdefghijklmnopqrstuvwxyz')) abcdefghijabcdefghij klmnopqrstklmnopqrst >>>
Отредактировано py.user.next (Авг. 26, 2015 16:07:05)
Офлайн
0
py.user.nextЯ, если честно, подумал о более примитивной реализации, вроде такого:
Да, типа такого.
while True:
buf = list(input().strip())
check(buf)
Офлайн
857
Donald522Так я ж говорю, что одна скобочная последовательность может быть на нескольких строках, а input() читает не более одной.
Я, если честно, подумал о более примитивной реализации, вроде такого:
Donald522Да это просто изображение файла, чтобы как бы файл открыть, но при этом файл не открывать.
надо читать мануалы по модулю io
Donald522У тебя там хреново с алгоритмами. Стек ещё нормально сделан, а функция check() вызывает подозрения и требует перепроверок.
А что можете сказать именно по стилистике написания?
Офлайн