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

C и C++ для начинающих

  Все выпуски  

C и C++ для начинающих - Выпуск 9. Разбор полетов.


Служба Рассылок Subscribe.Ru проекта Citycat.Ru
Доброго времени суток! Сегодня я приведу решения домашних заданий с четвертого по восьмой выпуск рассылки.

Я получил от вас огромное количество писем с вопросами. Вопросы были разные. Но главный вопрос меня добил. Вот он: "Скажите пожалуйста, где можно взять предыдущие выпуски рассылки?"

Ну нельзя же так! Давайте установим правило: сперва вы пытаетесь решить вопрос сами, а уж потом просите о помощи. Ну подумайте: рассылка распространяется через Subscribe.Ru, так зайдите на него и хорошенько осмотритесь вокруг. И вы сразу найдете лежащий там архив рассылки. Только хочу вам порекомендовать выпуски с 1-го по 4-й читать в текстовом варианте - когда я их писал, я еще не разобрался с конвертацией в HTML, в результате чего HTML-версия оказалось несколько подпорченной. Особенно это видно в 4-м выпуске.

Еще один вопрос был такой: как подписаться, не имея полноценного доступа к Интернету, а только к e-mail? Отвечаю: напишите письмо по адресу subscribe@subscribe.ru, содержащее единственную строку HELP, и ждите ответа.

И еще просьба не присылать мне сообщений не по теме, как то "как подписаться на рассылку", "где взять архив рассылки", "где скачать C++", и т.д. Я просто физически не могу отвечать на все письма такого содержания. Еще просьба указывать в поле "Subject" тему письма, а не "вопрос", "помогите" , "?????", и т.д. Этим вы сильно упростите процедуру разбора корреспонденции, следовательно, быстрее получите ответ. Да, не пугайтесь, если я вам не ответил: быть может, я решил ответить в рассылке, а для этого необходимо дождаться ее очередного выпуска.

Итак, решения домашних заданий (если у кого нет условий - ищите в архивах). Тем, кто их сделал, все же рекомендую посмотреть, как их сделал я. Тем, кто не сделал: посмотрите на них, поймите, а после этого закройте и, больше не смотря на них, сделайте все сами! Тогда все поймете. Да, я решил изменить нумерацию. Теперь номера задач будут состоять из номера выпуска рассылки и номера задачи в выпуске, разделенных точкой. Этого обозначения я буду придерживаться и здесь.

4.2. a = 2, f = 10, i = 1. Остальные переменные - без изменений.

Если с первым присваиванием все еще кое-как ясно (обратите внимание: a меняется!), то со вторым у многих возникли вопросы. Что ж, разбираем детально.

Для начала расставим скобки, чтобы обозначить порядок операций: i = ((3 < 2) < 1);. 3 больше чем 2, следовательно 3 < 2 - ложно, т.е. равно нулю (напомню, что в С ложь - это 0, истина - все остальное). А теперь этот нуль сравнивается с единицей. Т.к. 0 < 1, то (0 < 1) = 1. Эта единица и присваивается переменной i.

4.3. Привожу полностью исходный текст программы:
 #include <stdio.h>
 #include <math.h>

 int main (void)
 {
  float a, b, c, d, x1, x2;

  a = 1;
  b = -1;
  c = -6;

  d = b * b - 4 * a * c;

  x1 = (-b + sqrt (d)) / (2 * a);
  x2 = (-b - sqrt (d)) / (2 * a);

  printf ("%f\n%f\n", x1, x2);
  return 0;
 }
В комментариях, я думаю, не нуждается. Единственное замечание - это строка "%f" в параметрах функции printf. Если на место %d подставляется целое число, то на место %f будет подставлено дробное (float или double).

5.1. Опять текст программы:
 #include <stdio.h>
 #include <math.h>

 int main (void)
 {
  float a, b, c, d, x1, x2;

  a = 0;
  b = 0;
  c = 2;

  if (!a)
   if (!b)
    if (!c)
     printf ("x - любое число\n");
    else
     printf ("Решений нет.\n");
   else
   {
    x1 = -c / b;

    printf ("%f\n", x1);
   }
  else
  {
   d = b * b - 4 * a * c;

   if (d < 0)
    printf ("Действительных решений нет.\n");
   else
   {
    x1 = (-b + sqrt (d)) / (2 * a);

    if (!d)
     printf ("x = %f\n", x1);
    else
    {
     x2 = (-b - sqrt (d)) / (2 * a);

     printf ("x1 = %f\nx2 = %f\n", x1, x2);
    }
   }
  }

  return 0;
 }
Опять, я думаю, все понятно. Единственное, на что стоит обратить внимание - это на конструкции типа if (!d). Как я уже говорил, в С истина - все, что не нуль, поэтому эта конструкция эквивалентна конструкции if (d == 0).

5.2. Снова текст (на этот раз только функции):
 int triangle (int a, int b, int c)
 {
  int t;

  /* Поменяем стороны местами так, чтобы c была наибольшей */
  if (a > c)
  {
   t = a;
   a = c;
   c = t;
  }

  if (b > c)
  {
   t = b;
   b = c;
   c = t;
  }

  if (c >= a + b)
   return 0;

  if (c*c < a*a + b*b)
   return 1;

  return 2;
 }
Думаю, в пояснениях не нуждается (конечно, если вы еще не забыли геометрию).

6.1. И снова текст:
 #include <stdio.h>

 int main (void)
 {
  double c = 1, s = 1;
  int i = 0;

  do
   s += 1 / (c *= ++i);
  while (c < 10000);

  printf ("%f\n", s);

  return 0;
 }
Я надеюсь, что вы уже оценили краткость всей программы. Все же приведу некоторые пояснения по части выделенного красным цветом выражения. Итак, в переменной c у нас находится факториал числа i, в переменной s - сумма ряда. На каждом шаге переменная i увеличивается на 1 (++i), вычисляется ее факториал (с *= ++i, напомню, что n! = n * (n-1)!), и величина, обратная этому факториалу, добавляется к переменной s. Так делается, пока 1/c > 0.0001, то есть пока c < 10000.

6.2. Я думаю, все уже ее запустили и посмотрели :-) И все же:
 36
 18
 9
 4
 2
 1
Что делает эта программа? Она печатает серию чисел, первое из которых - 36, а каждое последующее вдвое меньше предыдущего (с точностью до округления). После того, как напечатается единица, i примет значение, равное 0 (0.5, округленное до целого), и цикл прекратится (напомню, что 0 - это ложь).

6.3. Вообще-то я тут ошибся с условием. Но ничего не поделаешь, придется решать то, что написал :-)
 #include <stdio.h>

 int main (void)
 {
  int i, j;

  for (i = 0; i < 6; i++)
  {
   for (j = 0; j < (((i < 2) ? 7 : 6) - i); j++)
    printf ("$");
   printf ("\n");
  }

  return 0;
 }
Внимательно присмотритесь к выделенному красным цветом выражению. Если вы еще раз прочтете условие, то заметите, что во второй строчке должно быть шесть знаков, а в третьей - уже четыре. Поэтому в условие введен добавочный оператор (i < 2) ? 7 : 6, который, как вы помните, возвратит 7, если i < 2, и 6 в противном случае. Этим достигнется указанный эффект - из треугольника как бы выбросится одна строка.

7.1. Текст функции:
 void exchange (int *a, int *b)
 {
  int *t, c, d;

  if (*a < *b)
  {
   t = a;
   a = b;
   b = t;
  }

  c = *a;
  d = *b;

  *a = (c + d) / 2;
  *b = (c - d) / 2;

  return;
 }
А вот тут придется разбираться. Сперва обратите внимание на условие и блок за ним. В нем мы переставляем переменные так, чтобы a содержало большее из двух переменных. Но обратите внимание: мы меняем на значения, а адреса. Значения переменных a и b в вызывающей функции пока что остались без изменений, но a теперь указывает на большую переменную, а b - на меньшую. А после этого мы с чистой совестью производим требуемую замену, не забыв сохранить начальные значения переменных - иначе мы перезапишем a новым значением и не сможем вычислить правильное значение b.

7.2. Снова текст:
 void PrintFunc (int (*f)(int x))
 {
  int i;

  for (i = 0; i <= 20; i++)
   printf ("%d %d\n", i, (*f)(i));

  return;
 }
По-моему, тут все понятно.

8.1. Текст функции:
 int Search4max (int d[], int Count)
 {
  int i, m = d [0];

  for (i = 1; i < Count; i++)
   if (m < d [i])
    m = d [i];

  return m;
 }
8.2. Текст функции:
 int Search4max (int d[4][4][4])
 {
  int i, j, k, m = d [0][0][0];

  for (i = 0; i < 4; i++)
   for (j = 0; j < 4; j++)
    for (k = 0; k < 4; k++)
     if (m < d [i][j][k])
      m = d [i][j][k];

  return m;
 }
По-моему, в этих двух задачах тоже все понятно.

Ну, вроде все. До встречи!

Ведущий рассылки, av

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться Relayed by Corbina
Рейтингуется SpyLog

В избранное