3. Инициализировать цикл (количество итераций равно длине введенной пользователем строки).
4. Перемещаться во введенной строке посимвольно.
5. Если символ цифра перейти к пункту 6, иначе перейти к пункту 8.
6. Переводим символ в цифру.
7. Прибавляем цифру к числу, которое будет являться переводом введенной строки, если она число, предварительно умноженное его на десять.
8. Выдаем сообщение об ошибке и переходим к пункту 2.
9. Запоминаем получившееся число при корректном вводе.
Второй проблемой явилось переполнение типа данных – longпри перемножении (в данной программе, написанной на языке С). Однако она была решена при написании функций проверки при перемножении и общей проверки коэффициентов генерируемого полинома, которые будут приведены ниже.
Третья проблема – переполнение буфера. При написании программы пришлось увеличить буфер для ввода значений, но при считывании рассматривать только первые девять символов, чтобы заведомо не превысить максимальное значение используемого типа, и, если было введено более девяти символов, то выдать сообщение об ошибке и попросить пользователя заново ввести значение.
Четвертая проблема – хранение введенных данных. Для ее преодоления было использовано четыре массива; в первом (массив m)будут храниться все корни генерируемого полинома (его размер – 2∙n, где n – степень генерируемого полинома), второй и третий – вспомогательные (участвуют в перемножении), в третьем (массив b) будет храниться корень генерируемого многочлена, взятый из первого массива, (его размер – 2); во втором (массив a) вначале храниться корень генерируемого многочлена из первого массива, а после первого перемножения в него будет перезаписываться результат перемножения для следующего выполнения этой операции (размер – n+1); последний массив (массив c) – результирующий, содержит все коэффициенты генерируемого многочлена после перемножения (размер n+1).
В данном пункте будут приведены некоторые части программы, реализующей алгоритм генерации полиномов, с пояснениями.
1. Функция реализующая нахождение модуля числа типа long
long Modul(long a)
{
if (a<0)
return (-a);
else
return (a);
}
Если функция получила отрицательное число, то она возвращает число с противоположным знаком, в противном случае само число.
Входные данные – число типа long.
Выходные данные – число типа long.
2. Функция проверки возможности выхода за диапазон типа long при перемножении корней генерируемого полинома.
int provper(long a, long b)
{
if(b==0 || a==0)
return(1);
else
if(Modul(a)<MAXLONG/Modul(b))
return(1);
else
return(0);
}
Если одно из переданных функции значений равно нулю, то функция возвращает единицу, иначе, если абсолютное значение одного из полученных функций значений меньше, чем число равное частному от деления максимального значения типа long на другое введенное значение, т.е., если при перемножении полученных функцией значений, их произведение не выходит за диапазон типа long, то функция возвращает единицу, в противном случае – ноль.
Входные данные – два числа типа long.
Выходные данные – число типа int (единица или ноль).
3. Функция проверки выхода за диапазон при сложении коэффициентов генерируемого полинома при одинаковых степенях переменного.
int provsum(long a, long b)
{
if(Modul(a)<(MAXLONG-Modul(b)))
return(1);
else
return(0);
}
Если одно из переданных функции значений меньше, чем разность максимального значения типа long и другого переданного значения, то функция возвращает единицу, в противном случае – ноль.
Входные данные – два числа типа long.
Выходные данные – число типа int (единица или ноль).
4. Функция, перемножающая два многочлена.
void peremnoz (long *a, int n, long *b, long *c)
{
long z=0;
int i,j;
for ( i=0; i<n;i++)
for( j=0; j<2; j++)
{
if(provper(*(a+i),*(b+j))==1)
z=(*(a+i)*(*(b+j)));
else
*(c+(i+j))=MAXLONG;
if(provsum(z,*(c+(i+j)))==1)
*(c+(i+j))+=z;
else
*(c+(i+j))=MAXLONG;
}
}
В функции инициализируются два цикла, один из которых вложен в другой. Внешний пробегает по всем коэффициентам первого многочлена, участвующего в перемножении (в программе реализуется в виде массива a, а коэффициенты многочлена – элементы массива а), внутренний – по коэффициентам второго многочлена (в программе – в виде массива b, коэффициенты многочлена – элементы массива b). Если перемножение коэффициентов (элементов массивов) возможно (начинает работу функция intprovper(longa, longb)), т.е. не произойдет выход за диапазон типа long, то результат перемножения записываем в переменную z, в противном случае, соответствующему коэффициенту результирующего многочлена (в программе – массив c, коэффициенты многочлена – элементы массива) присваивается максимальное значение (MAXLONG) типа longи внутренний цикл прекращает свою работу. Если произведение коэффициентов массива не вышло за диапазон типа long, то проверяем: не произойдет ли выход за диапазон типа long при сложении получившегося значения (храниться в переменной z) с коэффициентом результирующего многочлена (элемент массива c) (начинает работу функция intprovsum(longa, longb)); если сложение возможно, то к соответствующему коэффициенту результирующего многочлена (элемент массива c) прибавляется результат перемножения коэффициентов первых двух многочленов (значение переменной z), иначе, соответствующему коэффициенту результирующего многочлена присваивается максимальное значение (MAXLONG) типа long.
Работа функции перемножения основана на свойствах полинома (см. пункт 1.1.3).
Входные данные: три указателя типа long (на массивы, участвующие в перемножении, и на результирующий массив), число типа int (количество элементов первого массива).
5. Функция проверки нахождения коэффициентов генерируемого полинома в диапазоне используемого типа.
int prov(long *a, int n)
{
int i, y=0;
for(i=0;i<n+1;i++)
if(Modul(*(a+i))==MAXLONG)y++;
return (y);
}
В функции инициализируется цикл (количество итераций равно степени генерируемого многочлена, увеличенной на единицу). Производим движение по коэффициентам генерируемого многочлена (элементам массива a); если абсолютное значение какого-либо коэффициента генерируемого многочлена равно максимальному значению (MAXLONG) типа long, то значение флага (переменной y), изначально равное нулю, увеличиваем на единицу.
Входные данные: указатель типа long (на массив a), число типа int (степень генерируемого полинома, увеличенная на единицу).
Выходные данные: число типа int.
6. Часть программы, переводящая символ, являющийся цифрой, в число.
{
w=s[i]-'0';
q=10*q+w;
x=1;
}
Если введенный символ – цифра, то из кода этого символа вычитаем из кода символа код нуля и получаем число, соответствующее введенному символу.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <values.h>
#include <time.h>
long Modul(long a)
{
if (a<0) return (-a);
else return (a);
}
int provper(long a, long b)
{
if(b==0 || a==0)return(1);
else
if(Modul(a)<MAXLONG/Modul(b)) return(1);
else return(0);
}
int provsum(long a, long b)
{
if(Modul(a)<(MAXLONG-Modul(b))) return(1);
else return(0);
}
void peremnoz (long *a, int n, long *b, long *c) {
long z=0;
int i,j;
for ( i=0; i<n;i++)
for( j=0; j<2; j++)
{
if(provper(*(a+i),*(b+j))==1)
z=(*(a+i)*(*(b+j)));
else *(c+(i+j))=MAXLONG;
if(provsum(z,*(c+(i+j)))==1)
*(c+(i+j))+=z;
else *(c+(i+j))=MAXLONG;
}
}
int prov(long *a, int n)
{
int i, y=0;
for(i=0;i<n+1;i++)
if(Modul(*(a+i))==MAXLONG)y++;
return (y);
}
void main()
{
int stepen=0, n=2, w, x=0, i, k, f=1;
long *a, *b, *m, *c, q=0, z;
char *s;
s=(char *) calloc(900, sizeof(char ));
clrscr();
do{
printf("Введите степень не меньшую, чем 2 и не большую, чем 100:");
gets(s);
if(strlen(s)<1)
{
printf("\nНе было введено значения. Повторите ввод\n");
x=0;
}
if(strlen(s)>9)
{
printf("\nВведено более 9 символов. Повторите ввод\n");
x=0;
}
else
{
for( i=0;i<strlen(s); i++)
if (isdigit(s[i])!=0)
{
w=s[i]-'0';
q=10*q+w;
x=1;
}
else
{
printf("\nВведен символ или пробел. Повторите ввод\n");
x=0;
break;
}
stepen=q;
free(s);
s=(char *) calloc(900, sizeof(char ));
q=0;
w=0;
}
}while( stepen<2 || stepen>100 || x==0);
clrscr();
a=(long *) calloc(stepen+1, sizeof(long ));
b=(long *) calloc(2, sizeof(long ));
m=(long *) calloc((stepen)*2, sizeof(long ));
c=(long *) calloc(stepen+1, sizeof(long ));
for(i=0;i<stepen*2;i++)
{
if(i%2==0)
{
do{
q=0;
printf("Введитекореньмногочлена#%d ", (i/2)+1);
gets(s);
if(strlen(s)<1)
{
printf("\nНе было введено значения. Повторите ввод\n");
x=0;
}
if(strlen(s)>9)
{
printf("\nВведено более 9 символов. Повторите ввод\n");
x=0;
}
else
{
if(s[0]=='-')
for(k=1; k<strlen(s); k++)
if (isdigit(s[k])!=0)
{
w=s[k]-'0';
q=10*q+w;
x=1;
f=-1;
}
else
{
printf("\nВведен символ или пробел. Повторите ввод\n");
x=0;
break;
}
else
for( k=0; k<strlen(s);k++)
if (isdigit(s[k])!=0)
{
w=s[k]-'0';
q=10*q+w;
x=1;
f=1;
}
else
{
printf("\nВведен символ или пробел. Повторите ввод\n");
x=0;
break;
}
}
free(s);
s=(char *) calloc(900, sizeof(char ));
} while(x==0);
if(f==1)
{
*(m+i)=q;
q=0;
w=0;
*(m+i)=-*(m+i);
}
else
if(f==-1)
{
*(m+i)=q;
q=0;
w=0;
}
}
else *(m+i)=1;
}
for(i=0;i<2;i++)
{
*(a+i)=*(m+i);
*(b+i)=*(m+2+i);
}
for( k=0;k<stepen-1;k++)
{
peremnoz(a,n,b,c);
for( w=0; w<n+1; w++)
{
*(a+w)=*(c+w);
*(c+w)=0;
}
for(w=0;w<2;w++)
*(b+w)=*(m+(i*n)+w);
n++;
}
clrscr();
if(prov(a,stepen)!=0)
{
printf("\nПроизошел выход за диапазон типа.");
printf("\n\nПри следующем использовании данного программного продукта будьте осторожны с\n вводимыми значениями степени и корней");
printf("\n\nСпасибо, что пользовались моим прогаммным продуктом!:)");
printf("\n\nНажмите любую кнопку.");
}
else
{
printf("\Генериремый полином:\n");
printf("x^%d",stepen);
for(i=stepen-1;i>0;i--)
{
if(i==1)
if(*(a+i)==-1) printf("-x");
else
if(*(a+i)==1) printf("+x");
else
if(*(a+i)<0) printf("%ldx",*(a+i));
else
if(*(a+i)>0) printf("+%ldx",*(a+i);
else n++;
else
if(*(a+i)==-1) printf("-x^%d",i);
else
if(*(a+i)==1) printf("+x^%d",i);