1. Пусть b1, b2, b3 — переменные логического типа. Записать оператор if и операторы присваивания, которые выполняют те же действия, что и оператор
 b1= b2 || b3.
 Решение: if (b2) b1=true; else b1=b3;
 2. Нарисовать область плоскости, в которой и только в которой для вещественных величин x и y следующее логическое выражение истинно:
 а) (fabs(x) < 1) > (fabs(y) < 1);
 б) ! (fabs(x) < 1 ) = = (fabs(y) < 1);
 в) ! (( fabs(x) < 1 ) = = (fabs(y) < 1)).
 Указания к решению. Для величин логического типа следующие выражения истинны: true > false, true = = true, false = = false, 
 ! true = = false, true = = ! false.
 a) Надо найти область плоскости, в которой и только в которой одновременно первое неравенство истинно, а второе ложно, т. е. такие точки, для которых выражение (fabs(x)<1) && (fabs(y)>=1) истинно.
 б) !(fabs(x) < 1) равносильно неравенству (fabs(x) >= 1). Поэтому надо найти область плоскости, в которой и только в которой выражение (fabs(x)>=1) &&( fabs(y)<1) ||( fabs(x)<1) &&( fabs(y)>=1) истинно.
 в) Сначала определяем область, в которой и только в которой выражение (fabs(x)<1) && ( fabs(y)<1) ||( fabs(x)>=1) && (fabs(y)>=1) истиннo. Это был бы ответ, если бы не было операции отрицания. Операция отрицания в качестве ответа оставит точки, не вошедшие в эту область.
 3. Записать следующее логическое выражение, используя операции логического умножения и сложения (&& , || ) и не используя сравнение логических величин:
 а) (y>x) = = (x>0);
 б) (y > x) > !(x > 0). 
 Решение: a) (y > x) && ( x> 0) || (y <= x) && (x <= 0);
 б) y>x && x>0.
 4. Не используя логических операций, записать выражение, принимающее значение true тогда и только тогда, когда точка плоскости с координатами (x, y) принадлежит первой четверти, включая и оси координат, или третьей четверти, не включая оси координат.
 Решение: (x>=0) = = (y>=0).
 5. Пусть bool b1, b2, b3, b4; Записать оператор if и операторы присваивания, которые выполняют те же действия, что и следующий оператор:
 а) b1= b2 && b3;
 б) b1=b2 || b3 && b4;
 в) b1=(b2 || b3) && b4;
 г) b1= !(b2 && b3 || b4).
 6. Записать с помощью логических операций и оператора присваивания,не используя оператор if:
 bool b1, b2, b3,r;
 if (!b1) r=false;
  else if (!b2) r=false;
  else r=b3;
 7. Объяснить работу следующей программы:
 float x,y; bool lg; cin>>x>>y;
 while (!(x==100 && y==100))
 { lg=x>0; cout<<"x>0 "<<lg<<" y>0 "<<(y>0)<<" "<<(lg > (y>0));
  if (lg > (y>0)) cout<<" YES ";
  else cout<<" NO";
  cin>>x>>y;
  }
 8. Записать следующее логическое выражение, используя логические операции и не используя сравнение логических величин:
 a) !((y > x) > (x>0)); 
 б) (y > x) != (x > 0) ;
 в) ! (y > x) > (x > 0).
 Нарисовать область плоскости, в которой и только в которой записанное логическое выражение истинно.
 9. Записать логическое выражениес помощью сравнения логических величин, не используя операций && и ||:
 а) x*x+y*y > 1 && y <= x;
 б) x*x+y* y> 1 && y <= x || x*x+y*y <= 1 && y > x;
 в) x>0 && y > 0 || x <= 0 && y <= 0.
 Нарисовать область плоскости, в которой и только в которой записанное логическое выражение истинно.
 10. Пусть B1= x*x – y*y < 4; B2= y>0; 
 а) Записать логическое выражение B1 && B2, используя сравнение булевских величин и не используя логических операций.
 б) Записать выражение B1<B2, не используя сравнение булевских величин.
 11. Нарисовать область плоскости, в которой и только в которой для вещественных x и y следующее логическое выражение истинно:
 а) (fabs(x) > 1) > (fabs(y)> 1);
 б) ! (fabs(x) > 1 ) = = (fabs(y)> 1);
 в) ! (( fabs(x) > 1 ) = = (fabs(y) > 1)).
 12. Операторы
  int x=8, y=4;
  cout <<(x&y)<<", "<<(x&&y)<<", "<<(x|y)<<", "<<(x||y)
  <<", "<<(y<x<1)<<", "<<(x<y<1)<<endl;
 выведут 0, 1, 12, 1, 0, 1. Объяснить результат.
 13. Объяснить выполнение printf("%c %d %c %d\n", a, a, b, b); Результат, как и раньше, зависит от объявления и от введенных величин.
 Вариант 1. Переменные объявлены int a, b; и вводим два числа — 97 и 120. Тогда будет выведено a 97 x 120, т. е. по формату %c выводятся символы, коды которых хранятся в переменных a и b, а по формату %d — эти целые числа, которые интерпретируются как коды символов.
 Вариант 2. Этот же результат получим, если объявим char a, b; и введём два символа — a и x.
 14. Что будет выведено и почему:
 а) char ch; cin>>ch; cout<< (ch*2); если введём 1? d?:
 б) char CH=1; cout<<” “<<(CH*2);
 в) char ch2=’1’; cout<<” “<<(ch2*2);
 г) printf (“ \n %c %d %c %d %c %d”, ch, ch, CH, CH, ch2, ch2);
 Объявление и инициализация такие, как в а), б), в). 
 д) int ci; cin>>ci; printf(“\n %c %d”, ci,ci); если введём 40?
 Глава 5
 МАТРИЦЫ (ДВУХМЕРНЫЕ МАССИВЫ)
 § 1. Объявление, способы определения
 Матрица объявляется, например, следующим образом:
 const n=3, m=5; int A[n][m],
 где n — количество строк (первая, левая размерность), m —количество столбцов или количество элементов в строке (вторая, правая размерность). Матрица располагается в оперативной памяти по строкам и занимает непрерывный участок, объём которой равен n*m*sizeof(int), где int — тип элементов матрицы.
 Тот или иной способ определения матрицы применяется в зависимости от специфики конкретной задачи.
 Матрицу можно инициализировать при объявлении:
  int A[n][m]= {{1, -2, 3, -4, 5},
  { 10, 20, 33, -40},
  {-11, 22, 300, 400, 500}};
 Если в строке указано меньше элементов, чем требуется, то остальные инициализируются нулями. У нас во второй строке с номером 1 (нумерация и строк, и столбцов начинается с нуля) последний элемент будет нулевым.
 Ввод матрицы используется, если для тестирования программы принципиально важно, какие значения элементов матрицы введены, а другие способы её задания неприемлемы. Например, некоторые строки (но не все) не должны содержать нулей. Очевидным недостатком этого способа является трудоёмкость ввода и необходимость его повторения при отладке программы. Простейший ввод можно выполнить следующим образом:
 for ( i=0; i<n; i++)
  for ( j=0; j<m; j++)
  cin>>A[i][j];
 Но в этом варианте в каждой строке набираем одно число, и не видно, элемент с каким номером вводим. Желательно, чтобы вводимые элементы матрицы на экране располагались так, как в математической записи, то есть элементы строки матрицы должны вводиться из одной строки экрана. Это можно выполнить, например, следующим образом:
 for ( y=wherey(), i=0; i<n; i++, y++)
  { gotoxy(1, y); cout<<"i="<<i;
  for (x=5, j=0; j<m; j++, x+=5)
  { gotoxy(x,y);
  cin>>A[i][j];
  } } 
 Для экономии времени, затрачиваемого на ввод матрицы, для некоторых задач её элементы можно определить с помощью датчика случайных чисел (см. 6.2 гл. 1):
 Randomize();
 for ( i=0; i<n; i++)
  for ( j=0; j<m; j++)
  A[i][j]=random(100);
 Если по условию задачи требуется, чтобы числа матрицы принадлежали интервалу [r1, r2), где r2>r1, то в цикле следует записать A[i][j]=random(r2-r1)+r1; Этот метод можно использовать при отладке программы, если на элементы матрицы нет ограничений.
 Элементы матрицы можно задать также по некоторому специальному правилу, например:
 for ( i=0; i<n; i++)
  for ( j=0; j<m; j++)
  A[i][j]=(i+1)*(j+1);
 Сформированную так матрицу для некоторых задач легче анализировать.
 Преимущество последних двух способов в том, что во время отладки программмы не нужно тратить время на неоднократный ввод элементов матрицы или записывать их в тексте программы при объявлении. При этом матрицу надо обязательно выводить на экран, чтобы можно было проверить полученный результат.
 § 2. Вывод матриц
 Простой вывод можно выполнить, используя управление курсором. Для этого в программе ввода (§ 1) достаточно заменить cin на cout. 
 Кроме этого можно предложить следующий вариант вывода: 
  cout<<endl;
  for ( i=0; i<n; i++)
  { printf("\n"); // Переход на новую строку экрана.
  for ( j=0; j<m; j++)
  printf ("%5d", A[i][j]);
  }
 При таком выводе числа столбцов будут выровнены благодаря наличию формата %5d, т. е. независимо от размерности чисел они будут выводиться друг под другом. Напомним, что для вещественных чисел необходимо указать, например, формат %7.2f. В этом фрагменте важно место оператора printf("\n"). Если символ “\n” записать во внутреннем цикле (printf ("\n%5d", A[i][j])), то в каждой строке экрана будет выводиться по одному числу. Необходимо также обратить внимание на расстановку фигурных скобок.
 Иногда для наглядности целесообразно элементы матрицы в зависимости от условия выводить разным цветом. Например, положительные числа вывести цветом C1 на фоне C2, а отрицательные и нулевые — наоборот, цветом С2 на фоне С1, где С1 и С2 — целые числа, определяющие цвет. Это реализуется, например, следующим образом:
 void MyColors (int C1, int C2)
  { textcolor(C1);
  textbackground(C2); }
 int main()
 { textbackground(3); clrscr(); // Очищает и закрашивает экран
  const n=4,m=6; float A[n][m];
  // Пример формирования вещественной матрицы 
  // случайным образом 
  randomize(); 
  for ( int i=0; i<n; i++)
  for ( int j=0; j<m; j++)
  A[i][j]=(random(50)-40)/100. + random(5); 
  for ( int i=0; i<n; i++)
  { cout<<endl; // Переход на новую строку экрана.
  for ( int j=0; j<m; j++)
  { if (A[i][j]>0) MyColors(2,15); // Изменение цветов
  else MyColors(15,2);
  cprintf ("%7.2f", A[i][j]);
  }
  } getch(); return 0;
 }
 Замечания.
 Напомним, что стандартные функции textcolor и textbackground устанавливают только цвет выводимых символов и цвет фона в текстовом режиме, но ничего не выводят. Для “цветного” вывода вместо printf или cout необходимо использовать функцию cprintf.
 Предполагается, что размерности матрицы такие, что её строка размещается в одной строке экрана. Кроме того, вся матрица размещается на экране. В противном случае надо усложнить предложенный фрагмент программы.
 
 Для удобства анализа результатов часто требуется одновременно выводить несколько матриц, матрицу и вектор и т. п. При этом они должны располагаться в определённом порядке и в заданном месте экрана.
 Например, слева выведем матрицу A[n][m] цветом С1, далее, правее — одномерный массив B[n] в столбец по одному элементу цветом С2 и, наконец, ещё правее — матрицу D[n][k] цветом C3 в обратном порядке, т. е. сначала (n–1)–ю строку, затем (n–2)–ю и так далее, 0–ю строку.
 void MyC(int C)
  {textcolor(C); }
  int main()
 { textbackground(1); clrscr();
  const n=4, m=6, k=5; int D[n][k], A[n][m];
  float b[n]; randomize();
  for ( int i=0; i<n; i++)
  { b[i]=(float)random(m+k)/10;
  // или b[i]=random(m+k)/10.; 
  // можно по-другому правилу b[i]=(float)i / 10;
  for ( int j=0; j<m; j++)
  { A[i][j]= random(50)-100; // Все элементы отрицательные
  D[i][j]= random(500)+200; // Все элементы положительные
  }
  }
  MyC(10); cprintf(" Matrix A ");
  MyC(11); cprintf(" Vector b");
  MyC(15); cprintf(" Matrix D\n");
  for ( int i=0; i<n; i++)
  { cout<<endl;
  MyC(10);
  for ( int j=0; j<m; j++) // Вывод i–й строки матрицы A
  cprintf ("%4d", A[i][j]);
  MyC(11);
  // Вывод одного i–го элемента вектора b
  cprintf (" %6.1f ", b[i]); 
  MyC(15); // Вывод i–й строки матрицы D в обратном порядке
  for ( int j=0; j<k; j++) 
  cprintf ("%5d", D[n-1-i][j]);
  }
  getch(); return 0;
 }
 Замечание. Предполагается, что размерности матриц и вектора такие, что в одной строке экрана размещаются две строки из A и D и один элемент b. Кроме того, все три массива могут поместиться на экране. В противном случае требуется усложнение вывода.
 Упражнение. Написать второй вариант этой же программы, в которой используется функция gotoxy. Сначала выводим всю матрицу A, затем возвращаемся на первую строку и выводим в столбец вектор b и, наконец, в обратном порядке выводим матрицу D.