Документ взят из кэша поисковой машины. Адрес оригинального документа : http://angel.cs.msu.su/~oxana/prac/task2/task2_parallel.c~
Дата изменения: Thu Feb 18 02:39:14 2010
Дата индексирования: Sat Apr 9 23:38:16 2016
Кодировка:
#include
#include
#include
#include
#include "omp.h"

#define MARKS_NUM 50

enum Sex {
male, female
};

struct Date {
int day;
int month;
int year;
};

struct Student {
char fam[16];
char name[16];
char ot[16];
enum Sex sex;
struct Date date;
char town[16];
int group;
int mark[MARKS_NUM];
int age;
double avg_mark;
};


int strtostr(char * s, char ** buf_end, char * result)
{
while (isspace(*s))
s++;
while ((*s) && !isspace(*s)){
(*result) = (*s);
result++;
s++;
}
(*result) = 0;
(*buf_end) = s;
return 0;
}

int convert_string_to_sex(char * str_sex, enum Sex * sex)
{
switch (str_sex[0])
{
case 'M':
(*sex) = male;
return 0;
case 'F':
(*sex) = female;
return 0;
default:
return -1;
}
}

int convert_string_to_date(char * str_date, struct Date * date)
{
date->day = strtol(str_date, &str_date, 10);
if (str_date[0] != '.')
return -1;
str_date++;
date->month = strtol(str_date, &str_date, 10);
if (str_date[0] != '.')
return -2;
str_date++;
date->year = strtol(str_date, &str_date, 10);
if (str_date[0] != 0)
return -3;
return 0;
}

int convert_string_to_student(char * s, struct Student * student)
{
char str_date[10];
char str_sex[5];
int i;
if (strtostr(s, &s, student->fam))
return -2;
if (strtostr(s, &s, student->name))
return -3;
if (strtostr(s, &s, student->ot))
return -4;
if (strtostr(s, &s, str_sex))
return -5;
if (convert_string_to_sex(str_sex, &student->sex))
return -8;
if (strtostr(s, &s, str_date))
return -7;
if (convert_string_to_date(str_date, &student->date))
return -8;
if (strtostr(s, &s, student->town))
return -9;
student->group = strtol(s, &s, 10);
if (student->group < 501 || student->group > 529)
return -10;
for (i = 0; i < MARKS_NUM; i++){
student->mark[i] = strtol(s, &s, 10);
if (student->mark[i] < 2 || student->mark[i] > 5)
return -11;
}
return 0;
}

int convert_data (char ** str, int N, struct Student * students)
{
int i;
int res_code = 0;
#pragma omp parallel for shared (str,N,students) private(i) reduction(+:res_code)
for (i = 0; i < N; i++)
res_code += convert_string_to_student (str[i], &students[i]);
return res_code;
}

int get_age_from_date (struct Date date)
{
return 365 * (110 - date.year) + 30 * (2 - date.month) + (17 - date.day);
}

void compute_sum_of_ages (int N, struct Student * students, int * sum_of_ages)
{
int i;
int sum = 0;
#pragma omp parallel for shared (N,students) private(i) reduction(+:sum)
for (i = 0; i < N; i++)
{
students[i].age = get_age_from_date (students[i].date);
sum += students[i].age;
}
(*sum_of_ages) = sum;
}

double get_average(int * array, int len)
{
int i, sum;
sum = 0;
for (i = 0; i < len; i++)
sum += array[i];
return (double) sum / (double) len;
}

void generate_student_ids (int N, struct Student * students, int sum_of_ages, int * studentIDs, int * print_number)
{
int i,index_priv,index_glob,index_res;
int number = 0;
int * private_studentIDs;
int private_number;
#pragma omp parallel shared (students,studentIDs,number) firstprivate(N,sum_of_ages) private(i, private_studentIDs, private_number,index_priv,index_glob,index_res)
{
private_studentIDs = malloc (N * sizeof(int));
private_number = 0;
#pragma omp for
for (i = 0; i < N; i++)
{
if (students[i].age * N < sum_of_ages)
{
students[i].avg_mark = get_average (students[i].mark, MARKS_NUM);
private_studentIDs[private_number] = i;
private_number++;
}
}
#pragma omp critical
{
memcpy (private_studentIDs + private_number, studentIDs, number * sizeof(int));
index_priv = 0;
index_glob = 0;
index_res = 0;
while (index_glob < number && index_priv < private_number)
{
if (private_studentIDs[private_number + index_glob] < private_studentIDs[index_priv])
{
studentIDs[index_res] = private_studentIDs[private_number + index_glob];
index_glob++;
index_res++;
}else{
studentIDs[index_res] = private_studentIDs[index_priv];
index_priv++;
index_res++;
}
}
while (index_priv < private_number)
{
studentIDs[index_res] = private_studentIDs[index_priv];
index_priv++;
index_res++;
}
while (index_glob < number)
{
studentIDs[index_res] = private_studentIDs[private_number + index_glob];
index_glob++;
index_res++;
}
number = index_res;
}
(*print_number) = number;
}

void print_student(FILE * f_out, struct Student * student)
{
fprintf(f_out, "%s %s %s %d %.2lf\n", student->fam, student->name, student->ot, student->group, student->avg_mark);
}

int print_student_ids (int print_number, int * studentIDs, struct Student * students)
{
FILE * f_out;
int i;
f_out = fopen("StudAnswer.DB","w");
if (!f_out)
return -1;
for (i = 0; i < print_number; i++)
print_student (f_out, &students[studentIDs[i]]);
fclose(f_out);
return 0;
}

int read_file (char ***strings, int* length)
{
FILE *in;
int N = 0;
char **str = NULL;
char s[255];
int len;
in = fopen("Students.DB","r");
if (!in)
return -1;
while (fgets (s, 255, in) != NULL){
len = strlen(s);
str = realloc (str, (N + 1) * sizeof (char*));
str[N] = malloc (len + 1);
strcpy (str[N], s);
N++;
}
fclose (in);
(*strings) = str;
(*length) = N;
return 0;
}

int main(int argc, char **argv)
{
int N = 0;
char **str = NULL;
struct Student * students;
int sum_of_ages;
int * studentIDs;
int print_number = 0;
if (read_file (&str, &N))
return 1;
students = malloc (N * sizeof (struct Student));
if (convert_data (str, N, students))
return 2;
compute_sum_of_ages (N, students, &sum_of_ages);
studentIDs = malloc (N * sizeof (int));
generate_student_ids (N, students, sum_of_ages, studentIDs, &print_number);
if (print_student_ids (print_number, studentIDs, students))
return 3;
printf("Success! Number of students %d, printed %d of them\n", N, print_number);
return 0;
}