Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 [2] 3 4 5 6   Вниз
  Печать  
Автор Тема: Процессы  (Прочитано 111793 раз)
0 Пользователей и 12 Гостей смотрят эту тему.
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #30 : 16-12-2008 19:52 » 

Я хотел сказать - 1/4. Даже если их было бы 23 - точное число неважно, главное разделить примерно поровну и раздать потокам чёткое задание, чтобы минимизировать время.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #31 : 16-12-2008 19:55 » 

Если я правильно понял, загоняем в один поток функцию вида
Код: (C++)
float srbal(student s[])
{
    int i,sum;
    student t;
    sum = 0;
    for(i = 0; i < 20; i++)
        sum = s[i].col+sum;//сумма балов по математике
    return (sum/20.0);
    }

для нахождения среднего для одного предмета и все?


Код: (C++)
        for (i=0;i<3;i++)
        {
        //a1=s[i].col; b1=s[i+1].col;
        Thread[i] = (HANDLE)_beginthreadex(NULL, 0, Sum, 0, 0, &tid);
        Sleep(10);
        }
        WaitForMultipleObjects(4, Thread, TRUE, INFINITE);
        cout<<"Потоки завершили виконання" <<endl;
        //Закрываємо потоки
        for (i=0;i<4;i++) CloseHandle(Thread[i]);
        k=0;
Такое создание потоков проконает?
« Последнее редактирование: 05-01-2009 11:33 от RXL » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #32 : 16-12-2008 20:03 » 

Да, вроде того. Это половина задания. Единственная проблема, которую я вижу, заключается в том, что у тебя для каждого предмета отдельная функция. Более универсальное решение - это чтобы вместо col, col1, col2, col3 был массив int col[nobb][4][/nobb].
Но если задача стоит так, что нужно лишь доработать имеющуюся программу, и чтобы при этом не писать 4 функции для потоков, считающих каждый предмет, а написать одну функцию, подходящую для всех потоков, то потоку можно передавать указатель на функцию, вычисляющую сумму. Хотя массив лично мне ближе, ибо избавляет от необходимости держать по одной функции подсчёта среднего для каждой дисциплины.
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #33 : 16-12-2008 20:06 » 

Такое создание потоков проконает?
Проблем я не вижу, разве что Sleep(10) - зачем оно тебе?
Мысль в том, чтобы сначала во всех потоках сосчитать результат (и временно собрать куда-то в одно место этот результат), а уже потом в основном потоке вывести. А то, как я предполагаю, могли быть проблемы с одновременным выводом результатов из потоков, так?
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #34 : 17-12-2008 06:44 » 

Теперь наконец то главный вопрос как функции unsigned __stdcall Sum(void * arg) вместо "void * arg" или дополняя ее передать "student s[]" - если это решается, то думаю, что проблема решена.
Записан
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #35 : 17-12-2008 07:01 » 

Не знаю, то ли у преподов чегото с головами, то ли где.
Скорее всего изначально была задача про студентов. Типа подсчитать средний балл и т.д. А потом вдруг преподу стукнуло в голову из нее сделать задачу на распараллеливание вычислений. Но мозгом думать лень. Можно тогда было бы хотя бы сформулировать "дано 10000000 записей. Подсчитать сумму, среднее значение, количество последовательностей 01020304h, еще чтонибудь и т.д.". Тогда можно хоть к примеру сделать поток, который считает сумму, второй поток, который считает среднее и т.д. Так хоть понятно для чего многозадачность. (Хотя вот подумалось, что все что я предложил можно сделать и за один проход на одном процессе). Или, наоборот, подсчитать среднее значение но для этого разделить массив на куски, считать по каждому отдельно, потом среднее значение средних значений.

з.ы. Самое смешное, что в коде
Код: (C++)
        for (i=0;i<3;i++)
        {
        //a1=s[i].col; b1=s[i+1].col;
        Thread[i] = (HANDLE)_beginthreadex(NULL, 0, Sum, 0, 0, &tid);
        Sleep(10);
        }
        WaitForMultipleObjects(4, Thread, TRUE, INFINITE);
        cout<<"Потоки завершили виконання" <<endl;
        //Закрываємо потоки
        for (i=0;i<4;i++) CloseHandle(Thread[i]);
        k=0;
многопоточного исполнения не получица, т.к. каждый поток отработает раньше, чем выполнится Sleep(10).

Чтоб исполнение и вправду было многопоточным нужно тогда уж заставить каждый поток в начале своего исполнения ждать разрешения. Т.е. создать все потоки, а потом стартануть их каким нибудь методом. С помощью семафора, например. Это было бы стильно и препод умер бы от щастья )
Записан

Good user - dead user
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #36 : 17-12-2008 07:07 » 

v.korleone, можно передать и student[], хотя ещё лучше передавать, помимо этого массива, задание (скажем, какую именно дисциплину считать, или средний балл каких студентов). В любом случае, параметры в поток передаются в качестве void* arg. То есть, именно через этот аргумент. Я бы сделал так: для каждого потока перед его созданием создавал бы структуру с описанием задачи, что-то типа
Код:
struct STask
{
   student * src; // исходные данные
   int subj; // дисциплина, для которой считаем среднее
}
и передавал бы указатель на такую структуру в качестве параметра для потока в той части, где считаем средние для дисциплин.

uintptr_t _beginthreadex(
   void *security,
   unsigned stack_size,
   unsigned ( *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr
);

Parameters

start_address
    Start address of a routine that begins execution of a new thread. For _beginthread, the calling convention is either __cdecl or __clrcall; for _beginthreadex, it is either __stdcall or __clrcall.

stack_size
    Stack size for a new thread or 0.

arglist
    Argument list to be passed to a new thread or NULL.


security
    Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If NULL, the handle cannot be inherited. Must be NULL for Windows 95 applications.

initflag
    Initial state of a new thread (0 for running or CREATE_SUSPENDED for suspended); use ResumeThread to execute the thread.

thrdaddr
    Points to a 32-bit variable that receives the thread identifier. Might be NULL, in which case it is not used.
я выделил тот аргумент _beginthreadex, который тебе нужен. Именно этот параметр и будет передан в качестве void * arg в функцию потока
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #37 : 17-12-2008 17:27 » 

Вад спасибо. Похоже лед тронулся. Пошел реализововать.


Блин опять непонятки. Все по порядку.
1. На этом этапе пока без реализации масивов функции как было предложено в Ответ #36. Уже есть функция для подсчета среднего балла по математике:
Код: (C++)
float srbal(student s[])
{
    int i,sum;
    student t;
    sum = 0;
    for(i = 0; i < 20; i++)
        sum = s[i].col[3]+sum;//сумма балов по математике
    return (sum/20.0);
    }
Как известно вот здесь
Код: (C++)
Thread[i] = (HANDLE)_beginthreadex(NULL, 0, srbal, 0, 0, &tid);
функция srbal должна быть представлена не float srbal(student s[]) (см. выше), а unsigned __stdcall srbal (void * arg).
Как это сделать? Если просто написать, что unsigned __stdcall srbal (student s[]) нечего не выходит, нужно как-то, чтобы и void * arg и student s[]?
Как это сделать?    
« Последнее редактирование: 05-01-2009 11:34 от RXL » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #38 : 17-12-2008 17:39 » 

Пусть есть
Код:
float srbal(student s[], int subj)
{
    int i,sum;
    student t;
    sum = 0;
    for(i = 0; i < 20; i++)
        sum = s[i].col[subj]+sum; //сумма балов по предмету subj
    return (sum/20.0);
}
(унифицируем уже твои функции подсчёта среднего). И есть структура вида:
Код:
struct STask
{
   student * src; // исходные данные
   int subj; // дисциплина, для которой считаем среднее
   float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его
}

делаешь функцию unsigned __stdcall CalcAvg (void * arg), в которой вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова

А поток создаёшь как-то так:
Код:
STask tasks[4];
//...
tasks[i].src = student;
tasks[i].subj = i;
Thread[i] = (HANDLE)_beginthreadex(NULL, 0, CalcAvg, &tasks[i], 0, &tid);
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #39 : 17-12-2008 17:49 » 

Вад прошу прощения за свое незнание, но здесь можно поподробнее:
Цитата
делаешь функцию unsigned __stdcall CalcAvg (void * arg), в которой вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова


Может как-то так?
Код: (C++)
unsigned __stdcall CalcAvg (void * arg)
{
    return (srbal(student s[]));
}
« Последнее редактирование: 05-01-2009 11:34 от RXL » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #40 : 17-12-2008 18:03 » 

Ну смотри: у тебя arg будет содержать указатель на структуру с заданием. Надо только привести тип и пользоваться. А возвращать ничего не надо (точнее, правильные потоки возвращают в случае успешного завершения 0):
Код:
unsigned __stdcall CalcAvg (void * arg)
{
    STask task * = (STask*) arg;
    if (task) // проверяем - вдруг параметры забыли передать
    {
        // вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова

        // ...
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #41 : 17-12-2008 18:11 » 

А это как сделать
Цитата
сохраняешь в эту же структуру результат вызова
?
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #42 : 17-12-2008 18:16 » 

Код:
task->avg = вызов функции
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #43 : 18-12-2008 13:47 » 

Вад я опять таки извиняюсь, за свою некомпетентность, но вот какая штука, (попробую описать очень подробно):
мои стандартные структуры:
Код: (C++)
struct fio//структура fio включает данные студентов:
{
    char fam[l];//фамилии
    char im[l];//имена
    char ot[l];//отчества
};

struct student//структура student включает данные студентов:
{
    fio f; //ФИО
    int col[3];//количество баллов по философии
};
дальше идет структура предложеная тобой:
Код: (C++)
struct STask
{
   student *src; // исходные данные
   int fil; // дисциплина, для которой считаем среднее
   int subd;// СУБД
   int tau;// ТАУ
   int math;// математика
   float avg; // средний балл - используется для сохранения результата
}
Следуйщая строчка моей программы:
Код: (C++)
//==================Перечисление функций, которые используются в программе==========================//

void inputstfile(student s[],int &m);//ввод из файла
void outputst(student s[],int m); //вывод на экран массива студентов
void outputstfile(student s[],int m);//сохранение в файле массива студентов
void srstud(student s[], int m);//расчет и вывод среднего балла для каждого студента
float srbal(student s[]);//средний балл по предмету

ifstream in;
ofstream out;
дальше идет описание функций..... доходим до функции среднего балла:
Код: (C++)
float srbal(student s[])
{
    int i,sum;
    student t;
    sum = 0;
    for(i = 0; i < 20; i++)
        sum = s[i].col[3]+sum;//сумма балов по математике
    return (sum/20.0);
}
Вопрос1: Из какой структуры (может быть из какой-то предпочтительнее?) брать значение s.col[3] из student или STask, как лучше?
далее в программе идет тобою предложеная функция:
Код: (C++)
unsigned __stdcall CalcAvg (void * arg)
{
    STask task* = (STask*) arg;
    if (task) // проверяем - вдруг параметры забыли передать
    {
        srbal(student s[]);
        task->avg=srbal(student s[]);
        // вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Вопрос2: Помоги, пожалуйста, правильно выбрать структуру в строчках
Код: (C++)
srbal(student s[]);
task->avg=srbal(student s[]);
а еще лучше (не сочти за дерхость) со всей функцией.
Вопрос3: Если я все так и оставляю первых четрые ошибки компилятора сязаны со строкой:
Код: (C++)
void inputstfile(student s[],int &m);//ввод из файла
Текст ошибок:
1. error: new types may not be defined in a return type
2. note: (perhaps a semicolon is missing after the definition of `STask')
3. error: two or more data types in declaration of `inputstfile'
4. error: ambiguates old declaration `STask inputstfile(student*, int&)'
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #44 : 18-12-2008 14:06 » 

v.korleone,
я такого:
Код:
struct STask
{
   student *src; // исходные данные
   int fil; // дисциплина, для которой считаем среднее
   int subd;// СУБД
   int tau;// ТАУ
   int math;// математика
   float avg; // средний балл - используется для сохранения результата
}
не предлагал. Я предлагал структуру, которая содержит задание и результаты для одной дисциплины. Какая именно это дисциплина - определялось у меня одной переменной int subj.
Далее, src - ничто иное как указатель на student[] (или как там этот массив называется в месте вызова). Так что ты просто копируешь (типа src = student) и передаёшь эту структуру в функцию _beginthreadex. И делаешь так для каждой дисциплины отдельно, в цикле (ты же в цикле потоки запускаешь?)

далее:
Код:
unsigned __stdcall CalcAvg (void * arg)
{
    STask task* = (STask*) arg;
    if (task) // проверяем - вдруг параметры забыли передать
    {
        srbal(student s[]);
        task->avg=srbal(student s[]);
        // вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
- забудь здесь про student s[] - у тебя его здесь под этим именем не должно быть. у тебя здесь есть указатель на структуру STask *task, и в той структуре содержатся все нужные данные - входные и выходные. И посмотри, что я писал по поводу srbal: лучше сделать одну функцию, которая умеет считать среднее для любой дисциплины. Я именно из этого расчёта выстраивал весь код (иначе реализация будет либо ещё сложнее, либо корявой, и всяко - избыточной по всем направлениям).

По поводу 3-го вопроса: там во 2й ошибке указано - забыта точка с запятой после закрывающей фигурной скобки у STask.
« Последнее редактирование: 18-12-2008 14:08 от Вад » Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #45 : 18-12-2008 14:33 » 

Вад спасибо за разъяснение всех ошибок. Исходя из предложеного тобой варианта:
Цитата
struct STask
{
   student * src; // исходные данные
   int subj; // дисциплина, для которой считаем среднее
   float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его
}
будет 4 структруы?
Если можно здесь поподробней:
Код: (C++)
Более универсальное решение - это чтобы вместо col, col1, col2, col3 был массив int col[nobb][4][/nobb].
здесь не понятно, если бы int col[4] - массив из 4(5) элементов, а так не совсем понял.
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #46 : 18-12-2008 14:51 » 

Допустим, есть 4 дисциплины. 0-я, 1-я, 2-я и 3-я Улыбаюсь
Есть структура типа
Код:
struct Student
{
string name;    // имя
string lastname;  // фамилия
int col[4];  // массив оценок за 4 дисциплины.
};
(ну что-то вот такое)
Есть массив таких структур
Код:
Student students[20];
// и дальше она типа как-то заполняется

Есть функция, которая умеет посчитать среднее для одной дисциплины (передаём в функцию указатель на массив данных и номер дисциплины)
Код:
float srbal(
    Student *src,   // массив данных
    int size,  // размер массива
    int subj   // номер дисциплины
)
{
    int i,sum;
    sum = 0;
    for(i = 0; i < size; i++)
        sum = src[i].col[subj]+sum; //сумма балов по предмету subj
    return ( sum/(float)size );
}

Чтобы посчитать в одном потоке, можно было бы вызывать эту функцию как
Код:
srval(students, 20, number); // где number - интересующий нас номер дисциплины < 4.

Но нам надо посчитать 4 дисциплины, и мы делаем 4 потока, формируя для них задачи:
Код:
STask tasks[4];
for (int i = 0; i < 4; ++i)
{
    tasks[i].src = students;
    tasks[i].subj = i;
    Thread[i] = (HANDLE)_beginthreadex(NULL, 0, CalcAvg, &tasks[i], 0, &tid);
}

Ну и в CalcAvg работаешь ТОЛЬКО с тем, что тебе передали в avg. Поток, вообще говоря, не должен получать информацию извне иначе, кроме как через этот параметр - в противном случае логика программы будет недостаточно чёткой.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #47 : 18-12-2008 15:11 » 

Цитата
Student students[20];
// и дальше она типа как-то заполняется
Если у нас чтение из файла, то записуем просто массив без
Цитата
// и дальше она типа как-то заполняется
 


Код: (C++)
//------------------------------------------Подпрограмма передачи знчения средного балла потоку-----------------------------------------//
unsigned __stdcall CalcAvg (void * arg)
{
    Student *src = (Student*) arg;
        if (src) // проверяем - вдруг параметры забыли передать
    {
        src->avg = srbal(Student *src,size,subj);// вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Вад, еще один вопрос:
После компиляции пишет относительно строчки
Код: (C++)
src->avg = srbal(Student *src,size,subj)
:
1. error: 'struct Student' has no member named 'avg'
2. error: expected primary-expression before '*' token
3. error: `size' was not declared in this scope
4. error: `subj' was not declared in this scope
Я понял, что неправильно передал параметры ф-и srbal(Student *src,size,subj) как правильно написать?
 
« Последнее редактирование: 05-01-2009 11:34 от RXL » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #48 : 18-12-2008 18:47 » 

ну, всё правильно компилятор пишет.
1. в структуре Student нет никакого avg
2. какой-то очень странный 1й параметр при вызове srbal
3. нет в области видимости никакой переменной size
4. переменной subj тоже не имеется

Итого:
1. По идее, на что указатель передал - на то и следует получать в функции потока. Иначе будут забавные спецэффекты (и точно не будет работать как надо)
2. Copy+paste нужно делать вдумчиво. Я ж сказал, в структуре STask, передаваемой в поток, есть все необходимые данные - по полям. Их только передать в функцию srbal остаётся.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #49 : 18-12-2008 19:10 » 

Вад, так у нас 2 структуры Student и STask?

Почему нельзя пользоваться Student?
« Последнее редактирование: 05-01-2009 11:35 от RXL » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #50 : 18-12-2008 19:23 » new

v.korleone, структуры - две (и ещё 3я может понадобиться, когда параллелить расчёт среднего для студентов станешь). Вторая содержит в себе копию указателя на массив студентов

Почему нельзя пользоваться Student?
А как ты будешь передавать задачу и возвращать значение? Кроме студентов, ещё ж надо передать, по какому предмету среднее считать, и вернуть среднее куда-то надо.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #51 : 19-12-2008 07:08 » 

Вад, посмотри пожалуйста, что не так?
Есть 2 структуры:
Код: (C++)
struct Student
{
char lastname[l];// фамилия
char name[l];// имя
char ot[l];//отчествo
char col[4];  // массив оценок за 4 дисциплины.
};

struct STask
{
   Student *src; // исходные данные
   int subj; // дисциплина, для которой считаем среднее
   float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его
};
Есть функция для полсчета среднего балла:
Код: (C++)
float srbal(
    Student *src,   // массив данных
    int size,  // размер массива
    int subj   // номер дисциплины
           )
{
    int i,sum;
    sum = 0;
    for(i = 0; i < size; i++)
    sum = src[i].col[subj]+sum;
    return ( sum/(float)size );//сумма балов по предмету subj
}
Есть функция для преобразования ф-и srbal для потока (если я правильно понял ее назначение):
Код: (C++)
unsigned __stdcall CalcAvg (void * arg)
{
    STask *task = (STask*) arg;
        if (task) // проверяем - вдруг параметры забыли передать
    {
        task->avg = srbal(*task);
        // вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Если пишу
Код: (C++)
task->avg = srbal(*task);
тогда пишет ошибку:
error: cannot convert `STask' to `Student*' for argument `1' to `float srbal(Student*, int, int)'
Если пишу
Код: (C++)
task->avg = srbal(*STask);
тогда пишет ошибку:
error: expected primary-expression before ')' token
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #52 : 19-12-2008 07:12 » 

Правильно, у тебя 3 параметра в srbal, а ты хочешь туда 1 занести, да ещё и не того типа.

(Я, кстати, забыл про передачу размера массива студентов, надо добавить)
Код:
struct STask
{
   Student *src; // исходные данные
   int size; // число элементов в src
   int subj; // дисциплина, для которой считаем среднее
   float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его
};
Ну и, собственно, тогда параметрами для srbal будут task->src, task->size и task->subj.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #53 : 19-12-2008 08:08 » 

Вад, в этой функции нужно еще что-то дописывать?
Код: (C++)
unsigned __stdcall CalcAvg (void * arg)
{
    STask *task = (STask*) arg;
        if (task) // проверяем - вдруг параметры забыли передать
    {
        srbal(task->src,task->size,task->subj);
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #54 : 19-12-2008 08:36 » 

v.korleone, нужно. Результат вычисления среднего потерял Улыбаюсь
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #55 : 20-12-2008 19:29 » 

Вад, согласен, но куда его записать в функцию srbal, можно записать только три параметра? Я так понял, получается как-то так:
Код: (C++)
unsigned __stdcall CalcAvg (void * arg)
{
    STask *task = (STask*) arg;
        if (task) // проверяем - вдруг параметры забыли передать
    {   task->avg;
        srbal(task->src,task->size,task->subj);
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Я правильно, понял?
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #56 : 20-12-2008 22:02 » 

v.korleone, у функции ещё остаётся возвращаемый результат. Вот его-то и надо присвоить этой task->avg.

Возможно, у тебя ещё небольшая путаница в голове. Смотри: в твоём случае многопоточность используется для распараллеливания вычислительных задач. Соответственно, каждый поток должен уметь выполнить полученную задачу и вернуть результат. При этом, имхо (и не только), хороший стиль - давать потоку задание и определять способ получения результата через входной параметр потока - тот самый void* arg.

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

Твой поток уже почти это самое и делает: вычисляет среднее на основании полученных данных, но результат в структуру не сохраняет. После того, как поправишь сохранение результата, всё с этой частью задания будет ОК: после завершения потока в переданной ему структуре будет изменение: поле avg будет содержать среднее, которое тебе останется вывести на экран сразу после того, как кончится ожидание завершения выполнения всех потоков.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #57 : 21-12-2008 13:03 » 

Вад, сделал так как ты советовал, несколькими пунктами выше (думаю, что сделал правильно):
Код: (C++)
unsigned __stdcall CalcAvg (void * arg)
{
    STask *task = (STask*) arg;
        if (task) // проверяем - вдруг параметры забыли передать
    {   task->avg = srbal(task->src,task->size,task->subj);
        return 0;
    }
    else
        return 1; // типа, ошибка - вдруг кого волнует
}
Теперь начались новые проблемы. При структурах типа:
Код: (C++)
struct Student
{
string lastname;// фамилия
string name;// имя
string ot;//отчествo
int col[3];  // массив оценок за 4 дисциплины.
};

struct STask
{
   Student *src; // исходные данные
   int size; // число элементов в src
   int subj; // дисциплина, для которой считаем среднее
   float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его
};
и массиве: Student students[20];
Есть функции:
Код: (C++)
//------------------------------------------------------Подпрограмма ввода из файла-------------------------------------------------//
void inputstfile(Student students[], int &m)//ввод из файла
{
    m = 0;
    in >> students[m].lastname >> students[m].name >> students[m].ot >> students[m].col[0] >> students[m].col[1] >> students[m].col[2] >> students[m].col[3];
    while (in.good())//пока не прекратятся записи в файле
    {
    m++;
    in >> students[m].lastname >> students[m].name >> students[m].ot >> students[m].col[0] >> students[m].col[1] >> students[m].col[2] >> students[m].col[3];/*ввод из файла ФИО,количества баллов по философии,
    СУБД, математике*/

    }
}
//--------------------------------------------------------------------------------------------------------------------------------------//

//----------------------------------------Подпрограмма вывода на экран массива студентов-------------------------------------------//
void outputst(Student students[], int m)//вывод на экран массива студентов
{
    int i;
    for(i = 0; i < m; i++)
    {
   cout << "|" << setw(12) << setiosflags(ios::left)  << students[m].lastname//вывод на экран фамилий,
        << "|" << setw(10) << setiosflags(ios::left) << students[m].name//имен,
        << "|" << setw(14) << setiosflags(ios::left) << students[m].ot//отчеств,
        << "|" << setw(12) << setiosflags(ios::left) << students[m].col[0]//количества баллов по философии,
        << "|" << setw(6) << setiosflags(ios::left) << students[m].col[1]//количества баллов по СУБД,
        << "|" << setw(5) << setiosflags(ios::left) << students[m].col[2]//количества баллов по ТАУ,
        << "|" << setw(6) << setiosflags(ios::left) << students[m].col[3] << "      |" << endl;//количества баллов по математике
        if((i+1)%10==0) getch();//задержка на экране
    }
    getch();
}
//--------------------------------------------------------------------------------------------------------------------------------------//

Главная программа:
Код: (C++)
....
int n;
Student a[N];
cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
cout<<"|  Прізвище  |"<<"  Ім'я    |"<<"  По батькові |"<<" Філософія  |"<<" СУБД |"<<" ТАУ |"<<" Математика |"<<"\n";
cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
inputstfile(a, n);
in.close();
оutputst(a, n);
.....
Компилит все исправно вот только функции inputstfile(a, n),оutputst(a, n) не работают, т.к. при работе программы выводится только строчки типа:
Код: (C++)
cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
cout<<"|  Прізвище  |"<<"  Ім'я    |"<<"  По батькові |"<<" Філософія  |"<<" СУБД |"<<" ТАУ |"<<" Математика |"<<"\n";
cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
и больше ничего. Думаю, что это связано с изменением типов char на string здесь:
Код: (C++)
{
string lastname;// фамилия
string name;// имя
string ot;//отчествo
int col[3];  // массив оценок за 4 дисциплины.
};
Для этого я взял и оставил все как было, т.е. поменял string на char. В принципе ничего не изменилось, выводится шапка таблицы + (то чего не было при string) надпись "Потоки окончили выполнение".
Что делать?
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #58 : 21-12-2008 16:32 » 

В структуре Student:
Код:
int col[4];
- у тебя 3. Задаётся же размер, а не максимальный индекс (хотя элементы массива и нумеруются с нуля).
Но это так, между делом.

Код:
Student a[N];
// ...
inputstfile(a, n);
in.close();
оutputst(a, n);
Что такое N и n? С точки зрения C/C++ это разные переменные: какие у них значения?
И покажи код, где запускаешь потоки, ждёшь завершения и выводишь результаты из структур STask.
Записан
v.korleone
Помогающий

ua
Offline Offline

« Ответ #59 : 21-12-2008 16:45 » 

Вад, я знаю там нужно переделывать вывод с процесов, но не в этом сейчас суть. Вот код:
Код: (C++)
unsigned tid;
HANDLE Thread[3];// Імітація 4-х процесорів
DWORD res;
const int N = 100;
int main()
{
    Student a[N];
    int n,i,j,k,fl,max;
    char file[l];
    SetConsoleOutputCP(1251);
    cout << endl << "Вкажiть шлях до файлу: ";
    cin >> file;
    in.open(file);
    if(in == NULL)
    {//если не указан путь к файлу, то вывести сообщение "файл не найден"
        cout << "Файл не був знайдений";
        getch();
        exit(1);
    }
    cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
    cout<<"|  Прізвище  |"<<"  Ім'я    |"<<"  По батькові |"<<" Філософія  |"<<" СУБД |"<<" ТАУ |"<<" Математика |"<<"\n";
    cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
    inputstfile(a, n);
    in.close();
    outputst(a, n);
    max = a[0].col[3];
    k = 0;
    for(i = 1; i < n; i++)
        if (a[i].col[3]>max) max = a[i].col[3];
    cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n";
    cout<<"\n";
//--------------------------------------------Створення потоків_1-й ярус---------------------------------------------------------------//
        STask tasks[3];
        for (int i = 0; i < 3; ++i)
    {
         tasks[i].src = students;
         tasks[i].subj = i;
         Thread[i] = (HANDLE)_beginthreadex(NULL, 0, CalcAvg, &tasks[i], 0, &tid);
    }
        WaitForMultipleObjects(4, Thread, TRUE, INFINITE);
        cout<<"Потоки завершили виконання" <<endl;
        //Закриваємо потоки
                for (i=0;i<3;i++) CloseHandle(Thread[i]);
//***Расчет и вывод средних баллов по предметам для каждого предмета**//
    cout << " \n \n";
    cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------------------------------|"<<"\n";
    cout<<"|  Прізвище  |"<<"  Ім'я    |"<<"  По батькові |"<<" Середній бал для кожного студента  |"<<"\n";
    cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------------------------------|"<<"\n";
    //подсчет среднего для каждого студента srstud(a,n);
    out.open("resultst.txt");
    if(out==NULL) {
                cout<<"Файл не створений";
                getch();
                exit(1);
               }
    outputstfile(a,n);
    out.close();
    cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------------------------------|"<<"\n";
}
Записан
Страниц: 1 [2] 3 4 5 6   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines