Форум программистов, компьютерный форум, киберфорум
acmades
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

С++ «Неделя третья - Введение в структуры и классы - Имена и фамилии» #17

Запись от acmades размещена 21.08.2017 в 17:29
Показов 83774 Комментарии 2

Третья неделя обучения на coursera.org
Структуры и классы - интересная тема. Некоторые задания долго разбирал.

Для начала маленькое задание:
Реализуйте класс, поддерживающий набор строк в отсортированном порядке. Класс должен содержать два публичных метода:
C++
1
2
3
4
5
6
7
8
9
10
11
class SortedStrings {
public:
  void AddString(const string& s) {
    // добавить строку s в набор
  }
  vector<string> GetSortedStrings() {
    // получить набор из всех добавленных строк в отсортированном порядке
  }
private:
  // приватные поля
};
Пример:
Код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void PrintSortedStrings(SortedStrings& strings) {
  for (const string& s : strings.GetSortedStrings()) {
    cout << s << " ";
  }
  cout << endl;
}
 
int main() {
  SortedStrings strings;
  
  strings.AddString("first");
  strings.AddString("third");
  strings.AddString("second");
  PrintSortedStrings(strings);
  
  strings.AddString("second");
  PrintSortedStrings(strings);
  
  return 0;
}
Вывод
C++
1
2
first second third
first second second third
Моё решение:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
class SortedStrings {
public:
  void AddString(const string& s) {
    v.push_back(s); //добавим строку
  }
  vector<string> GetSortedStrings() {
    sort(begin(v), end(v)); //отсортируем вектор строк
    return v; //и вернем вектор
  }
private:
  vector<string> v; //так будут строки храниться
};
Следующее задание: Имена и фамилии
Реализуйте класс для человека, поддерживающий историю изменений человеком своих фамилии и имени.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
public:
  void ChangeFirstName(int year, const string& first_name) {
    // добавить факт изменения имени на first_name в год year
  }
  void ChangeLastName(int year, const string& last_name) {
    // добавить факт изменения фамилии на last_name в год year
  }
  string GetFullName(int year) {
    // получить имя и фамилию по состоянию на конец года year
  }
private:
  // приватные поля
};
Считайте, что в каждый год может произойти не более одного изменения фамилии и не более одного изменения имени. При этом с течением времени могут открываться всё новые факты из прошлого человека, поэтому года́ в последовательных вызовах методов ChangeLastName и ChangeFirstName не обязаны возрастать.

Гарантируется, что все имена и фамилии непусты.
Строка, возвращаемая методом GetFullName, должна содержать разделённые одним пробелом имя и фамилию человека по состоянию на конец данного года.
Если к данному году не случилось ни одного изменения фамилии и имени, верните строку "Incognito".
Если к данному году случилось изменение фамилии, но не было ни одного изменения имени, верните "last_name with unknown first name".
Если к данному году случилось изменение имени, но не было ни одного изменения фамилии, верните "first_name with unknown last name".

Пример
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main() {
  Person person;
  
  person.ChangeFirstName(1965, "Polina");
  person.ChangeLastName(1967, "Sergeeva");
  for (int year : {1900, 1965, 1990}) {
    cout << person.GetFullName(year) << endl;
  }
  
  person.ChangeFirstName(1970, "Appolinaria");
  for (int year : {1969, 1970}) {
    cout << person.GetFullName(year) << endl;
  }
  
  person.ChangeLastName(1968, "Volkova");
  for (int year : {1969, 1970}) {
    cout << person.GetFullName(year) << endl;
  }
  
  return 0;
}
Вывод
C++
1
2
3
4
5
6
7
Incognito
Polina with unknown last name
Polina Sergeeva
Polina Sergeeva
Appolinaria Sergeeva
Polina Volkova
Appolinaria Volkova
Моё решение:
C++
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
37
38
39
40
41
42
43
44
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct FullName { //создадим структуру из имени и фамилии
    string Name;
    string Soname;
};
class Person {
public:
    void ChangeFirstName(int year, const string& first_name) {
        if (YearNameSoname.count(year) == 0) YearNameSoname[year].Soname = ""; //если такого года еще нет, то добавим пустую фамилию в этот год
        YearNameSoname[year].Name = first_name; //добавим указанное имя
    }
    void ChangeLastName(int year, const string& last_name) {
        if (YearNameSoname.count(year) == 0) YearNameSoname[year].Name = ""; //если такого года еще нет, то добавим пустое имя в этот год
        YearNameSoname[year].Soname = last_name; //и добавим указанную фамилию
    }
    string GetFullName(int year) {
        if (YearNameSoname.size() == 0) { //если размер = 0
            return "Incognito"; //выводим Инкогнито
        }
        else { //ну или так
            for (const auto& i : YearNameSoname) {
                if (year < i.first) return "Incognito"; //если искомый год меньше первого года изменения, выводим Инкогнито
                break; //сразу выходим из цикла
            }
        }
        //иначе
        string nm = "";
        string sn = "";
        for (const auto& i : YearNameSoname) { //полистаем нашу структуру, (не стал отдельно функцию делать)
            //и будем присваивать переменной sn значение фамилии, если она не пустая и пока искомый год больше текущего(в структуре)
            if (i.first <= year && i.second.Soname != "") sn = i.second.Soname;
            //тоже самое с именем
            if (i.first <= year && i.second.Name != "") nm = i.second.Name;
        }
        if(nm == "") return sn + " with unknown first name"; //условие, если имя пустое(вывод фамилии и текста)
        else if(sn == "") return nm + " with unknown last name"; //условие, если фамилия пуста (вывод имени и текста)
        else return nm + " " + sn; //вывод имени и фамилии
    }
private: //объявим в приватной секции
    map<int, FullName> YearNameSoname; //структуру с годом и полным именем
};
Ещё задача:
Дополните класс из предыдущей задачи «Имена и фамилии — 1» методом GetFullNameWithHistory:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person {
public:
  void ChangeFirstName(int year, const string& first_name) {
    // добавить факт изменения имени на first_name в год year
  }
  void ChangeLastName(int year, const string& last_name) {
    // добавить факт изменения фамилии на last_name в год year
  }
  string GetFullName(int year) {
    // получить имя и фамилию по состоянию на конец года year
  }
  string GetFullNameWithHistory(int year) {
    // получить все имена и фамилии по состоянию на конец года year
  }
private:
  // приватные поля
};
В отличие от метода GetFullName, метод GetFullNameWithHistory должен вернуть не только последние имя и фамилию к концу данного года, но ещё и все предыдущие имена и фамилии в обратном хронологическом порядке. Если текущие факты говорят о том, что человек два раза подряд изменил фамилию или имя на одно и то же, второе изменение при формировании истории нужно игнорировать.
Пример:
C++
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
int main() {
  Person person;
  
  person.ChangeFirstName(1965, "Polina");
  person.ChangeLastName(1967, "Sergeeva");
  for (int year : {1900, 1965, 1990}) {
    cout << person.GetFullNameWithHistory(year) << endl;
  }
  
  person.ChangeFirstName(1970, "Appolinaria");
  for (int year : {1969, 1970}) {
    cout << person.GetFullNameWithHistory(year) << endl;
  }
  
  person.ChangeLastName(1968, "Volkova");
  for (int year : {1969, 1970}) {
    cout << person.GetFullNameWithHistory(year) << endl;
  }
  
  person.ChangeFirstName(1990, "Polina");
  person.ChangeLastName(1990, "Volkova-Sergeeva");
  cout << person.GetFullNameWithHistory(1990) << endl;
  
  person.ChangeFirstName(1966, "Pauline");
  cout << person.GetFullNameWithHistory(1966) << endl;
  
  person.ChangeLastName(1960, "Sergeeva");
  for (int year : {1960, 1967}) {
    cout << person.GetFullNameWithHistory(year) << endl;
  }
  
  person.ChangeLastName(1961, "Ivanova");
  cout << person.GetFullNameWithHistory(1967) << endl;
  
  return 0;
}
Вывод:
C++
1
2
3
4
5
6
7
8
9
10
11
12
Incognito
Polina with unknown last name
Polina Sergeeva
Polina Sergeeva
Appolinaria (Polina) Sergeeva
Polina Volkova (Sergeeva)
Appolinaria (Polina) Volkova (Sergeeva)
Polina (Appolinaria, Polina) Volkova-Sergeeva (Volkova, Sergeeva)
Pauline (Polina) with unknown last name
Sergeeva with unknown first name
Pauline (Polina) Sergeeva
Pauline (Polina) Sergeeva (Ivanova, Sergeeva)
Моё решение:
C++
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
struct FullName { //создадим структуру из имени и фамилии
    string Name;
    string Soname;
};
class Person {
public:
    void ChangeFirstName(int year, const string& first_name) {
        if (YearNameSoname.count(year) == 0) YearNameSoname[year].Soname = ""; //если такого года еще нет, то добавим пустую фамилию
        YearNameSoname[year].Name = first_name; //добавим указанное имя
    }
    void ChangeLastName(int year, const string& last_name) {
        if (YearNameSoname.count(year) == 0) YearNameSoname[year].Name = ""; //если такого года еще нет, то добавим пустое имя
        YearNameSoname[year].Soname = last_name; //и добавим указанную фамилию
    }
    string GetFullName(int year) {
        if (YearNameSoname.size() == 0) { //если размер = 0
            return "Incognito"; //выводим Инкогнито
        }
        else {
            for (const auto& i : YearNameSoname) {
                if (year < i.first) return "Incognito"; //если искомый год меньше первого года изменения, выводим Инкогнито
                break; //сразу выходим из цикла
            }
        }
        //иначе
        string nm = "";
        string sn = "";
        for (const auto& i : YearNameSoname) { //полистаем нашу структуру
            //и будем присваивать переменной sn значение фамилии, если она не пустая и пока искомый год больше текущего(в структуре)
            if (i.first <= year && i.second.Soname != "") sn = i.second.Soname;
            if (i.first <= year && i.second.Name != "") nm = i.second.Name; //тоже самое с именем
        }
        if(nm == "") return sn + " with unknown first name"; //условие, если имя пустое(вывод фамилии и текста)
        else if(sn == "") return nm + " with unknown last name"; //условие, если фамилия пуста (вывод имени и текста)
        else return nm + " " + sn; //вывод имени и фамилии
    }
    string GetFullNameWithHistory(int year) {
        if (YearNameSoname.size() == 0) { //если размер = 0
            return "Incognito"; //выводим Инкогнито
        }
        else {
            for (const auto& i : YearNameSoname) {
                if (year < i.first) return "Incognito"; //если искомый год меньше первого года изменения, выводим Инкогнито
                break; //сразу выходим из цикла
            }
        }
        //иначе
        string nm = "";
        string sn = "";
        vector<string> secondnames; //вектор предыдущих фамилий
        vector<string> firstnames; //вектор предыдущих имен
        for (const auto& i : YearNameSoname) { //полистаем нашу структуру
            //и будем присваивать переменной sn значение фамилии, если она не пустая и пока искомый год больше текущего(в структуре)
            if (i.first <= year && i.second.Soname != "") { //если Фамилия непуста
                if (i.second.Soname != sn && sn != "") { //и не повторяется
                    secondnames.push_back(sn);
                }
                sn = i.second.Soname; //тут присваиваем
            }
            if (i.first <= year && i.second.Name != "") { //то же самое с Именем
                if (i.second.Name != nm && nm != "") {
                    firstnames.push_back(nm);
                }
                nm = i.second.Name;
            }
        }
        //инициализируем переменные в которые будем складывать фамилии и имена в обратном порядке
        string secnames_string = "", firstnames_string = "";
        if (secondnames.size() > 0) { //если вектор с фамилиями не пуст, то
            secnames_string += " (" + secondnames[secondnames.size() - 1]; //добавим в строку пробел, скобку и предыдущую фамилию
            if (secondnames.size() > 1) {
                for (int i = secondnames.size() - 1; i > 0; --i) {//в обратном порядке
                    secnames_string += ", " + secondnames[i - 1]; // добавим в строку остальные фамилии
                }
            }
            secnames_string += ")"; //закроем строку скобкой
        }
        //аналогично с именами
        if (firstnames.size() > 0) {
            firstnames_string += " (" + firstnames[firstnames.size() - 1];
            if (firstnames.size() >1) {
                for (int i = firstnames.size() - 1; i > 0; --i) {
                    firstnames_string += ", " + firstnames[i - 1];
                }
            }
            firstnames_string += ")";
        }
        //в зависимости от наличия Имени и Фамилии, вернем соответствующие сообщения
        if (nm == "") return sn + secnames_string + " with unknown first name";
        else if (sn == "") return nm + firstnames_string + " with unknown last name";
        else return nm + firstnames_string + " " + sn + secnames_string;
    }
private: //объявим в приватной секции
    map<int, FullName> YearNameSoname; //структуру с годом и полным именем
};
Немного переборщил с кодом. Но думаю для собственного понимания пойдет. Можете предложить свою оптимизацию )))

Ещё задача:
Дополните класс Person из задачи «Имена и фамилии — 2» конструктором, позволяющим задать имя и фамилию человека при рождении, а также сам год рождения. Класс не должен иметь конструктора по умолчанию.

При получении на вход года, который меньше года рождения:
  • методы GetFullName и GetFullNameWithHistory должны отдавать "No person";
  • методы ChangeFirstName и ChangeLastName должны игнорировать запрос.
Кроме того, необходимо объявить константными все методы, которые по сути ими являются.
Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
  Person person("Polina", "Sergeeva", 1960);
  for (int year : {1959, 1960}) {
    cout << person.GetFullNameWithHistory(year) << endl;
  }
  
  person.ChangeFirstName(1965, "Appolinaria");
  person.ChangeLastName(1967, "Ivanova");
  for (int year : {1965, 1967}) {
    cout << person.GetFullNameWithHistory(year) << endl;
  }
 
  return 0;
}
Вывод:
C++
1
2
3
4
No person
Polina Sergeeva
Appolinaria (Polina) Sergeeva
Appolinaria (Polina) Ivanova (Sergeeva)
Моё решение:
C++
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
struct FullName { //создадим структуру из имени и фамилии
    string Name;
    string Soname;
};
class Person {
public:
    Person(const string& first_name, const string& last_name, int year) {
        YearNameSoname[year] = { first_name, last_name };
        birth_year = year;
        for (auto& i : YearNameSoname) {
            if (i.first < year) YearNameSoname.erase(i.first);
        }
    }
    void ChangeFirstName(int year, const string& first_name) {
        for (auto& i : YearNameSoname) {
            if (year > i.first) {
                if (YearNameSoname.count(year) == 0) YearNameSoname[year].Soname = ""; //если такого года еще нет, то добавим пустую фамилию
                YearNameSoname[year].Name = first_name; //добавим указанное имя
            }
            break;//сразу выходим
        }
    }
    void ChangeLastName(int year, const string& last_name) {
        for (auto& i : YearNameSoname) {
            if (year > i.first) {
                if (YearNameSoname.count(year) == 0) YearNameSoname[year].Name = ""; //если такого года еще нет, то добавим пустое имя
                YearNameSoname[year].Soname = last_name; //и добавим указанную фамилию
            }
            break; //сразу выходим
        }
    }
    string GetFullName(int year) const {
        if (birth_year != 0 && year < birth_year) return "No person";
        else if (YearNameSoname.size() == 0) { //если размер = 0
            return "Incognito"; //выводим Инкогнито
        }
        else {
            for (const auto& i : YearNameSoname) {
                if (year < i.first) return "Incognito"; //если искомый год меньше первого года изменения, выводим Инкогнито
                break; //сразу выходим из цикла
            }
        }
        //иначе
        string nm = "";
        string sn = "";
        for (const auto& i : YearNameSoname) { //полистаем нашу структуру
                                               //и будем присваивать переменной sn значение фамилии, если она не пустая и пока искомый год больше текущего(в структуре)
            if (i.first <= year && i.second.Soname != "") sn = i.second.Soname;
            if (i.first <= year && i.second.Name != "") nm = i.second.Name; //тоже самое с именем
        }
        if (nm == "") return sn + " with unknown first name"; //условие, если имя пустое(вывод фамилии и текста)
        else if (sn == "") return nm + " with unknown last name"; //условие, если фамилия пуста (вывод имени и текста)
        else return nm + " " + sn; //вывод имени и фамилии
    }
    string GetFullNameWithHistory(int year) const {
        if (birth_year != 0 && year < birth_year) return "No person";
        else if (YearNameSoname.size() == 0) { //если размер = 0
            return "Incognito"; //выводим Инкогнито
        }
        else {
            for (const auto& i : YearNameSoname) {
                if (year < i.first) return "Incognito"; //если искомый год меньше первого года изменения, выводим Инкогнито
                break; //сразу выходим из цикла
            }
        }
        //иначе
        string nm = "";
        string sn = "";
        vector<string> secondnames; //вектор предыдущих фамилий
        vector<string> firstnames; //вектор предыдущих имен
        for (const auto& i : YearNameSoname) { //полистаем нашу структуру
                                               //и будем присваивать переменной sn значение фамилии, если она не пустая и пока искомый год больше текущего(в структуре)
            if (i.first <= year && i.second.Soname != "") {
                if (i.second.Soname != sn && sn != "") {
                    secondnames.push_back(sn);
                }
                sn = i.second.Soname;
            }
            if (i.first <= year && i.second.Name != "") {
                if (i.second.Name != nm && nm != "") {
                    firstnames.push_back(nm);
                }
                nm = i.second.Name;
            }
        }
        //инициализируем переменные в которые будем складывать фамилии и имена в обратном порядке
        string secnames_string = "", firstnames_string = "";
        if (secondnames.size() > 0) { //если вектор с фамилиями не пуст, то
            secnames_string += " (" + secondnames[secondnames.size() - 1]; //добавим в строку пробел, скобку и предыдущую фамилию
            if (secondnames.size() > 1) {
                for (int i = secondnames.size() - 1; i > 0; --i) {//в обратном порядке
                    secnames_string += ", " + secondnames[i - 1]; // добавим в строку остальные фамилии
                }
            }
            secnames_string += ")"; //закроем строку скобкой
        }
        //аналогично с именами
        if (firstnames.size() > 0) {
            firstnames_string += " (" + firstnames[firstnames.size() - 1];
            if (firstnames.size() >1) {
                for (int i = firstnames.size() - 1; i > 0; --i) {
                    firstnames_string += ", " + firstnames[i - 1];
                }
            }
            firstnames_string += ")";
        }
 
        if (nm == "") return sn + secnames_string + " with unknown first name";
        else if (sn == "") return nm + firstnames_string + " with unknown last name";
        else return nm + firstnames_string + " " + sn + secnames_string;
    }
private: //объявим в приватной секции
    map<int, FullName> YearNameSoname; //структуру с годом и полным именем
    int birth_year = 0;
};
Продолжение следует...
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 2
Комментарии
  1. Старый комментарий
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    class SortedStrings {
    public:
      void AddString(const string& s) {
        // добавить строку s в набор
        vstrings.push_back(s);
      }
      vector<string> GetSortedStrings() {
        // получить набор из всех добавленных строк в отсортированном порядке
        sort(vstrings.begin(), vstrings.end());
        return vstrings;
      }
    private:
      // приватные поля
      vector<string> vstrings;
    };
    Запись от flash_back размещена 24.10.2017 в 13:34 flash_back вне форума
  2. Старый комментарий
    Аватар для Avazart
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
     void AddString(const string& s) 
    {
        v.push_back(s); //добавим строку
    }
     
    vector<string> GetSortedStrings() 
    {
        sort(begin(v), end(v)); //отсортируем вектор строк
        return v; //и вернем вектор
    }
    Почему бы сразу не содержать строки в отсортированном порядке? Т.е вставлять строку сразу в нужно место "по старшинству" ?

    Или ввести признак отсортированности что бы не сортировать повторно при повторных вызовах методах.
    Запись от Avazart размещена 25.10.2017 в 14:05 Avazart вне форума
 
Новые блоги и статьи
Nekobox - outbounds[0].transport: unknown transport type: raw
damix 01.10.2026
Фикс ошибки Правым кликом по серверу -> отладочная информация -> edit Заменить "net": "raw", на "net": "tcp", Нажать кнопку reload.
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru