Вад
|
|
« Ответ #30 : 16-12-2008 19:52 » |
|
Я хотел сказать - 1/4. Даже если их было бы 23 - точное число неважно, главное разделить примерно поровну и раздать потокам чёткое задание, чтобы минимизировать время.
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #31 : 16-12-2008 19:55 » |
|
Если я правильно понял, загоняем в один поток функцию вида 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); } для нахождения среднего для одного предмета и все? 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 »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #32 : 16-12-2008 20:03 » |
|
Да, вроде того. Это половина задания. Единственная проблема, которую я вижу, заключается в том, что у тебя для каждого предмета отдельная функция. Более универсальное решение - это чтобы вместо col, col1, col2, col3 был массив int col[nobb][4][/nobb]. Но если задача стоит так, что нужно лишь доработать имеющуюся программу, и чтобы при этом не писать 4 функции для потоков, считающих каждый предмет, а написать одну функцию, подходящую для всех потоков, то потоку можно передавать указатель на функцию, вычисляющую сумму. Хотя массив лично мне ближе, ибо избавляет от необходимости держать по одной функции подсчёта среднего для каждой дисциплины.
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #33 : 16-12-2008 20:06 » |
|
Такое создание потоков проконает?
Проблем я не вижу, разве что Sleep(10) - зачем оно тебе? Мысль в том, чтобы сначала во всех потоках сосчитать результат (и временно собрать куда-то в одно место этот результат), а уже потом в основном потоке вывести. А то, как я предполагаю, могли быть проблемы с одновременным выводом результатов из потоков, так?
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #34 : 17-12-2008 06:44 » |
|
Теперь наконец то главный вопрос как функции unsigned __stdcall Sum(void * arg) вместо "void * arg" или дополняя ее передать "student s[]" - если это решается, то думаю, что проблема решена.
|
|
|
Записан
|
|
|
|
DrGluck
|
|
« Ответ #35 : 17-12-2008 07:01 » |
|
Не знаю, то ли у преподов чегото с головами, то ли где. Скорее всего изначально была задача про студентов. Типа подсчитать средний балл и т.д. А потом вдруг преподу стукнуло в голову из нее сделать задачу на распараллеливание вычислений. Но мозгом думать лень. Можно тогда было бы хотя бы сформулировать "дано 10000000 записей. Подсчитать сумму, среднее значение, количество последовательностей 01020304h, еще чтонибудь и т.д.". Тогда можно хоть к примеру сделать поток, который считает сумму, второй поток, который считает среднее и т.д. Так хоть понятно для чего многозадачность. (Хотя вот подумалось, что все что я предложил можно сделать и за один проход на одном процессе). Или, наоборот, подсчитать среднее значение но для этого разделить массив на куски, считать по каждому отдельно, потом среднее значение средних значений. з.ы. Самое смешное, что в коде 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
|
|
|
Вад
|
|
« Ответ #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
Помогающий
Offline
|
|
« Ответ #37 : 17-12-2008 17:27 » |
|
Вад спасибо. Похоже лед тронулся. Пошел реализововать. Блин опять непонятки. Все по порядку. 1. На этом этапе пока без реализации масивов функции как было предложено в Ответ #36. Уже есть функция для подсчета среднего балла по математике: 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); } Как известно вот здесь 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 »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #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
Помогающий
Offline
|
|
« Ответ #39 : 17-12-2008 17:49 » |
|
Вад прошу прощения за свое незнание, но здесь можно поподробнее: делаешь функцию unsigned __stdcall CalcAvg (void * arg), в которой вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова Может как-то так? unsigned __stdcall CalcAvg (void * arg) { return (srbal(student s[])); }
|
|
« Последнее редактирование: 05-01-2009 11:34 от RXL »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #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
Помогающий
Offline
|
|
« Ответ #41 : 17-12-2008 18:11 » |
|
А это как сделать сохраняешь в эту же структуру результат вызова ?
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #42 : 17-12-2008 18:16 » |
|
task->avg = вызов функции
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #43 : 18-12-2008 13:47 » |
|
Вад я опять таки извиняюсь, за свою некомпетентность, но вот какая штука, (попробую описать очень подробно): мои стандартные структуры: struct fio//структура fio включает данные студентов: { char fam[l];//фамилии char im[l];//имена char ot[l];//отчества };
struct student//структура student включает данные студентов: { fio f; //ФИО int col[3];//количество баллов по философии }; дальше идет структура предложеная тобой: struct STask { student *src; // исходные данные int fil; // дисциплина, для которой считаем среднее int subd;// СУБД int tau;// ТАУ int math;// математика float avg; // средний балл - используется для сохранения результата } Следуйщая строчка моей программы: //==================Перечисление функций, которые используются в программе==========================//
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; дальше идет описание функций..... доходим до функции среднего балла: 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, как лучше? далее в программе идет тобою предложеная функция:
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: Помоги, пожалуйста, правильно выбрать структуру в строчках srbal(student s[]); task->avg=srbal(student s[]); а еще лучше (не сочти за дерхость) со всей функцией. Вопрос3: Если я все так и оставляю первых четрые ошибки компилятора сязаны со строкой: 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&)'
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #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
Помогающий
Offline
|
|
« Ответ #45 : 18-12-2008 14:33 » |
|
Вад спасибо за разъяснение всех ошибок. Исходя из предложеного тобой варианта: struct STask { student * src; // исходные данные int subj; // дисциплина, для которой считаем среднее float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его } будет 4 структруы? Если можно здесь поподробней: Более универсальное решение - это чтобы вместо col, col1, col2, col3 был массив int col[nobb][4][/nobb]. здесь не понятно, если бы int col[4] - массив из 4(5) элементов, а так не совсем понял.
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #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
Помогающий
Offline
|
|
« Ответ #47 : 18-12-2008 15:11 » |
|
Student students[20]; // и дальше она типа как-то заполняется Если у нас чтение из файла, то записуем просто массив без // и дальше она типа как-то заполняется //------------------------------------------Подпрограмма передачи знчения средного балла потоку-----------------------------------------// 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; // типа, ошибка - вдруг кого волнует } Вад, еще один вопрос: После компиляции пишет относительно строчки 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 »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #48 : 18-12-2008 18:47 » |
|
ну, всё правильно компилятор пишет. 1. в структуре Student нет никакого avg 2. какой-то очень странный 1й параметр при вызове srbal 3. нет в области видимости никакой переменной size 4. переменной subj тоже не имеется
Итого: 1. По идее, на что указатель передал - на то и следует получать в функции потока. Иначе будут забавные спецэффекты (и точно не будет работать как надо) 2. Copy+paste нужно делать вдумчиво. Я ж сказал, в структуре STask, передаваемой в поток, есть все необходимые данные - по полям. Их только передать в функцию srbal остаётся.
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #49 : 18-12-2008 19:10 » |
|
Вад, так у нас 2 структуры Student и STask?
Почему нельзя пользоваться Student?
|
|
« Последнее редактирование: 05-01-2009 11:35 от RXL »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #50 : 18-12-2008 19:23 » |
|
v.korleone, структуры - две (и ещё 3я может понадобиться, когда параллелить расчёт среднего для студентов станешь). Вторая содержит в себе копию указателя на массив студентов Почему нельзя пользоваться Student?
А как ты будешь передавать задачу и возвращать значение? Кроме студентов, ещё ж надо передать, по какому предмету среднее считать, и вернуть среднее куда-то надо.
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #51 : 19-12-2008 07:08 » |
|
Вад, посмотри пожалуйста, что не так? Есть 2 структуры: struct Student { char lastname[l];// фамилия char name[l];// имя char ot[l];//отчествo char col[4]; // массив оценок за 4 дисциплины. };
struct STask { Student *src; // исходные данные int subj; // дисциплина, для которой считаем среднее float avg; // средний балл - используется для сохранения результата, в прошлый раз упустил его }; Есть функция для полсчета среднего балла: 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 для потока (если я правильно понял ее назначение): unsigned __stdcall CalcAvg (void * arg) { STask *task = (STask*) arg; if (task) // проверяем - вдруг параметры забыли передать { task->avg = srbal(*task); // вызываешь srbal для параметров из структуры, переданной по указателю в arg, и сохраняешь в эту же структуру результат вызова return 0; } else return 1; // типа, ошибка - вдруг кого волнует } Если пишу task->avg = srbal(*task); тогда пишет ошибку: error: cannot convert `STask' to `Student*' for argument `1' to `float srbal(Student*, int, int)' Если пишу task->avg = srbal(*STask); тогда пишет ошибку: error: expected primary-expression before ')' token
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #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
Помогающий
Offline
|
|
« Ответ #53 : 19-12-2008 08:08 » |
|
Вад, в этой функции нужно еще что-то дописывать? unsigned __stdcall CalcAvg (void * arg) { STask *task = (STask*) arg; if (task) // проверяем - вдруг параметры забыли передать { srbal(task->src,task->size,task->subj); return 0; } else return 1; // типа, ошибка - вдруг кого волнует }
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #54 : 19-12-2008 08:36 » |
|
v.korleone, нужно. Результат вычисления среднего потерял
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #55 : 20-12-2008 19:29 » |
|
Вад, согласен, но куда его записать в функцию srbal, можно записать только три параметра? Я так понял, получается как-то так: 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; // типа, ошибка - вдруг кого волнует } Я правильно, понял?
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #56 : 20-12-2008 22:02 » |
|
v.korleone, у функции ещё остаётся возвращаемый результат. Вот его-то и надо присвоить этой task->avg.
Возможно, у тебя ещё небольшая путаница в голове. Смотри: в твоём случае многопоточность используется для распараллеливания вычислительных задач. Соответственно, каждый поток должен уметь выполнить полученную задачу и вернуть результат. При этом, имхо (и не только), хороший стиль - давать потоку задание и определять способ получения результата через входной параметр потока - тот самый void* arg.
В самом простом случае: мы запускаем поток, передав ему структуру, содержащую указатель на данные, информацию о размере данных, параметры задания (в данной задаче - предмет, по которому считать среднее) и результат операции. Нам нужно, чтобы после того, как поток завершит свою работу, в поле результата оказалось среднее значение: следовательно, поток должен вычислить и установить это значение в той самой структуре, которую ему передали.
Твой поток уже почти это самое и делает: вычисляет среднее на основании полученных данных, но результат в структуру не сохраняет. После того, как поправишь сохранение результата, всё с этой частью задания будет ОК: после завершения потока в переданной ему структуре будет изменение: поле avg будет содержать среднее, которое тебе останется вывести на экран сразу после того, как кончится ожидание завершения выполнения всех потоков.
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #57 : 21-12-2008 13:03 » |
|
Вад, сделал так как ты советовал, несколькими пунктами выше (думаю, что сделал правильно): 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; // типа, ошибка - вдруг кого волнует } Теперь начались новые проблемы. При структурах типа: 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]; Есть функции: //------------------------------------------------------Подпрограмма ввода из файла-------------------------------------------------// 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(); } //--------------------------------------------------------------------------------------------------------------------------------------// Главная программа: .... 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) не работают, т.к. при работе программы выводится только строчки типа: cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n"; cout<<"| Прізвище |"<<" Ім'я |"<<" По батькові |"<<" Філософія |"<<" СУБД |"<<" ТАУ |"<<" Математика |"<<"\n"; cout<<"|------------|"<<"----------|"<<"--------------|"<<"------------|"<<"------|"<<"-----|"<<"------------|"<<"\n"; и больше ничего. Думаю, что это связано с изменением типов char на string здесь: { string lastname;// фамилия string name;// имя string ot;//отчествo int col[3]; // массив оценок за 4 дисциплины. }; Для этого я взял и оставил все как было, т.е. поменял string на char. В принципе ничего не изменилось, выводится шапка таблицы + (то чего не было при string) надпись "Потоки окончили выполнение". Что делать?
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #58 : 21-12-2008 16:32 » |
|
В структуре Student: - у тебя 3. Задаётся же размер, а не максимальный индекс (хотя элементы массива и нумеруются с нуля). Но это так, между делом. Student a[N]; // ... inputstfile(a, n); in.close(); оutputst(a, n); Что такое N и n? С точки зрения C/C++ это разные переменные: какие у них значения? И покажи код, где запускаешь потоки, ждёшь завершения и выводишь результаты из структур STask.
|
|
|
Записан
|
|
|
|
v.korleone
Помогающий
Offline
|
|
« Ответ #59 : 21-12-2008 16:45 » |
|
Вад, я знаю там нужно переделывать вывод с процесов, но не в этом сейчас суть. Вот код: 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"; }
|
|
|
Записан
|
|
|
|
|