1

Тема: Тричлен

Доброго вечора!
Є така задача

Прихований текст

Тричлен a + bx + сy двох змінних x і y однозначно визначається коефіцієнтами a, b та c. Написати програму, яка за заданими a, b та c виводить відповідний тричлен, що записаний з використанням таких алгебраїчних правил:
•    коефіцієнт при члені, що містить змінну, опускається, якщо його модуль дорівнює одиниці;
•    член, коефіцієнт якого дорівнює нулю, опускається (крім випадку, коли всі коефіцієнти дорівнюють нулю, тоді тричлен складається з однієї цифри 0);
•    знак "+" опускається, якщо він передує від'ємному коефіцієнту;
•    знак "+" опускається, якщо він стоїть на початку виразу (так званий унарний плюс);
•    знак множення між коефіцієнтом та змінною не записується.
При цьому заборонено міняти місцями члени.

Ось мій код
program secret;

var
  z, a1, b1, c1, m, n: string;
  a, b, c, i: integer;



begin
  read(a, b, c);
  str(a, a1);
  str(b, b1);
  str(c, c1);
  m := 'x';
  n := 'y';
  
  
  z := a1 + '+' + b1 + m + '-' + c1 + n;
  if b1 = '1' then delete(z,  pos(b1, z), length(b1)); 
  if c1 = '1' then delete(z,  pos(c1, z), length(c1));
  if a1 = '0' then delete(z,  pos(a1, z), length(a1));
  if b1 = '0' then begin delete(z,  pos(b1, z), length(b1)); delete(z, pos(m, z), length(m)) end;
  if c1 = '0' then begin delete(z,  pos(c1, z), length(c1)); delete(z, pos(n, z), length(n)) end;
  if (a1 = '0') and (b1 = '0') and (c1 = '0') then z := '0';
  if z[1] = '+'  then delete(z, pos('+', z), length('+'));
  if z[1] = '-'  then delete(z, pos('-', z), length('-'));
  for i := 1 to (length(z)) + 1 do
    if (z[i] = '+') and (z[i + 1] = '-') then delete(z, pos(z[i], z), 1);
  
  
  writeln(z);
  
end.

Але вибиває помилку

Прихований текст

Ошибка времени выполнения: Индекс выходит за границы массива

2

Re: Тричлен

for i := 1 to (length(z)) + 1 do

має бути

for i := 1 to (length(z)) do

Детальніше

Прихований текст

Delphi работает со строками типа String, в котором длина строки записывается в начале строки, перед первым символом. Поэтому индекс первого символа в строке не 0, а 1.

Подякували: Q-bart1

3 Востаннє редагувалося Q-bart (22.12.2014 19:35:46)

Re: Тричлен

Але це паскаль...
І помилка лишилась...

4

Re: Тричлен

Q-bart написав:

Але це паскаль... І мені вчитель казав - перший елемент - 1 ... Це неправильно??
І помилка лишилась...

Ви використовуєте тип String? Тому і інформацію шукайте про нього. Pascal/Delphi/PascalABC/Object Pascal/TurboPascal це все паскаль в різних варіаціях.
Просто запам'ятайте, в нульовому індексі рядка S[0] зберігається його довжина, а значить перший S[1] це перша літера, останній відповідно - це довжина рядка S[length] = останній елемент.

Подякували: Q-bart1

5

Re: Тричлен

Дивіться ще, коли у Вас виконується функція delete(z...); Ваш рядок z автоматично зменшує свою довжину, правильно? А цикл продовжує виконуватись, звертаючись вже за межами рядка.

Подякували: Q-bart1

6

Re: Тричлен

Chemist-i написав:

S[length]

Чи не length(s)???
помилка так і залишилась..

7 Востаннє редагувалося Q-bart (22.12.2014 19:44:35)

Re: Тричлен

Chemist-i написав:

Дивіться ще, коли у Вас виконується функція delete(z...); Ваш рядок z автоматично зменшує свою довжину, правильно? А цикл продовжує виконуватись, звертаючись вже за межами рядка.

Що тоді робити?
Виходити з циклу?? Але воно тоді не все повидаляє...

8

Re: Тричлен

Q-bart написав:
Chemist-i написав:

S[length]

Чи не length(s)???
помилка так і залишилась..

length це эквівалент слова довжина
S[довжина рядка] = останій елемент.

Подякували: Q-bart1

9 Востаннє редагувалося Q-bart (22.12.2014 19:52:23)

Re: Тричлен

теж саме....
А-а-а, видалили комент....

10

Re: Тричлен

Q-bart написав:

А-а-а, видалили комент....

Так, то я трохи поспішив...

11

Re: Тричлен

Chemist-i написав:
Q-bart написав:

А-а-а, видалили комент....

Так, то я трохи поспішив...

Буває,...

12

Re: Тричлен

Змініть підхід до вирішення проблеми. Заведіть п’ять стрінгових змінних, які будуть представляти те, як слід записати a,b,c,x,y, вичисліть їх по заданим правилам і в кінці складіть в правильному порядку.

Подякували: Chemist-i, Q-bart2

13

Re: Тричлен

От в мене отаке працює

i:=1;
    while ( true ) do
    begin
      if (z[i] = '+') and (z[i + 1] = '-') then delete(z, pos(z[i], z), 1);
      inc(i);
      if (i >= length(z)) then Break;
    end;

Тут якщо бачимо, що i вже останій елемент - просто завершуємо цикл.

Подякували: Q-bart1

14

Re: Тричлен

Я б теж збирав по шматочках за правилами - по одному шматку за раз. Додавати і потім викидати - марна праця.

Подякували: Q-bart1

15 Востаннє редагувалося Q-bart (23.12.2014 11:30:17)

Re: Тричлен

Ось так в мене вийшло

program secret;

var
  z, a1, b1, c1, m, n: string;
  a, b, c, i: integer;



begin
  m := 'x';
  n := 'y';
  read(a, b, c);
  str(a, a1);
  str(b, b1);
  str(c, c1);
  
  
  if a1 = '0' then a1 := '';
  if b1 = '0' then begin b1 := ''; m := ''; end;
  if c1 = '0' then begin c1 := ''; n := ''; end;
  
  if b1 = '1' then b1 := '';
  if c1 = '1' then c1 := '';
  
  z := a1 + '+' + b1 + m + '-' + c1 + n;
  
  i := 1;
  while i <= length(z) do 
  begin
    if (z[i] = '+') and (z[i + 1] = '-') then delete(z, pos(z[i], z), 1); {видаляєм плюс якщо він перед мінусом}
    if (z[i] = '-') and (z[i + 1] = '-') then begin  z[i]:='+'; delete(z, pos(z[i+1], z), 1); end;{якщо два мінуси, - один виаляєм, а другому присвоюєм плюс}
    inc(i);
    
    if (i >= length(z)) then break;
  end;
  if z[1]='+' then delete(z, 1, 1);
  if (z[length(z)]='-')or (z[length(z)]='+')then delete(z, pos(z[length(z)], z), 1);
  if (a1 = '0') and (b1 = '0') and (c1 = '0') then z := '0';
  writeln(z);
  
end.

Але воно не працює, якщо ввести

 -2 -3 -4

видає

2-3x+-4y

Цей if

 if (z[i] = '-') and (z[i + 1] = '-') then begin  z[i]:='+'; delete(z, pos(z[i+1], z), 1); end;

має видаляти, але цього не робить, чому???

16

Re: Тричлен

Q-bart написав:
2-3x+-4y

Цей if

if (z[i] = '-') and (z[i + 1] = '-') then begin z[i]:='+'; delete(z, pos(z[i+1], z), 1); end;

має видаляти, але цього не робить, чому???

if (z[i] = '-') and (z[i + 1] = '-') then 
    begin  
        z[i]:='+'; 
        delete(z, pos(z[i+1], z), 1); 
    end;
Якщо (z[i] = '-') та (z[i + 1] = '-') то (щось там видаляємо)

Щоб виконався оператор - обидва операнду маєть повернути труЪ, т.є має бути '--' (а у вас '+-')

Подякували: Q-bart1

17

Re: Тричлен

Ну так, якщо без цього if то виводить "--"
а з іфом - одне виконує(присвоєння), а друге (видалення) - ні

18

Re: Тричлен

Q-bart написав:

Ну так, якщо без цього if то виводить "--"
а з іфом - одне виконує(присвоєння), а друге (видалення) - ні

Я Ваш новий вчитель, і я даю Вам нове завдання =) . Зробити оце все не використовуючи жодної операції delete() з рядка. Уточнення. Працюйте окремо з членами, а конкатенацію робіть в кінці.
член зразу записуйте із знаком, наприклад додатнє 2х записуйте '+2х', від'ємне 2х записуйте '-2х', коли це перший член і він додатній - записуйте без знака '2х', коли останій член і нульовий - нічого не записуйте ''.
А в кінці конкатенація тих трьох стрінгів в одне і вивід...

Подякували: quez, Q-bart2

19

Re: Тричлен

Ну, отже зробив, все працює, але без делете не обійшлося, хоч воно і працює не там де було до того...

program secret;

var
  z, a1, b1, c1, m, n: string;
  a, b, c, i: integer;



begin
  z:='                ';
  m := 'x';
  n := 'y';
  read(a, b, c);
  str(a, a1); if (a1[1]='-') or (a1[1]='+') then delete(a1, 1,1);
  str(b, b1); if (b1[1]='-') or (b1[1]='+') then delete(b1, 1,1);
  str(c, c1); if (c1[1]='-') or (c1[1]='+') then delete(c1, 1,1);
  
  
  if a1 = '0' then a1 := '';
  if b1 = '0' then begin b1 := ''; m := ''; end;
  if c1 = '0' then begin c1 := ''; n := ''; end;
  
  if b1 = '1' then b1 := '';
  if c1 = '1' then c1 := '';
  if a<0 then a1:='-'+a1;
  if b<0 then b1:='-'+b1;
  if c<0 then c1:='+'+c1;
  if c>0 then c1:='-'+c1;
  if b>0 then b1:='+'+b1;
  z := a1  + b1 + m  + c1 + n;
  if z[1]='+' then delete(z, 1,1);
  writeln(z);
  
end.
Прихований текст

Вчителю, оцініть.

20

Re: Тричлен

Q-bart, серйозно нормально працює?, ну добре.
Давайте спершу нормально його розмітимо і я його відкоментую

Прихований текст
program secret;
var
    z, a1, b1, c1, m, n: string;
    a, b, c, i: integer;
begin
    z:=' '; //Навіщо?
    m := 'x'; //Прикольна ідея давати рядку, який буде містити х назву m (мабуть, щоб вороги не здогадались)
    n := 'y'; //Те саме.
    
    read(a, b, c); //Читаємо а, б, с, окей
    
    //а тут починається щось, чого я не розумію, для чого це?
    //ми перетворюємо число в рядок, після того відчикрижуємо його знак
    //і залишається у нас беззнаковий (такий собі модуль числа члена, причому рядковий)
    str(a, a1); 
    if (a1[1]='-') or (a1[1]='+') then delete(a1, 1,1);
    
    str(b, b1); 
    if (b1[1]='-') or (b1[1]='+') then delete(b1, 1,1);
    
    str(c, c1); 
    if (c1[1]='-') or (c1[1]='+') then delete(c1, 1,1);
    
    if a1 = '0' then a1 := ''; //як перший член 0 змінюємо його на нічого, гаразд
    
    if b1 = '0' then //ну тут я Вашу криптозбочену логіту почав трохи розуміти
    begin 
        b1 := '';
        m := ''; 
    end;
    
    if c1 = '0' then 
    begin 
        c1 := ''; 
        n := ''; 
    end;
    
    //і тут починається... (нагадує викладача в інституті - "забудьте все чому вас навчали в школі")
    //вбиваємо одинички, додаєм знаки які позабирали напочатку (нагадує 2-х робітників СРСР,
    //один викопує яму, інший тут-же закопує, обидав молодці, обидва план виконують)
    if b1 = '1' then b1 := '';
    if c1 = '1' then c1 := '';
    if a<0 then a1:='-'+a1;
    if b<0 then b1:='-'+b1;
    if c<0 then c1:='+'+c1;
    if c>0 then c1:='-'+c1;
    if b>0 then b1:='+'+b1;
    
    z := a1 + b1 + m + c1 + n; //тут се збираємо докупи
    
    if z[1]='+' then delete(z, 1,1); //і наостанок вбиваємо знак на самому початку
    writeln(z); //Виводимо.
end.

Як би зробив я.
після отримання від користувача а, б, ц, в вас вже є цілочисленні значення із знаком? навіщо купа зайвих перетворень у текст?

Прихований текст
//отримали, працюйте зразу
read(a, b, c);

//працюємо з першим членом
if (a > 0) then //якщо а > 0
begin
    str(a, a1); //перетворюємо
end
else //інакше
    if (a = 0) then //якщо а = 0
    begin
        a1 := ''; //нічого не записуємо, ні знаку, ні цифри
    end
    else //якщо все вищезведене не підійшло (a < 0) то
        begin
            //можна зробити так str() сам підставить знак
            //str(a, a1); //перетворюємо
            //a1 := a1 + 'x'; //додаємо х

            //але для наглядності покажу як чипляти знак, за допомогою функції модуль, або абсолютна величина (Abc())
            str( abc(a) , a1);
            a1 := '-' + a1;    //і знову ж таки додаємо знак
        end;


//тепер так само з другим членом, все точно так само, тільки це другий член і в нього є додаткові умови
if (b > 1) then //якщо b > 0
begin
    str(b, b1); //перетворюємо
    b1 := '+' + b1 + 'x'; //додаємо x
end
else //інакше
    if (b = 1) then //якщо b = 1
    begin
        b1 := '+x'; //просто x
    end
    else
        if (b = 0) then //якщо b = 0
        begin
            b1 := ''; //нічого не записуємо, ні знаку, ні символу
        end
        else //інакше 
            if (b = -1) then //якщо b = -1
            begin
                b1 := '-x'; //додаємо -x
            end
            else //якщо все вищезведене не підійшло (b <- 1) то
            begin
                //але для наглядності покажу як чипляти знак, за допомогою функції модуль
                str( abc(b) , b1);
                b1 :='-' + b1 + 'x'; //і знову ж таки додаємо знак і символ
            end;


//і на закуску третій член, точно такий самий як і другий
if (c > 1) then //якщо c > 0
begin
    str(c, c1); //перетворюємо
    c1 := '+' + c1 + 'y'; //додаємо y
end
else //інакше
    if (c = 1) then //якщо c = 1
    begin
        c1 := '+y'; //просто c
    end
    else
        if (c = 0) then //якщо c = 0
        begin
            c1 := ''; //нічого не записуємо, ні знаку, ні символу
        end
        else //інакше 
            if (c = -1) then //якщо c = -1
            begin
                c1 := '-y'; //додаємо -y
            end
            else //якщо все вищезведене не підійшло (c <- 1) то
            begin
                //але для наглядності покажу як чипляти знак, за допомогою функції модуль
                str( abc(c) , c1);
                c1 :='-' + c1 + 'y'; //і знову ж таки додаємо знак і символ
            end;

як бачите другий і третій члени асболютно однакові,
змінюються тільки назва, тому їх можна зліпити у цикл з двома ітераціями, але мені лінь то робити

тепер оброблюємо кінець, просто зливаючи члени вкупу, "але є одне але, скорочено АЄОА", поглянемо ще раз в завдання і бачимо там:
"крім випадку, коли всі коефіцієнти дорівнюють нулю, тоді тричлен складається з однієї цифри 0"
так і пишемо

if (a = 0) and (b = 0) and (c = 0) then z := '0'
else z := a1 + b1 + c1;
// тут виводимо z...

п.с. я її не тестував, тому можуть бути незначні помилки

Подякували: Q-bart1