Новичок
Профиль
Группа: Участник
Сообщений: 48
Регистрация: 20.2.2012
Репутация: нет Всего: нет
|
Поставили на днях задачу написать следующую программу под Linux (Ubuntu): Написать программу нахождения массива N последовательных значений функции y[i]=sin(2*PI*k/N) ( i=0,1,2…N-1 ) с использованием ряда Тейлора. Пользователь задаёт значения k и количество N членов ряда Тейлора, n - количество максимально возможных созданных дочерних процессов. Для расчета каждого члена ряда Тейлора запускается отдельный процесс. Каждый процесс выводит на экран и в файл свой pid и рассчитанное значение ряда. Головной процесс считывает из файла значения всех рассчитанных членов ряда Тейлора, суммирует их и полученное значение y[i] записывает в файл. Проверить работу программы для N=256 k=5; N=1024 k=10. Использовать для процессов только функции fork() и wait(). Если не ограничивать в количестве максимального количества процессов, то рассчеты производятся верно. После попытки ограничить количество процессов, все приводит к тому, что пересчеты идут неверные, причем некоторые значения по несколько раз, плюс ко всему не закрываются процессы, что ставит в ступор программу, и она ничего не делает. Подскажите, что и как исправить, а то уже битый час бьюсь... | Код | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define PI 3.14159265358979323846 extern int errno;
//удаление подстроки из строки void DeletePartPath(char *str, char *fnd, char *buf) { //Ищем поисковый контекст (fnd) в строке char *p=strstr(str, fnd); //Если fnd не найден, то копируем всю строку и завершаем функцию. if(p==NULL) {strcpy(buf, str); return;} //Если нашли, то вырежем часть строки char *fnd1=fnd; while(str<p) {*buf=*str; buf++; str++; *buf='\0';} //Скопировали строку до встречи fnd. while(*fnd1) {str++; fnd1++;} //Пропустили fnd. //Скопировали все, что идет после fnd. strcpy(buf, str); return; }
//возведение дробного числа в степень float PowFloat(float value,int in) { int i; float result=1; for(i=1;i<=abs(in);i++) result*=value; return result; }
//возведение -1 в степень int PowMinusOne(int in) { //если остаток от деления =0 => степень четная, и возвращаем 1 if((in%2)==0) return 1; //иначе степень - нечетная, а результат равен -1 else return -1; }
//Рассчет ряда Тейлора с помощью процессов int TailorFunction(char err[], int K, int N, int n) { FILE *input,*output; //входной и выходной файлы char InPath[]="/tmp/math.txt"; //путь входного файла char OuPath[]="/tmp/result.txt"; //путь выходного файла
///Подсчет членов ряда Тейлора с помощью процессов int i; float *arr; //указатель на динамический массив
//выделяем память для массива arr=(float*)calloc(N,sizeof(float)); //обнуляем все элементы динамического массива for(i=0;i<N;i++) arr[i]=0; //создаем файл для входных данных if((input=fopen(InPath,"w+"))==NULL) { DeletePartPath(err,"./",err); //проверка на ошибку, если она возникла switch(errno) { case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;} case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;} case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;} case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;} case EISDIR:{fprintf(stderr,"%s Error: It is directory!\n",err);break;} default: {fprintf(stderr,"%s Error: Cannot open or create file!\n",err);break;} } return 1; } /* | ВЫЧИСЛЕНИЕ РЯДА ТЕЙЛОРА | от фукнции sin(2*PI*K/N), где | i={0,1,2,..,N-1} | K - № гармоники | N - делитель для члена ряда (и кол-во всевозможных значений) | n - кол-во процессов */
int j=0; long int factorial=1; //факториал int cnt=1; //счетчики int sign; //знак float degree; //значение X^i int pid,son; //PID процесса и его статус for(i=0;i<=N-1;i++) { //создаем процесс if (j!=n) { pid=fork(); j++;
//если это дочерний процесс if(pid==0) { //подсчет элемента ряда degree=PowFloat((2*PI*K/N),2*i+1);//вычисляем X^(2j+1) sign=PowMinusOne(i+2); //меняем знак на противоположный arr[i]=sign*degree/factorial; //элемент ряда cnt=cnt+2; //факториал следующего эл-та factorial=factorial*(cnt-1)*cnt; //вычислим факториал для следующего эл-а //выводим значение подсчетов и ID процесса fprintf(stdout,"PID=%d and arr[%d]=%.25f\n",getpid(),i+1,arr[i]); //фомируем выходную строку из числа char buffer[30]; //строка на 30 символов *buffer='\0'; //очищаем строку buffer sprintf(buffer,"%.25f\n",arr[i]); //перевод дробного числа в строку //запись значения в текстовый файл if((fputs(buffer,input))==-1) { //удаляем часть пути DeletePartPath(err,"./",err); //проверка на ошибку, если она возникла switch(errno) { case ENOTTY:{fprintf(stderr,"%s Error: Uknown operation I/O control!\n",err);break;} case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;} case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;} default: {fprintf(stderr,"%s Error: Cannot write file!\n",err);break;} } return 1; } } } //ожидаем завершение процесса if (j==n) { //Ожидаем завершения всех дочерних процессов while(wait(NULL)==-1); //обнуляем, и по новой повторяем j=0; } } //освобождаем память от динамического массива free(arr);
///Подсчет суммы элементов ряда Тейлора //перевод окна входного файла на его начало rewind(input); //создаем файл if((output=fopen(OuPath,"w"))==NULL) { DeletePartPath(err,"./",err); //проверка на ошибку, если она возникла switch(errno) { case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;} case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;} case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;} case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;} case EISDIR:{fprintf(stderr,"%s Error: It is directory!\n",err);break;} default: {fprintf(stderr,"%s Error: Cannot open or create file!\n",err);break;} } return 1; } //подсчет суммы ряда char buffer[50],tmp[50]; float sum,value; //сумма элементов ряда тейлора; элемент в виде числа
while(!feof(input)) { *buffer='\0'; //очищаем строку buffer fgets(buffer,50,input); //считываем строку sscanf(buffer,"%f",&value); //переводим строку в дробное число sum+=value; //считаем сумму }
//фомируем выходную строку *buffer='\0'; //очищаем строку buffer *tmp='\0'; //очищаем строку tmp sprintf(tmp,"%.25f",sum); //перевод числа в строку strcat(buffer,tmp); //строка вида "summ=%f" //подаем команду на запись if((fputs(buffer,output))==-1) { DeletePartPath(err,"./",err); //проверка на ошибку, если она возникла switch(errno) { case ENOTTY:{fprintf(stderr,"%s Error: Uknown operation I/O control!\n",err);break;} case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;} case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;} default: {fprintf(stderr,"%s Error: Cannot write file!\n",err);break;} } return 1; }
//пробуем закрыть входной файл if(fclose(input)==-1) { //удаляем часть пути DeletePartPath(err,"./",err); //проверка на ошибку, если она возникла switch(errno) { case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;} case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;} case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;} case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;} default: {fprintf(stderr,"%s Error: Cannot close file!\n",err);break;} } return 1; }
//пробуем закрыть выходной файл if(fclose(output)==-1) { DeletePartPath(err,"./",err); //проверка на ошибку, если она возникла switch(errno) { case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;} case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;} case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;} case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;} default: {fprintf(stderr,"%s Error: Cannot close file!\n",err);break;} } return 1; }
return 0; }
int main(int argc,char *argv[]) { int K,N,n; //проверка на количество аргументов if(argc<4) { fprintf(stderr,"Error:Too few arguments!\n"); return 1; } K=atoi(argv[1]); N=atoi(argv[2]); n=atoi(argv[3]); //если все указано верно, то высчитываем ряд Тейлора TailorFunction(argv[0],K,N,n); return 0; }
|
|