С Новым годом! Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.59/190: Рейтинг темы: голосов - 190, средняя оценка - 4.59
0 / 0 / 0
Регистрация: 22.11.2019
Сообщений: 7

Телефонный справочник

22.11.2019, 15:49. Показов 40942. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помогите, пожалуйста, написать программу. Я запуталась в ее написании(

Требования к программе:
1) При запуске программы (скрипта), она должна считывать содержимое
телефонного справочника из файла, хранящего на жестком диске. Файл может как
содержать записи (в корректном виде), так и быть пустым.
2) При завершении работы программы и/или при завершении выполнении команды,
изменяющей справочник, все изменения в справочнике должны быть сохранены в
файл (тот, из которого справочник считывается в начале).
3) Минимальный набор поддерживаемых команд для работы со справочником:
 Просмотр всех записей справочника: вывод всего справочника так, чтобы
было читабельно.
 Поиск по справочнику.
Поиск может осуществляться по любому из полей, а также по нескольким
полям одновременно (например, найти запись с именем «А» и фамилией
«Б»).
В результате поиска должны быть выведены найденные записи со
значением полей.
 Добавление новой записи.
NB: Обязательна проверка на то, что такая запись не содержится в
справочнике (по уникальному идентификатору).
Если такая запись уже содержится в справочнике, сообщить об этом
пользователю и предложить: изменить существующую запись, изменить
(Имя, Фамилия) новой записи или вернуться к выбору команды.
NB: При вводе Имени и Фамилии обязательна автозамена первой буквы на
заглавную.
 Удаление записи из справочника по Имени и Фамилии
 Изменение любого поля в определенной записи справочника
 Вывод возраста человека (записи) по Имени и Фамилии
4) Если пользователь неправильно ввел команду, программа должна
проинформировать его о некорректном вводе и вернуться в состояние ожидания
ввода команды.
5) Ни одна операция не должна заканчиваться ошибкой или вылетом программы при
поступлении любых входных данных – либо операция должна быть корректно
обработана, либо должно быть выведено сообщение об ошибке (желательно
информативное), и программа возвращена в состояние ожидания ввода.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.11.2019, 15:49
Ответы с готовыми решениями:

Телефонный справочник
Всем привет, помогите решить задачу Напишите программу, которая имитировала бы работу простого телефонного справочника. В первой строке...

Телефонный справочник
Помогите пожалуйста решить задачу! Напишите программу, которая имитировала бы работу простого телефонного справочника. В первой строке...

Телефонный справочник
Здравствуйте! Столкнулся с некоторыми проблемами реализации телефонного справочника. Условия: Для меня не понятно как лучше...

27
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
22.11.2019, 16:12
Ekaterina56, хм, интересное задание, можете начинать.
1
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
22.11.2019, 16:14
Ekaterina56, Это значительный объем работы. Если у кого то нет аналогичной сделанной раньше программы, то я сомневаюсь , что кто то возьмется написать Вам код. Эта работа для раздела фриланса.
0
Автоматизируй это!
Эксперт Python
 Аватар для Welemir1
7390 / 4817 / 1246
Регистрация: 30.03.2015
Сообщений: 13,664
Записей в блоге: 29
22.11.2019, 16:33
Цитата Сообщение от Ekaterina56 Посмотреть сообщение
Я запуталась в ее написании(
покажите где запутались, посмотрим, поможем, расскажем
0
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
22.11.2019, 16:46
Welemir1, она имела ввиду, что запуталась пока писала сюда.
0
 Аватар для Semen-Semenich
5222 / 3469 / 1173
Регистрация: 21.03.2016
Сообщений: 8,295
22.11.2019, 18:43
Ekaterina56, это в стиле ооп задание или как? как хранить данные как текст или в словарях, базах данных, json, что-то другое? а файл точно существует или его нужно создать при его отсутствии? вообщем без ваших начальных попыток по которым будет хоть что то понятно вы больше получите вопросов чем ответов
0
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
22.11.2019, 18:59
Ekaterina56, Хранить информацию в текстовом файле в виде таблицы и осуществлять все те действия, которые здесь описаны, которые осуществляются в полноценных базах данных, это не серьезно. Хранить нужно в базе данных, или создаваемой питоном с помощью модуля shelve или в сторонней базе данных. И именно используя их осуществлять все необходимые действия с данными. А выводить на экран или на печать в виде текстовой таблицы.
0
0 / 0 / 0
Регистрация: 22.11.2019
Сообщений: 7
23.11.2019, 07:55  [ТС]
Я написала эти операции по отдельности. Возник вопрос как объединить их так, чтобы пользователю при запуске программы выходило меню и предлагалось выбрать одну из представленных операций (по номерам). При выборе номера запускался процесс выполнения операции.
Файл уже существует, но изначально в нем нет записей.
Ещё вопрос открытие и чтение файла написать в начале скрипта или расписывать в каждой операции, ведь где-то происходят изменения в файле, а где-то просто его чтение?
А если не создавая базу данных, оставить хранение в файле?

Добавлено через 4 минуты
Я и не прошу выполнять весь процесс за меня. Просто подсказать в каком направлении двигаться.
0
 Аватар для Semen-Semenich
5222 / 3469 / 1173
Регистрация: 21.03.2016
Сообщений: 8,295
23.11.2019, 08:39
Лучший ответ Сообщение было отмечено Ekaterina56 как решение

Решение

ну примерно так. вы не указали в каком формате хранятся данные поэтому в примере используется чтение построчно из файла.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def readfile(filename):
    # чтение файла при запуске
    return open(filename).read().split('\n')
 
def scan(data):
    # Просмотр всех записей справочника:
    for i in  data:
        print(i)
        
def search(data):
    # Поиск по справочнику.
    flag = 1
    name = input('имя > ')
    for line in data:
        if name in line:
            flag = 0
            print(line)
    if flag: print('no name given')
    
data = readfile('data.txt') # При запуске программы (скрипта), она должна считывать содержимое
dict_command = {'1' :  scan, '2' : search} # словарь команд, в значениях функции их исполняющие
 
print('''Команды для работы со справочником:
    Просмотр всех записей справочника:  - 1
    Поиск по справочнику -2
    Добавление новой записи - 3
     Удаление записи из справочника по Имени и Фамилии - 4
     Изменение любого поля в определенной записи справочника - 5 
     Вывод возраста человека (записи) по Имени и Фамилии - 6 ''')
 
while True:
    command = input('Команда: > ')
    if command in dict_command:
        dict_command[command](data)
    else:
        print(' command error!')
0
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
23.11.2019, 10:29
Semen-Semenich, Я уважаю Вашу работоспособность при разработке громоздких кодов. Но замечу, что наиболее трудоемкую часть ( из за которой я говорил, что нужно использовать базу данных) Вы не реализовали. Это задача указанная в условии
Цитата Сообщение от Ekaterina56 Посмотреть сообщение
Поиск может осуществляться по любому из полей, а также по нескольким
полям одновременно
У Вас реализован поиск только по одному полю, по имени (name). Базы данных как раз и создаются, что бы поиск можно было осуществлять по любому полю или по нескольким полям одновременно.
Вы выложили только часть кода? Потому, что я не вижу где вносятся изменения в поля записи и где происходит запись (сохранение) этих изменений в файл. Может я что то недопонимаю?

Добавлено через 30 минут
И еще, основное достоинство баз данных, что при работе с ней база данных не перезаписывается целиком, а перезаписывается только та запись, в которую вносятся изменения. Я не представляю, как можно в текстовом файле изменять одну запись не трогая другие. Ведь в текстовом файле, как я понимаю для удаления одной записи или добавлении ее в середину повлечет перезапись всего, что располагается ниже ее. Интересно, как Вы будете заменять внутри таблицы запись, которую Вы изменили. В базах данных для этого существуют встроенные средства. Ведь Вы должны отслеживать, что бы размеры полей при вводе новой записи или при изменении существующей не превышали определенной длины. Все это придется контролировать. В случае использования формы, эту проблему можно было бы снять. Но я убедился, что использование формы значительно увеличивает размеры кода. В общем мне кажется, что проблем полно, за которые Вы еще даже не брались. В моем понимании текстовый файл в виде таблицы можно использовать только для нескольких записей, скажем с десяток, но не для большого количества записей. На этот случай были придуманы и разработаны базы данных.

Добавлено через 10 минут
Может конечно это просто задание данное преподавателем в процессе обучения. Тогда еще можно понять использование текстового файла. Потому что для практического применения, там где используются сотни записей, такой подход не эффективен. С другой стороны, для учебного процесса это задание уж очень громоздко.
0
 Аватар для Semen-Semenich
5222 / 3469 / 1173
Регистрация: 21.03.2016
Сообщений: 8,295
23.11.2019, 13:42
Viktorrus, я и не пытался это все реализовывать. я показал примерно как на вопрос автора
Цитата Сообщение от Ekaterina56 Посмотреть сообщение
Возник вопрос как объединить их так, чтобы пользователю при запуске программы выходило меню и предлагалось выбрать одну из представленных операций (по номерам). При выборе номера запускался процесс выполнения операции.
а реализовать все что требуется в задаче это задача автора. нет ни формата хранения данных, я привел просто пример. я бы вообще создал класс персона где реализовал бы методы которые возвращают требуемые поля и хранил бы объекты в базе. как то так. а можно просто функциями. все зависит от уровня знаний автора или требований согласно программе обучения
0
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
23.11.2019, 19:42
Semen-Semenich, Я аналогичный справочник создал для себя используя два класса, класс "Книга" и класс "Запись". И создал форму, что бы работать с этим Телефонным справочником. Правда у меня в этом коде нет проверок на ошибки. Их я добавил когда стал создавать шаблон, в котором не указывается область применения. а создается некий безликий журнал с записями имеющими безликие поля. И по определенной методики можно привязать этот журнал записей к любой тематике, простым способом заменив безликие названия полей на связанные с тематикой. Количеством полей можно варьировать, но максимум ограничен размерами экрана. А вот количество записей не ограничено, так как реализован механизм листания страниц, так как на одной странице в форме на весь экран умещается 25 записей. Хранится все в питоновской базе данных созданной с помощью модуля shelve. Кстати используя этот шаблон, каталог для книг я создал за 20 мин. Используя этот шаблон я могу быстро создавать телефонные книги, складские каталоги и любой журнал на любую тематику состоящий из некоторых записей. Это конечно примитивно по сравнению с существующими СУБД, но зато быстро решает простые задачи, которые можно свести к журналу и записям в нем. Поиск там тоже есть. Он ищит заданную подстроку по всем полям, во всех записях в журнале. И в том числе поиск в выбранных записях. Поэтому поиск по условиям в нескольких полях выполняется поэтапно. Ищется по одному условию, потом в найденных записях ищется по другому условию.
0
0 / 0 / 0
Регистрация: 22.11.2019
Сообщений: 7
24.11.2019, 18:47  [ТС]
Добавила ограничения на ввод данных и все сломалось...
Как правильно их вставить?

Ввод новой записи
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Member:
    def __init__(self, last_name=None, name=None, phone_number=None, from_line=None):
        if from_line is None:
            self.last_name = last_name
            try:
                text_1 = '{}'.format("Введите, пожалуйста, буквы", last_name, '>>>')
                Last_name = float(input(text_1))
                return last_namename
            except ValueError:
                print("Please reinsert")
            self.name = name
            try:
                text_2 = '{}'.format("Введите, пожалуйста, буквы", name, '>>>')
                name = float(input(text_2))
                return name
            except ValueError:
                print("Please reinsert")
            self.phone_number = phone_number
            try:
                text_3 = '{}'.format("Введите, пожалуйста, числа", phone_number, '>>>')
                phone_number = float(input(text_3))
                return phone_number
            except ValueError:
                print("Please reinsert")
        else:
            self.last_name, self.name, self.phone_number = str(from_line).replace(" ", '').split("|")
 
    def input_characters(self):
        self.last_name = input("Введите фамилию: ").capitalize()
        self.name = input("Введите имя: ").capitalize()
        self.phone_number = input("Введите номер телефона: +7 ").capitalize()
 
    def __str__(self):
        return '{0:10} | {1:10} | {2}'.format(self.last_name, self.name, self.phone_number) + '\n'
0
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
25.11.2019, 04:51
Ekaterina56, Ваша ошибка из за того, что Вы не совсем понимаете технологию ООП. В реальности у Вас есть объект "Запись в телефонной книге" , которая является экземпляром класса всех существующих записей в телефонной книге. Вы этот класс назвали Member. Вы видели где нибудь в реальной телефонной книге, что бы когда Вы в нее записываете телефон, то что бы запись из книги ограничивала, что Вы туда пишете? Нет. Значит в классе не должно быть метода проверяющего, что вы заносите в телефонную книгу. Ввод данных и проверка их корректности должны производиться вне класса. А в класс должны поступать в качестве аргументов уже проверенные данные.
Поэтому выведите ввод и проверку данных за пределы класса.
Описываете класс а потом в блоке
Python
1
if __name__ == '__main__':
пишете код работы с записью .
Осуществляете ввод данных и их проверку. Затем создаете экземпляр записи передавая ей введенные данные в виде аргументов.
И продолжаете работать с этой записью, делая с ней то, что Вам нужно. Например записываете ее в файл.

Добавлено через 11 минут
Ekaterina56, Скажите. Это учебное задание, от которого Вы не можете отступать? Просто работать с текстовым файлом очень не удобно. Много лишней работы.

Добавлено через 11 минут
Если это учебное задание, тогда использование текстового файла может быть оправдано. Лишняя работа используется для углубленного изучения программирования на питоне, пока Вы не изучали работу с базами данных. Последние упрощают программирование, беря на себя часть работы.
0
 Аватар для Semen-Semenich
5222 / 3469 / 1173
Регистрация: 21.03.2016
Сообщений: 8,295
25.11.2019, 15:40
Цитата Сообщение от Ekaterina56 Посмотреть сообщение
Добавила ограничения на ввод данных и все сломалось..
ну если в машину налить солярку вместо бензина она тоже сломается хотя обе жидкости топливо. как сказал выше Viktorrus, в экземпляр класса должны поступать корректные данные под который этот класс написан, отсюда следует что получение всех данных и их проверку нужно проводить вне класса.
0
0 / 0 / 0
Регистрация: 22.11.2019
Сообщений: 7
25.11.2019, 19:58  [ТС]
Это учебное задание. Была не знакома ни с одним языком программирования. Но в рамках учебы пришлось изучать питон..

Добавлено через 11 минут
Только все идет очень плохо и непонятно...

Добавлено через 19 минут
Отдельными операциями я написала все нужные функции, теперь надо к каждому добавить ограничения и сделать так, чтобы программа не останавливалась из-за ошибки (когда пользователь, что-то не так вводит), а сообщала ему об этом и предлагала повторный ввод
0
 Аватар для Semen-Semenich
5222 / 3469 / 1173
Регистрация: 21.03.2016
Сообщений: 8,295
25.11.2019, 20:14
Ekaterina56, все не совсем плохо. есть этот форум и ваше желание подкрепленное попытками с кодом. давайте начнем сначала. мне тоже интересно что из этого получиться.
Python
1
2
3
4
5
6
7
print('''Команды для работы со справочником:
    Просмотр всех записей справочника:  - 1
    Поиск по справочнику -2
    Добавление новой записи - 3
     Удаление записи из справочника по Имени и Фамилии - 4
     Изменение любого поля в определенной записи справочника - 5 
     Вывод возраста человека (записи) по Имени и Фамилии - 6 ''')
как нам понятно из первого пункта и и самого условия задачи что бы просмотреть все записи их надо получить то есть считать из файла, значить первое что нам нужно так это считать данные в переменную. данные будем хранить в тестовом файле в виде строк - 'сидоров иван +79091234567 45 москва' (для начала потом перейдем к объектам) вот начните с этого напишите две функции считать из файла и показать все записи.
пока писал вы уже дописали часть текста и я не видел.
Цитата Сообщение от Ekaterina56 Посмотреть сообщение
теперь надо к каждому добавить ограничения и сделать так, чтобы программа не останавливалась из-за ошибки
вам не нужно к каждому добавлять, вам это нужно все в отдельном участке кода или функции написать. привидите пример что нужно ограничивать.
0
0 / 0 / 0
Регистрация: 22.11.2019
Сообщений: 7
25.11.2019, 20:41  [ТС]
Ограничивать ввод данных от пользователя, чтобы имя, телефон и возраст были корректны. Если пользователь вводит вместо букв цифры и наоборот, то выдать ему ошибку "неправильный ввод". Знаю, что это можно сделать с помощью Try и except, но куда и как правильно вставить это в скрипт не понятно...
В питоне есть какая-либо функция для дат?
Я могу сделать после поиска еще дополнительные функции: выход или изменение контакта? или же лучше прописать это как отдельную функцию?
Чтобы после выполнения операции пользователю возвращалось меню, можно использовать цикл while и в отдельном пункте меню прописать операцию "выход"?

Добавлено через 6 минут
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Member:
    def __init__(self, surname=None, name=None, phone_number=None, from_line=None, age=None):
        if from_line is None:
            self.surname = surname
            self.name = name
            self.phone_number = phone_number
            self.age = age
        else:
            self.surname, self.name, self.phone_number, self.age = str(from_line).replace(" ", '').split("|")
 
    def input_characters(self):
        self.surname = input("Enter surname: ").capitalize()
        self.name = input("Enter name: ").capitalize()
        self.phone_number = input("Enter number phone: ").capitalize()
        self.age = input("Enter age: ").capitalize()
 
    def __str__(self):
        return '{0:10} | {1:10} | {2.2.4} | {2}'.format(self.surname, self.name, self.age, self.phone_number) + '\n'
Неуверенна в правильности ввода даты..
0
 Аватар для Semen-Semenich
5222 / 3469 / 1173
Регистрация: 21.03.2016
Сообщений: 8,295
25.11.2019, 21:24
ну вот пример, функция проверяет корректность ввода имени и фамилии и возвращает с заглавной буквой
Python
1
2
3
4
5
6
7
8
9
def correct_name(text):
    name = input(f'{text} ')
    while not all(map(str.isalpha,name)):
        print('не корректный ввод')
        name = input(f'{text} ')
    return name.capitalize()
    
name = correct_name('имя')
surname = correct_name('фамилия')
или если так не совсем понятно то же самое
Python
1
2
3
4
5
6
7
def correct_name(text):
    name = input(f'{text} ')
    while True:
        if name.isalpha():
            return name.capitalize()
        print('не корректный ввод')
        name = input(f'{text} ')
вот теперь вы получите имя и фамилию корректно (ну не совсем конечно Ян-Болг не прокатит а такое встречается)
теперь то же самое для телефона. проверяете что номер содержит + и 11 цифр или 12 цифр если через 8 записан. можно регуляркой а можно парсить входную строку или явно указывать при вводе формат ввода типа номер через + и без пробелов.

Добавлено через 10 минут
вот проверка номера (без заморочек)
Python
1
2
3
4
5
6
7
8
9
def correct_number():
    number = input('номер +7 код номер без пробелов -> ')
    while True:
        if number[0] == '+' and number[1:].isdigit() and len(number) == 12:
            return number
        print('не корректный ввод')
        number = input('номер +7 код номер без пробелов -> ')
    
number = correct_number()
теперь у вас 2 функции и 3 корректных ввода. то же самое для возраста напишите
0
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
25.11.2019, 21:39
Ekaterina56, Опять Вы ввод данных пытаетесь осуществлять с помощью метода класса. Выведете функцию запроса данных за пределы класса. У Вас вообще кроме определения класса ничего нет. А где у Вас будет запрос на создание экземпляра класса?
Python
1
rec = Member(аргументы)
Изнутри класса это делать нельзя.
Определите функцию ввода и проверки данных за пределами класса ниже него. А после того, как определити класс и все функции, которые не входят в класс, создайте блок
Python
1
if __name__ == '__main__':
и в нем вызываете функцию ввода и проверки данных, а так же создавайте экземпляр класса с аргументами из введенных данных.

Добавлено через 3 минуты
Semen-Semenich, выложил Вам функции проверки введенных данных, но это тоже нужно разместить за пределами класса.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.11.2019, 21:39
Помогаю со студенческими работами здесь

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

Класс "Телефонный справочник"
Я только начал изучать Python. Сам себе придумал задание и пытаюсь его сделать. Условие: Создать класс "Телефонный...

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

Телефонный номер
Здравствуйте, помогите пожалуйста с задачей, не могу понять как решается, спасибо! Дан телефонный номер. Напишите программу которая...

Вывести телефонный номер с необходимыми разделителями
Помогите пожалуйста с задачей: С помощью re.sub написать код, который на вход получает номер телефона, а на выход расписывает этот номер...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru