Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
24
Добавлен:
19.05.2015
Размер:
719.36 Кб
Скачать

Var f: Text; { указатель на текстовый файл }

s: string;

a, b, c: real; { коэффициенты уравнения }

D: real; { дискриминант }

X1, x2: real; { корни уравнения }

I, r: integer; { вспомогательные переменные }

begin

Assign(F, 'eq.txt');

Reset(F);

readln(F, s); { читаем первую строку файла }

Close(F);

{ обработка данных, запись корней уравнения в x1 и x2 }

Append(F);

writeln(F, x1); { вывод результатов в конец файла }

writeln(F, x2);

Close(F);

end.

Обратите внимание на три момента:

  • после завершения файловой операции (чтения, записи или добавления) файл нужно закрывать вызовом Close;

  • после вызова Close мы можем снова использовать тот же указатель F;

  • вызывать второй раз Assign не нужно, поскольку мы записываем в тот же файл.

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

2a-4b-6

2a-6-4b

-4b+2a-6

-4b-6+2a

-6+2a-4b

-6-4b+2a

Поэтому примитивный алгоритм (найти символ «a», слева от него – старший коэффициент и т.д.) не срабатывает. Тогда как искать коэффициенты?

Понятно, что нужно проходить вдоль строки, начиная с первого символа, и выделять очередной коэффициент. Рассмотрим алгоритм выделения первого (по порядку) коэффициента из строки s. Число заканчивается там, где встречается один из стоп-символов: 'a', 'b', '+' или '-'. Для удобства добавим в конец строки символ '!' – он нужен для того, чтобы остановиться в том случае, когда последний коэффициент – это свободный член уравнения, и за ним строка кончается.

s:=s+'!';

i:=1;

while i <= Length(s) do begin

{ обработка символа s[i] }

i:=i+1;

end;

Предположим, что мы нашли символ 'a', слева от него стоит коэффициент при . Его можно раскодировать в вещественную переменнуюa:

if s[i] = 'a' then begin

if i = 1 then a := 1; { нет коэффициента => a=1}

else Val(Copy(s,1,i-1), a, r); { есть коэффициент }

s:=Copy(s, i+1, Length(s)-i); { удалить из строки }

i := 0; { начать с начала }

end;

Поясним этот фрагмент. Если символ 'a' – первый в строке, значит коэффициент равен 1, этот вариант мы учитываем с помощью условного оператора. Если символ не первый, раскодируем значение переменной a (с помощью Val) из той части строки, которая находится слева от буквы 'a'. Затем удаляем из строки всю обработанную часть (вместе с буквой 'a') и устанавливаем номер символа в 0 (чтобы начать с начала измененной строки на следующем шаге цикла). Аналогично раскодируется значение b.

Когда мы определяем свободный член уравнения, мы найдем символы ‘+’, ‘-‘ или ‘!’ (если этот коэффициент стоит в конце строки). Обратим внимание, что если символ ‘+’ и ‘-‘ – первый в строке, то останавливаться не нужно, число еще не закончилось, а только началось.

if (s[i] = '+') or (s[i] = '-') then

if i > 1 then begin

Val(Copy(s,1,I-1), c, r);

s:=Copy(s, i, Length(s)-i);

i := 0;

end;

Если коэффициент последний, то встретим '!':

if (s[i]] = '!') and (i > 1) then

Val(Copy(s,1,i-1), c, r);

Условие i>1 отсекает случай, когда свободный член – не последний коэффициентв в строке, и перед символом '!' стоит ‘a’ или ‘b’.

Квадратное уравнение решается классическим способом. Предполагаем (по условию), что дискриминант не меньше нуля и уравнение имеет вещественные корни. Вот полная программа:

var F: Text;

s: string;

i, r: integer;

a, b, c, D, x1, x2: real;

begin

Assign(F, 'eq.txt');

Reset(F);

Readln(F, s);

Close(F);

s:=s+'!';

i:=1;

while i <= Length(s) do begin

case s[i] of

'a': begin

if i > 1 then

Val(Copy(s,1,i-1), a, r)

else a := 1;

s:=Copy(s, i+1, Length(s)-i);

i := 0;

end;

'b': begin

if i > 1 then

Val(Copy(s,1,i-1), b, r)

else b := 1;

s:=Copy(s, i+1, Length(s)-i);

i := 0;

end;

'+','-':

if i > 1 then begin

Val(Copy(s,1,i-1), c, r);

s:=Copy(s, i, Length(s)-i);

i := 0;

end;

'!':

if i > 1 then

Val(Copy(s,1,i-1), c, r);

end;

i:=i+1;

end;

D:= b*b-4*a*c;

x1 := (-b - sqrt(D)) /(2*a);

x2 := (-b + sqrt(D)) /(2*a);

Append(F);

writeln(F, x1);

writeln(F, x2);

Close(F);

end.

Альтернативное решение задачи предложил А.С. Абрамов (лицей при РГСУ, г.Воронеж):

var F: Text;

s, s0: string;

i, k, r: integer;

a, b, c, D, x1, x2: real;

mas : array[1..3] of string;

begin

Assign(F, 'eq.txt');

Reset(F);

Readln(F, s);

Close(F);

{ разбиваем уравнение на 3 части, каждая часть

будет содержать коэффициент уравнения и его знак,

а также букву 'a' или 'b', если это не свободный член }

i:= 0;

for k:=1 to 3 do

repeat

i:=i+1;

mas[k]:= mas[k] + s[i]

until (s[i+1]='+') or (s[i+1]='-') or (i=length(s));

{ если 1-й член положительный, добавляем ему его знак '+'}

if s[1] <> '-' then

mas[1]:= '+' + mas[1];

{ если коэффициент при a и b указан неявно, т.е. равен 1,

добавим эту 1 между знаком и буквой }

for k:=1 to 3 do

if (length(mas[k]) = 2) and

((mas[k][2] = 'a') or (mas[k][2] = 'b')) then

mas[k]:= mas[k][1] + '1' + mas[k][2];

{ в случае a или b на последнем месте, читаем до

предпоследнего символа, иначе - до последнего,

и переводим строку в число }

for k:=1 to 3 do begin

s:= mas[k];

i:= length(s);

if mas[k][i] = 'a' then begin

s0:= Copy(s,1,i-1);

Val(s0, a, r);

end

else

if mas[k][i] = 'b' then begin

s0:= Copy(s,1,i-1);

Val(s0, b, r);

end

else begin

s0:= Copy(s,1,i);

Val(s0, c, r);

end;

end;

{ вычисление корней уравнения }

D:= b*b - 4*a*c;

x1 := (-b - sqrt(D)) /(2*a);

x2 := (-b + sqrt(D)) /(2*a);

Append(F);

writeln(F, x1);

writeln(F, x2);

Close(F);

end.

  1. Простая задача, в которой нужно подсчитать, сколько раз встречается каждое из чисел из диапазона 1..12 во входных данных, а затем отсортировать список задач по возрастанию числа запросов. Для хранения данных удобнее использовать запись (структуру) с двумя целыми полями: в одном хранится номер задачи, во втором – количество запросов по ней:

type TInfo = record

zadacha: integer;

count: integer;

end;

Всего может быть 12 задач, поэтому нужно объявить массив из 12 таких записей:

const MAX = 12;

Соседние файлы в папке ЕГЗ_2012_Поляков_май