Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование с нуля - это совсем просто! 30) О типовых ошибках


Информационный Канал Subscribe.Ru

 
Школа программирования

Программирование с нуля - это совсем просто!

30) О типовых ошибках

Прежде всего важная информация:

По поводу Д. в 6-ой рассылке наткнулся на вопрос о Д.8 - " Вообщем, в инспекторе обьектов нет такого свойства как caption".
Он есть, просто надо выбирать в File/New - не Windows forms, а VСL Forms и будет вам счастье.
Так что зря на Delphi 8 наехали, по-моему, в нём можно делать всё, что делают в D. 7 :)
Антон

Ура! Мы эту особенность Дельфи рассмортим далее.

Что касается ошибок, то бывает, между прочим, и так:)

Собиралась написать несколько раз:
1. когда не получалась программа на С++. Я даже сфотографировала ошибку. Но потом проблема сама собой разрешилась, когда я сделала все снова.
Наталья

Чаще всего проблемы вызывает условный оператор. Точнее, неверное его использование :)

Во-первых, часто путаются в then - else. Где что чему соответствует, какой end какому begin-у итд.

Это потому, что не применяются отступы и пустые строки, а сам код пишется строчка за строчкой.

А как же его писать-то, спросите?

Лучше вводить его сразу целым блоком. Как-то так:

  if then
    begin

    end

  else
    begin

    end;

Потом вставляете условие, далее - внутрь каждой пары begin / end команды, и так далее. И максимально наглядно, чтобы каждая пара begin end была на одном уровне.

Еще одна важная особенность условного оператора. Для Паскаля и Си актуальная!

  1. почему не нравится что-то?
  if (a>b) and (b>c) then
   begin
   p:=100*a+10*b+c; //Value assigned to p never used
   m:=100*c+10*b+a; //Value assigned to m never used
   end;

За комментарием - это предупреждение компилятора. О чем оно? О том, что значение, занесенное в переменную p, далее нигде не используется. Умный компилятор, правда? Действительно, зачем нам в программе переменная, если мы ее нигде далее не задействуем, даже не выведем на экран. Такие предупреждения всегда надо учитывать.

И вот собственно ошибка:

  if (c>a) and (a>b) then ;
           begin
           p:=100*c+10*a+b;
           m:=100*b+10*a+c;
...

Команды, взятые в группу, выполняются в любом случае. Почему?

Потому что за then поставлена незаметная точка с запятой. А она означает завершение оператора (в данном случае условного). То есть на самом деле такая запись:

  if (c>a) and (a>b) then ;

Трактуется так:

  if (c>a) and (a>b) then
    begin

    end;

Внимательно, без спешки, набирайте операторы.

Проверяйте пошагово, все веточки.

Если вводите begin, сразу же для него укажите end, только потом вводите группу команд между ними.

Точка с запятой НЕ ставится (точнее, поставить можно, но лучше не надо) после then :) , после begin, перед else, перед end.


Продолжение ответов на первые задачи:

  1).
  var a,b:Integer;
  begin
    Write( ' Vvedite chislo a: ' );
    ReadLn(a);
    Write( ' Vvedite chislo b: ' );
    ReadLn(b);
    if a=b then
      begin
       Write( ' Oba chisla ravnie ' );
       Readln;
      end;
    if a>b then
      begin
       Write( ' Chislo a bolshe,ego znachenie: ' ,a);
       Readln;
      end
     else
      begin
       Write( ' Chislo b bolshe,ego znachenie: ' ,b);
       Readln;
      end;
  end.

  2).
  var x,y,z:Integer;
  begin
    Write( ' Vvedite chislo x: ' );
    ReadLn(x);
    Write( ' Vvedite chislo y: ' );
    ReadLn(y);
    Write( ' Vvedite chislo z: ' );
    ReadLn(z);
    if (x<y) and (x<z) then
      begin
       Write( ' Chislo x minimalnoe,ego znachenie: ' ,x);
       Readln;
    end;
    if (x<y) and (x>z) then
      begin
       Write( ' Chislo z minimalnoe,ego znachenie: ' ,z);
       Readln;
    end;
    if (x>y) and (x<z) then
      begin
       Write( ' Chislo y minimalnoe,ego znachenie: ' ,y);
       Readln;
      end;
    if (x=y)or (x=z) or (y=z)then
      begin
       Write( ' Chisla odinakovie ' );
       Readln;
      end;
  end.

  3).
  var x,y,z,a,b:Integer;
  begin
   Write( ' Vvedite chislo x: ' );
    ReadLn(x);
   Write( ' Vvedite chislo y: ' );
    ReadLn(y);
   Write( ' Vvedite chislo z: ' );
    ReadLn(z);
   a:=x+y+z;
   b:=x*y*z;
   if a>b then
    begin
     Write( ' Bolshe summa,ee znachenie: ' ,a);
     Readln;
    end;
   if a<b then
    begin
     Write( ' Bolshe proizvedenie,ee znachenie: ' ,b);
     Readln;
    end
   else
    begin
     Write( ' proizvedenie ravno summe ' );
     Readln;
    end;
  end.

  4).
  var x,y,z:Integer;
  begin
    Write( ' Vvedite chislo x: ' );
    ReadLn(x);
    Write( ' Vvedite chislo y: ' );
    ReadLn(y);
    Write( ' Vvedite chislo z: ' );
    ReadLn(z);
    if (x=y) or (y=z) or (x=z) then
      begin
       Write( ' Odinakovoe znachenie! ' );
       Readln;
      end;
    if (x>y) and (y>z) then
      begin
       Write( ' Znachenie raznosti: ' ,(x-z));
       Readln;
      end
    else
     if(y>z) and (y>x) then
       begin
       Write( ' y maximalnoe chislo: ' ,y);
       Readln;
     end
    else
     if(y<z) and (z>x) then
       begin
       Write( ' z maximalnoe chislo: ' ,z);
       Readln;
     end;
  end.

  5).
  var a,b:Integer;
  begin
    Write( ' Vvedite chislo a: ' );
    ReadLn(a);
    Write( ' Vvedite chislo b: ' );
    ReadLn(b);
    if a>b then
      begin
       a:=a*b;
       Write( ' Chislo a bolshe,ego znachenie stalo: ' ,a);
       Readln;
      end
     else
      begin
       b:=a+b;
       Write( ' Chislo b bolshe ili ravno,ego znachenie stalo: ' ,b);
       Readln;
      end;
  end.

  Константин.

Программы для задачи по Фанте:

Кстати:

Если вы действительно не знаете, как правильно решается задача про Фанту, то возьму на себя смелость сказать, что верное решение - у Лены, но не в словесном алгоритме, а в программе. В программе она начинает считать с пятницы, что, по-моему, и есть верный путь, ведь при минимальной начальной сумме в пятницу утром хватит денег ровно на одну бутылку.
Леонид

  Никак не получалось решить задачку о фанте, просмотрел другие
  ответы,
  ничего не могу сказать о правильности, но какие то все сложные.

  А потом решение само как то в голове образовалось:

  k - стоимость бутылки фанты;
  m - стоимость пустой бутылки;
  n - количество денег у друзей;
  x - размер компании, количество человек (служит для того чтобы
  никого
  не обидеть :), всем в пятницу по 1 бутылке!)

  Поскольку каждый раз ребята сдавали пустые бутылки, значит за
  посуду
  им пришлось платить только один раз - первый, отсюда:

  1. Введем k, m и x;
  2. n = (k-m)*x*5+m*x;
  Определяем стоимость фанты без бутылки и умножаем ее на
  количество
  человек в компании и на количество дней, к полученому результату
  прибавляем стоимость пустой бутылки умноженую на количество
  человек в
  компании;
  3. Напечатать n;
  4. Конец

  Если неважно количество человек в компании, просто убираем x.
  И по моему ВСЕ!

  program fanta;
  {$APPTYPE CONSOLE}

  var k, m, n, x :integer;

  begin

  writeln( ' vvedite stoimost 1 bytulki fantu ' );
  readln(k);
  writeln( ' vvedite stoimost pystoi bytulki ' );
  readln(m);
  writeln( ' vvedite razmer kompanii ' );
  readln(x);
  n := (k-m)*x*5+m*x;
  write ( ' nyjno imet ' );
  write (n);
  write ( ' ryblei ' );
  readln;

  end.

  Ух, Фанта парамия Рикки! :)

  Сергей

Еще вариант:

  var N,i,P,F,D,Sd:integer;
   begin
     writeln( ' cena fanty ' );
     readln(f);
     writeln( ' cena steklotary ' );
     readln(p);
     D:=F;
     for i:=2 to 5 do
       begin
         N:=D div P;
         Sd:=D mod P;
         D:=F*N+Sd;
       end;
    writeln( ' NADO DENEG ' ,D);
    readln;
   end.

   Нахождение корней квадратного уравнения

  begin

     writeln( ' vvedite a,b,c ' );
     readln(a,b,c);
     D:=b*b-4*a*c;
     if D>0 then
       begin
         x1:=(-b+sqrt(D))/(2*a);
         x2:=(-b-sqrt(D))/(2*a);
         writeln( ' x1= ' ,x1);
         writeln( ' x2= ' ,x2);
       end;
     if D=0 then
       begin
         x1:=-b/(2*a);
         writeln( ' x1= ' ,x1);
       end;
     if D<0 then
       writeln( ' korney net ' );
       readln;

  end.
     Задача "Влезет ли паралелограм и Паз".
      

  var x,y,z,w,h,min1,min2,a,b,max:real;
  begin
      writeln( ' vvedite storony paralelograma ' );
      readln(x,y,z);
      if (x<=0)or(y<=0)or(z<=0) then
      writeln( ' vvedite dopustimye znacheniya ' )
      else
       begin min1:=x;{min1 & min2- наименьшие стороны паралелограмма}
       if y<x then min1:=y;
       if z<y then min1:=z;
        max:=x;
       if y>x then max:=y;
       if z>x then max:=z;
       min2:=(x+y+z)-(min1+max);
        writeln( ' vvedite storony paza ' );
        readln(w,h);
        if w>h then
          begin
          a:=w-min2;
          b:=h-min1;
          end;
          if h>w then
            begin
             a:=h-min2;
             b:=w-min1;
            end;
     if (A>=0)and(B>=0) then writeln( ' vlezet ' )
     else writeln( ' ne vlezet ' );
     end;
     readln;
  end.

  Вроде всё.
      Ярослав.

Кстати, в задании по квадратному уравнению несколько ошибок было.

Смею заметить ,что в задании 6 в записи уравнения есть ошибочка.
не y = ax2 + by + c.
Должно быть y = ax2 + bx + c. а точнее ax2 + bх + c=0
Алексей

Потом, очень важно!

Так было в одном из решений:

begin
x1:=(-b-kd)/2*a;
x2:=(-b+kd)/2*a;

Там надо поставить -
x1:=(-b-kd)/(2*a);
x2:=(-b+kd)/(2*a);
А то она будет писаь мол минус Б, плюс корень из ДЕ поделить на 2 и умножить а потом... Что так же очнь важно...

Это ВАЖНО !

Если записано

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

то компилятор операции с равным приоритетом (деление и умножение) будет выполнять (точнее, переводить в исполнимый код) слева направо. То есть сначала выполнится

(-b-kd)/2

а потом то, что получится, умножится на a.

( (-b-kd)/2 ) *a

Чтобы таких ошибок избежать, все знаменатели в любых формулах всегда желательно явно заключать в скобки!

Далее - по бруску :)
Обратите внимание, как хорошо - наглядно! - здесь выделены пары проверок and и or.

  program Project2;

  {$APPTYPE CONSOLE}

  uses math,
    SysUtils;
   var x,y,z,h,w:integer;
  begin
  write( ' x= ' );
  readln(x);
  write( ' y= ' );
  readln(y);
  write( ' z= ' );
  readln(z);
  write( ' h= ' );
  readln(h);
  write( ' w= ' );
  readln(w);
    if ((x<=h) and (z<=w)) or ((x<=h) and (y<=w)) or ((z<=h) and (y<=w)) then
      begin
      writeln( ' da ' );
      end
     else
       begin
       writeln( ' net ' );
         end;
     readln;
  end.
Лена

Следующие ответы.

  1) ввести два числа а и b и напечатать максимальное из них

   var x,y: Integer;

  begin
  WriteLn( ' Tablica znachenii ' );
  WriteLn( ' 1 2 3 4 5 6 7 8 9 10 ' );
  WriteLn( ' Vveditee dva chisla, na ekran viidet bolshee znachenie ' );
  Readln(x,y);
  if (x >= y) then
    begin
    WriteLn(x);
    end
     else
       begin
       Writeln(y);
       end;
    Readln;
  end.

  2) ввести три числа x, y, z. Напечатать минимальное из них.

  var x,y,z: Integer;

  begin
    Writeln( ' Vvedite tri chisla ' );
    ReadLn(x,y,z);
    WriteLn( ' Menshee znachenie = ' );
    if (x<=y) and (x<=z) then
    begin
    WriteLn(x);
    end
      else
      if (y<=x) and (y<=z) then
      begin
      Writeln(y);
      end
        else
        if (z<=x) and (z<=y) then
        begin
        Writeln(z);
        end;
  Readln;
  end.

  Кстати программа работает и так

  begin
    Writeln( ' Vvedite tri chisla ' );
    ReadLn(x,y,z);
    WriteLn( ' Menshee znachenie = ' );
    if (x<=y) and (x<=z) then
     WriteLn(x)
           else
           if (y<=x) and (y<=z) then
           Writeln(y)
                else
                if (z<=x) and (z<=y) then
                Writeln(z);
  Readln;
  end.
  3) ввести три числа x, y, z. Найти, что больше их сумма или
  произведение.

  var x,y,z: Integer;

  begin
  WriteLn( ' Vvedite tri chisla ' );
  ReadLn(x,y,z);
    if (x+y+z)>(x*y*z) then
    begin
    Write( ' Summa > chem Proizvedenie i ravno = ' );
    WriteLn(x+y+z);
    end
    else
      if (x+y+z)<(x*y*z) then
      begin
      Write( ' Proizvedenie > chem Summa i ravno = ' );
      WriteLn(x*y*z);
      end;
  Readln;
  end.

4)   var x,y,z: Integer;

  begin
    Writeln( ' Vvedite tri chisla ' );
    ReadLn(x,y,z);
    if (x>y) and (x>z) and (y>z) then
    begin
    WriteLn(x-z);
    end
    else
      if (x<y) and (x<z) and (y<z) then
        begin
        if (x>y) and (x>z) then
        WriteLn(x);
      end
        else
        if (y>x) and (y>z) then
        begin
        WriteLn(y);
        end
          else
          if (z>x) and (z>y) then
          begin
          WriteLn(z);
          end;
  Readln;
  end.

5   var a,b: Integer;
  begin
    Writeln( ' Vvedite dva chisla ' );
    ReadLn(a,b);
    if (a>b) then
    begin
    WriteLn(a*b);
    Write(b);
    end
    else
      if (a<b) then
        begin
        WriteLn(a);
        Write(a+b);
        end;
  Readln;
  end.
Вячеслав

Это далеко не все ответы. Они будут продолжены далее. На Си уже много вариантов, они будут тематически объединены. На Бейсике очень мало (к счастью :).

Обязательно присылайте свой код! Потому что учиться на примерах других людей, которые выполняют такие-же упражнения - очень полезно! Пожалуй, ничего эффективнее в этой области еще не придумано.

Поэтому подумайте о других ! :)


Упражнения на условный оператор. Закрепляющие :)

13. Даны два прямоугольника с вершинами x1,y1 и x2,y2, и шириной/высотой w1,h1 и w2,h2. Определить, пересекаются ли они.

Примеры:
а) x1=15,y1=18 w1=5,h1=2
x2=13,y1=19 w2=5,h2=2

б) 0,0 1,1
-2,-2 1,1

14. С клавиатуры вводится число. Если это 0, то завершить программу. Если нет, определить максимальное и минимальное из всех введенных на данный момент, напечатать эти мин/макс, и продолжить ввод следующего числа.
Воспользоваться циклами!

15. ИЗвестны три стороны треугольника - a, b, c. ПРоверить, может ли такой треугольник существовать, и если да - дополнительно указать, является ли он прямоугольным.

16. Задание с Пермской олимпиады (на циклы, условия, арифметику).

Начните с алгоритма на бумаге! (хотя все равно не послушаете :).

Древнерусское умножение . Известен древнерусский прием умножения. Для умножения a и b поступаем так: делим a на 2, а b умножаем на 2, причем если делимое — число нечетное, то берем целую часть частного. С полученными числами проделываем то же самое, пока в частном не получится единица. Для получения произведения ab складываются только те числа правого столбика, слева от которого стоят нечетные числа.
Пример: a = 42; b = 63:
42 63
21 126
10 252
5 504
2 1008
1 2016
ab = 126 + 504 + 2016 = 2643

Вам надо избавиться от столбика к тому же, и выполнять все вычисления на лету (в этом предыдущее задание поможет).

Кстати, вот письмо про олимпиады от Максима:

Хочу Вам сказать ( поделиться радостью ), что я только что приехал с олимпиады по базовому курсу информатики. Эта олимпиада рассказала мне много, например, что я не такой уж компьютерный гений (как кажется на первый взгляд) чтобы быть таковым, похоже, надо быть на нем помешанным. Ну или где-то около+ Гм-гх (это я кашляю простыл). В общем, задания то простые с одной стороны, а с другой ой. И так, ближе к делу...
Начну, пожалуй, с наиболее мне понравившегося, потому что если я дал на него правильный ответ, то оно очень хитрое , а если нет, то не очень интересное. Вот условие:
Алфавит первого племени содержит X символов, алфавит второго племени содержит в 8 раз больше символов. Племена обменялись приветствиями, содержащее одинаковое количество символов. В приветствии второго племени на 30 байт информации больше, чем в приветствии первого. Сколько символов могло быть в каждом приветствии? (2 балла) .
Не знаю правильно или нет, но я дал ответ X символов. Условие очень запутанное, на, прочитав его 6-ой раз, мне данный ответ показался правильным.

Кто решит? Я не смог :)

Вот еще, где-то прочитал, уже не помню:

Задачка для второго класса церковно-приходской школы, придуманная Львом Толстым.
(Сейчас якобы её правильно могут решить только 30% старшеклассников, 20% студентов ВУЗов и 10% работников банков и кредитных учреждений.)
Продавец продает шапку, которая стоит 10 РУБ.
Подходит покупатель, меряет и согласен взять, но у него есть только 25 РУБ.
Продавец отсылает мальчика с этими 25 рублями к соседке разменять. Мальчик прибегает и отдает 10+10+5. Продавец отдает шапку и сдачу 15 РУБ.
Через какое-то время приходит соседка и говорит, что 25 РУБ фальшивые, требует отдать ей деньги. Ну, что делать, мужик лезет в кассу и возвращает ей деньги.
Вопрос: на какую сумму в результате "налетел" продавец?

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

Вот письмо, над которым я долго смеялся! Надеюсь, и вы со мной.

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


Кстати. Где сказки? Неужели с творческой составляющей так плохо? Не ожидал, честно говоря...

От одного программирования только отупеете, предупреждаю :)

Пока мне не придет достаточное количество сказок, следующий выпуск выпускать не буду! :)


(c) 2004 Сергей Бобровский bobrovsky@russianenterprisesolutions.com

Школа программирования с нуля
http://russianenterprisesolutions.com/sbo/

Все предыдущие выпуски базового курса тут:
http://russianenterprisesolutions.com/sbo/base.htm

 

http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.prognull
Отписаться

В избранное