Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.83
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
#1

Написать программу, создающую два потока, которые выполняются в одном адресном пространстве (в одном процессе) - C++

17.12.2011, 21:19. Просмотров 3083. Ответов 25
Метки нет (Все метки)

Здравствуйте!
Есть задание: Написать программу, создающую два потока, которые выполняются в одном адресном пространстве (в одном процессе). Их разделяемый ресурс - целочисленный массив, который содержит данные совместного использования. Потоки должны обрабатывать массив поочередно. Использовать критическую секцию для синхронизации. Пример обработки массива: нахождение суммы всех элементов, вывод этой суммы на экран и запись её в первый элемент массива.

Есть код:
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
#include <windows.h>
#include <stdio.h>
 
CRITICAL_SECTION cs = {0};
int a[]= {1,2,3};
 
 
DWORD WINAPI SUM(LPVOID param)
{
    int i=0;
    int sum;
    while(TRUE)
    {
        EnterCriticalSection(&cs);
        sum = 0;
        for(i=0; i<3; i++)
        {
            sum=sum+a[i];
        }
        a[0]=sum;
       
        LeaveCriticalSection(&cs);
        if (a[0] > 100) return 0;
    }
    return 0;
}
DWORD WINAPI PRINT(LPVOID param)
{
    while (TRUE)
    {
        EnterCriticalSection(&cs);
        printf("%d %d %d \n",a[0],a[1],a[2]);
        LeaveCriticalSection(&cs);
        if (a[0] > 100) return 0;
    }
    return 0;
}
 
int main(void)
{
    HANDLE THR[1];
 
    InitializeCriticalSection(&cs);
 
    THR[0]=CreateThread(NULL, 0, PRINT, NULL , 0, NULL);
    THR[1]=CreateThread(NULL, 0, SUM, NULL, 0, NULL);
 
    WaitForMultipleObjects(2, THR, TRUE, INFINITE);
 
    CloseHandle(THR[0]);
    CloseHandle(THR[1]);
    DeleteCriticalSection(&cs);
 
    getchar();
    return 0;
}
Желаемо, чтобы в итоге выводил нечто вроде:
6 2 3
11 2 3
16 2 3
.........
101 2 3,
а вместо этого:
101 2 3.
Пожалуйста помогите разобраться. Заранее спасибо!

Добавлено через 20 часов 0 минут
Господа, пожалуйста, помощь нужна!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.12.2011, 21:19
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Написать программу, создающую два потока, которые выполняются в одном адресном пространстве (в одном процессе) (C++):

Как сделать несколько функций в одном срр ?Написал программы, которые нужно поочередно запустить в одном срр
#include &lt;iostream&gt; void func(double&amp; x,double&amp; y) { double temp_min =...

Даны два слова, напечатать только те символы, которые встречаются только в одном из слов
помогите, пожалуйста, с программой:) Писать ее не нужно, просто нужно помочь...

Даны два слова. Напечатать только те буквы слов, которые есть только в одном из них
2.Даны два слова. Напечатать только те буквы слов, которые есть только в одном ...

Найти минимальный элемент и все элементы, расположение в одном ряду и в одном столбце с минимальным
Дана квадратная матрица A порядка n. Составить программу, которая находит...

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

Два консольный приложения в одном
Есть 2 разных консольных приложения... Нужно сделать так что бы они запускались...

25
alex_x_x
бжни
2454 / 1660 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
17.12.2011, 21:25 #2
final_sleep, критическую секцию нужно сменить на семафоры
твоя проблема в том, что записывающий поток не ждет, пока второй поток считает данные
0
xAtom
917 / 742 / 299
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
17.12.2011, 23:07 #3
Цитата Сообщение от final_sleep Посмотреть сообщение
HANDLE THR[1];
C++
1
HANDLE THR[2];
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
17.12.2011, 23:24  [ТС] #4
Дело в том, что нужно это сделать используя критическую секцию и только.

Добавлено через 54 секунды
xAtom, не сработало.

Добавлено через 9 минут
alex_x_x, проблема в том, что задание не сменить, и я знаю что люди делали чисто через крит. секцию.
есть вот такой пример кстати:
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
#include <windows.h>
#include <process.h>
#include <stdio.h>
 
CRITICAL_SECTION cs;
int a[ 5 ];
 
void Thread( void* pParams )
{
    int i, num = 0;
 
    while ( TRUE )
    {
        EnterCriticalSection( &cs );
        for ( i = 0; i < 5; i++ ) a[ i ] = num;
        LeaveCriticalSection( &cs );
        num++;
    }
}
 
int main( void )
 
{
    InitializeCriticalSection( &cs );
    _beginthread( Thread, 0, NULL );
 
    while( TRUE )
    {
        EnterCriticalSection( &cs );
        printf( "%d %d %d %d %d\n",
                a[ 0 ], a[ 1 ], a[ 2 ],
                a[ 3 ], a[ 4 ] );
        LeaveCriticalSection( &cs );
    }
    return 0;
}
0
alex_x_x
бжни
2454 / 1660 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
17.12.2011, 23:30 #5
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
#include <windows.h>
#include <stdio.h>
 
CRITICAL_SECTION cs_read, cs_write;
int a[]= {1,2,3};
 
 
DWORD WINAPI SUM(LPVOID param)
{
    int i=0;
    int sum;
    while(TRUE)
    {
        EnterCriticalSection(&cs_write);
        sum = 0;
        for(i=0; i<3; i++)
        {
            sum=sum+a[i];
        }
        a[0]=sum;
       
        LeaveCriticalSection(&cs_read);
        if (a[0] > 100) return 0;
    }
    return 0;
}
DWORD WINAPI PRINT(LPVOID param)
{
    while (TRUE)
    {
        EnterCriticalSection(&cs_read);
        printf("%d %d %d \n",a[0],a[1],a[2]);
        LeaveCriticalSection(&cs_write);
        if (a[0] > 100) return 0;
    }
    return 0;
}
 
int main(void)
{
    HANDLE THR[1];
 
    InitializeCriticalSection(&cs_read);
    InitializeCriticalSection(&cs_write);
    EnterCriticalSection(&cs_read);
 
    THR[0]=CreateThread(NULL, 0, PRINT, NULL , 0, NULL);
    THR[1]=CreateThread(NULL, 0, SUM, NULL, 0, NULL);
 
    WaitForMultipleObjects(2, THR, TRUE, INFINITE);
 
    CloseHandle(THR[0]);
    CloseHandle(THR[1]);
    DeleteCriticalSection(&cs_read);
    DeleteCriticalSection(&cs_write);
 
    getchar();
    return 0;
}
но я не помню позволяют критические секции рекурсивную блокировку или нет
но работать должно как-то так
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
17.12.2011, 23:39  [ТС] #6
alex_x_x, увы не то(
опять: 101 2 3
получается опять, что работает каким то хреном много много раз 1-й поток, а потом в конце второй 1 раз.
0
lavan
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
17.12.2011, 23:54 #7
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
#include<windows.h>
#include<iostream>
using namespace std;
CRITICAL_SECTION cs;
int ar[6];
void rand_arr();
void thr();
int main() {
 HANDLE htr;
 DWORD dwid;
 rand_arr();
 InitializeCriticalSection(&cs);
 htr=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)thr,NULL,0,&dwid);
  Sleep(20);
  for(int i=1;i<=5;i++) {
      EnterCriticalSection(&cs);
      cout<<ar[i]<<"-";
      LeaveCriticalSection(&cs);
  }
  cout<<"\nsum is "<<ar[0];
   DeleteCriticalSection(&cs);
   cin.get();
   return 0;
}
void rand_arr() {
    for(int i=1;i<=5;i++)
    ar[i]=rand()%20;
}
void thr() {
    for(int i=0;i<=5;i++) {
    EnterCriticalSection(&cs);
      ar[0]+=ar[i];
      LeaveCriticalSection(&cs);
    }
}
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
18.12.2011, 00:10  [ТС] #8
lavan, проблема таже.
мне нужно к слову чтобы было:
C++
1
a[]={1,2,3};
а в выводе нечто:
1 2 3
6 2 3
16 2 3
...

Чтобы было:
открылась cs в принте
закрылась cs в принте
открылась cs в сумме
закрылась cs в сумме
0
alex_x_x
бжни
2454 / 1660 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
18.12.2011, 00:29 #9
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
#include <windows.h>
#include <stdio.h>
 
CRITICAL_SECTION cs_read, cs_write;
int a[]= {1,2,3};
 
 
DWORD WINAPI SUM(LPVOID param)
{
    int i=0;
    int sum;
    while(TRUE)
    {
        sum = 0;
        for(i=0; i<3; i++)
        {
            sum=sum+a[i];
        }
        a[0]=sum; 
        LeaveCriticalSection(&cs_read);
        EnterCriticalSection(&cs_write);
        if (a[0] > 100) return 0;
    }
    return 0;
}
DWORD WINAPI PRINT(LPVOID param)
{
    while (TRUE)
    {
        EnterCriticalSection(&cs_read);
        printf("%d %d %d \n",a[0],a[1],a[2]);
        LeaveCriticalSection(&cs_write);
        if (a[0] > 100) return 0;
    }
    return 0;
}
 
int main(void)
{
    HANDLE THR[1];
 
    InitializeCriticalSection(&cs_read);
    InitializeCriticalSection(&cs_write);
    EnterCriticalSection(&cs_read);
    EnterCriticalSection(&cs_write);
 
    THR[0]=CreateThread(NULL, 0, PRINT, NULL , 0, NULL);
    THR[1]=CreateThread(NULL, 0, SUM, NULL, 0, NULL);
 
    WaitForMultipleObjects(2, THR, TRUE, INFINITE);
 
    CloseHandle(THR[0]);
    CloseHandle(THR[1]);
    DeleteCriticalSection(&cs_read);
    DeleteCriticalSection(&cs_write);
 
    system("pause");
    return 0;
}
а так?
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
18.12.2011, 01:50  [ТС] #10
alex_x_x, а так
6 2 3
6 2 3


Господа, кажется мне что все же косяк где-то простой, но я его не нахожу. Как я уже сказал вот этот код работает через критическую секцию:
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
#include <windows.h>
#include <process.h>
#include <stdio.h>
 
CRITICAL_SECTION cs;
int a[ 5 ];
 
void Thread( void* pParams )
{
    int i, num = 0;
 
    while ( TRUE )
    {
        EnterCriticalSection( &cs );
        for ( i = 0; i < 5; i++ ) a[ i ] = num;
        LeaveCriticalSection( &cs );
        num++;
    }
}
 
int main( void )
 
{
    InitializeCriticalSection( &cs );
    _beginthread( Thread, 0, NULL );
 
    while( TRUE )
    {
        EnterCriticalSection( &cs );
        printf( "%d %d %d %d %d\n",
                a[ 0 ], a[ 1 ], a[ 2 ],
                a[ 3 ], a[ 4 ] );
        LeaveCriticalSection( &cs );
    }
    return 0;
}
Пример, простой как божий день. Пытаюсь переработать - желаемое отсутствует.
0
lavan
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
18.12.2011, 01:55 #11
Цитата Сообщение от final_sleep Посмотреть сообщение
нахождение суммы всех элементов, вывод этой суммы на экран и запись её в первый элемент массива.
мой код-это выполняет!
Цитата Сообщение от final_sleep Посмотреть сообщение
Желаемо, чтобы в итоге выводил нечто вроде:
6 2 3
11 2 3
16 2 3
а это больше похоже на матрицу,тогда нужно менять условие

Добавлено через 3 минуты
Цитата Сообщение от final_sleep Посмотреть сообщение
Чтобы было:
открылась cs в принте
закрылась cs в принте
открылась cs в сумме
закрылась cs в сумме
и это условие тоже выполняется
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
18.12.2011, 13:19  [ТС] #12
Ребята, попробовал сделать еще проще, но к сожалению не выгорело( Может можно что-то сделать с этим?
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
#include "stdafx.h"
#include "windows.h"
#include "iostream"
#include "process.h" 
 
using namespace std;
 
#define MAX_ARRAY 5
 
CRITICAL_SECTION critsect;
 
int array[]={1,2,3,4,5};
 
void PrintArray(void *);
void SumArray(void *);
 
void main()
{
 
    InitializeCriticalSection(&critsect);
    _beginthread(SumArray,1024,NULL);
    _beginthread(PrintArray,1024,NULL);
    _beginthread(SumArray,1024,NULL);
    _beginthread(PrintArray,1024,NULL);
    _beginthread(SumArray,1024,NULL);
    _beginthread(PrintArray,1024,NULL);
    getchar();
 
}
 
 
void PrintArray(void *)
{
    EnterCriticalSection(&critsect);
    printf("%d %d %d %d %d\n",array[0],array[1],array[2],array[3],array[4]);
    Sleep(1000);
    LeaveCriticalSection(&critsect);
    _endthread();
}
 
void SumArray(void *)
{
    int sum=0;
    EnterCriticalSection(&critsect);
    for (int x=0;x<6; x++){
        sum=sum+array[x];}
    array[0]=sum;
    Sleep(1000);
    LeaveCriticalSection(&critsect);
    _endthread();
}
Добавлено через 17 минут
lavan, извините, я ваше сообщение не увидел(
Ваш код действительно работает!
Цитата Сообщение от lavan Посмотреть сообщение
Сообщение от final_sleep
Желаемо, чтобы в итоге выводил нечто вроде:
6 2 3
11 2 3
16 2 3
а это больше похоже на матрицу,тогда нужно менять условие
1-й поток суммирует
2-й поток выводит
1-й поток суммирует
2-й поток выводит
ну вот такое что-то.
0
lavan
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
18.12.2011, 13:20 #13
Тогда так
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
#include<windows.h>
#include<iostream>
using namespace std;
CRITICAL_SECTION cs;
int ar[5];
int coutn;
void thr();
void num();
int main() {
    HANDLE htr;
    DWORD dwId;
    InitializeCriticalSection(&cs);
    num();
    htr=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)thr,NULL,0,&dwId);
    Sleep(50);
    while(true) {
        EnterCriticalSection(&cs);
        for(int i=0;i<5;i++)
        cout<<ar[i]<<" ";
        cout<<endl;
        LeaveCriticalSection(&cs);
                       if(ar[0]>100)break;
        Sleep(50);
    }
     CloseHandle(htr);
     DeleteCriticalSection(&cs);
    cin.get();
    return 0;
}
void thr() {
    while(true) {
    EnterCriticalSection(&cs);
        for(int i=0;i<5;i++)
        ar[0]+=ar[i];
    LeaveCriticalSection(&cs);
        if(ar[0]>100)break;
        Sleep(50);
    }
}
void num() {
    for(int i=0;i<5;i++)
    ar[i]=rand()%10;
}
1
Вложения
Тип файла: doc 1.doc (54.5 Кб, 9 просмотров)
DU
1486 / 1132 / 164
Регистрация: 05.12.2011
Сообщений: 2,279
18.12.2011, 13:35 #14
Ваш упрощенный пример вполне себе работает корректно, только не так, как вы хотите. Я вставил печать чего-нибудь в ф-ию SumArray. Получается, что сперва отрабатывают три печатающих потока, и печатается неизмененный массив, а потом начинают работать суммирующие потоки. Если вы создаете пачку потоков в определенном порядке - это еще не значит, что они начнут работать в точно таком же порядке. Если вам нужна правильная последовательность запуска потоков, то одной критической секцией тут не обойдешься. Нужны еще и другие синхронизирующие объекты.
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
18.12.2011, 13:46  [ТС] #15
DU, предлагаете поставить семафор? Но по сути это же будет противоречить заданию?

Добавлено через 48 секунд
lavan, к сожалению немного не то(
Но спасибо, за то что пытаетесь помочь!
0
lavan
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
18.12.2011, 13:48 #16
а что конкретно не то?
0
DU
1486 / 1132 / 164
Регистрация: 05.12.2011
Сообщений: 2,279
18.12.2011, 13:52 #17
ну если заниматься буквоедством - то вы задание выполнили. потоки делают то, что вам нужно. потом, нигде в задании не сказано, что один поток занимается печатью, а другой подсчетом суммы. вы можете написать ф-ию, которая суммирует и сразу же печатае. т.е. две задачи в одном потоке. создайте два потока и передайте им эту ф-ию. и это тоже будет соответствовать заданию, если под обработкой массива понимать именно набор действий.
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
18.12.2011, 13:53  [ТС] #18
Вот используя семафоры все вышло просто чудесно!
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
#include <windows.h>
#include <stdio.h>
 
 
CRITICAL_SECTION cs = {0};
int a[]= {1,2,3};
int sem = 0;
 
 
DWORD WINAPI SUM(LPVOID param)
{
    int i=0;
    int sum;
    while(TRUE)
    {
        while (sem == 0);
        sem = 1;
    EnterCriticalSection(&cs);
    putchar('\r');
    sum = 0;
    for(i=0; i<3; i++)
        {
        sum=sum+a[i];
        }
    a[0]=sum;
    LeaveCriticalSection(&cs);
    sem = 0;
    if (a[0] > 100) return 0;
    }
    return 0;
}
DWORD WINAPI PRINT(LPVOID param)
{
    while (TRUE) {
    while (sem == 1);
    sem = 0;
    EnterCriticalSection(&cs);
    printf("%d %d %d \n",a[0],a[1],a[2]);
    LeaveCriticalSection(&cs);
    sem = 1;
    if (a[0] > 100) return 0;
    }
    return 0;
}
 
int main(void)
{
    HANDLE THR[1];
    InitializeCriticalSection(&cs);
    THR[0]=CreateThread(NULL, 0, SUM, NULL, 0, NULL);
    THR[1]=CreateThread(NULL, 0, PRINT, NULL , 0, NULL);
    WaitForMultipleObjects(2, THR, TRUE, INFINITE);
    CloseHandle(THR[0]);
    CloseHandle(THR[1]);
    DeleteCriticalSection(&cs);
    puts("End threads.");
    getchar();
    return 0;
}
http://imglink.ru/pictures/18-12-11/...d79808cb79.jpg
0
lavan
53 / 53 / 8
Регистрация: 21.03.2009
Сообщений: 371
18.12.2011, 14:08 #19
Цитата Сообщение от final_sleep Посмотреть сообщение
1-й поток суммирует
2-й поток выводит
1-й поток суммирует
2-й поток выводит
ну вот такое что-то.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
while(true) {
    EnterCriticalSection(&cs);
        for(int i=0;i<5;i++)
        ar[0]+=ar[i];
    LeaveCriticalSection(&cs);
        if(ar[0]>100)break;
        Sleep(50);//передали управление в поток показа
.....................
Sleep(50);//дали возможность взять управление потоку суммирования
    while(true) {
        EnterCriticalSection(&cs);
        for(int i=0;i<5;i++)
        cout<<ar[i]<<" ";//вывели результат
        cout<<endl;
        LeaveCriticalSection(&cs);
        if(ar[0]>100)break;
        Sleep(50);//для однозначности передачи управления в поток суммирования
    }
    }
Добавлено через 13 минут
Несколько слов о вышем коде.
1)Вы не используете семафоры!
2)У вас присутствует банальный выход за пределы массива
C++
1
2
3
HANDLE THR[1];
        THR[0]=CreateThread(NULL, 0, SUM, NULL, 0, NULL);
    THR[1]=CreateThread(NULL, 0, PRINT, NULL , 0, NULL);
0
final_sleep
0 / 0 / 0
Регистрация: 12.12.2010
Сообщений: 19
18.12.2011, 14:20  [ТС] #20
lavan, выход почему-то никак не сказался О_О
Эм эт блокирующая переменная. Извините, каша в голове.

Добавлено через 4 минуты
и к тому же в вашем алгоритме
C++
1
a[0]+=a[i]
сумма элементов должна не прибавляться, а записываться в первый элемент.
0
18.12.2011, 14:20
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.12.2011, 14:20
Привет! Вот еще темы с решениями:

Два значения в одном элементе списка
Подскажите как в сделать односвязный список, чтобы при добавление элемента...

Два класса в одном заголовочном файле, предварительное объявление
Дико туплю, никак не могу понять, где косячу. Ситуация - есть два описания...

LNK2019 два проекта в одном решении (MSVC gtest)
Собственно собрал gtest 1.7.0 static debug с ключом /MTd. Создал решение....

Вывести строку в два столбца: в одном строчные буквы, во втором прописные
помогите нубу написать программу) Вводные данные: 20 букв Представление...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru