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

Билет 13

1. Побитовые логические операции

Побитовые логические операции

& ! ^ ~ >> <<

применяются к целым, то есть к объектам типа char, short, int, long и их unsigned аналогам, результаты тоже це­лые.

Одно из стандартных применений побитовых логических опе­раций - реализация маленького множества (вектор битов). В этом случае каждый бит беззнакового целого представляет один член множества, а число членов ограничено числом битов. Би­нарная операция & интерпретируется как пересечение, ! как объединение, а ^ как разность. Для наименования членов такого множества можно использовать перечисление. Вот маленький при­мер, заимствованный из реализации (не пользовательского ин­терфейса) <stream.h>:

enum state_value (* _good=0, _eof=1, _fail=2, _bad=4 *);

// хорошо, конец файла, ошибка, плохо

Определение _good не является необходимым. Я просто хо­тел, чтобы состояние, когда все в порядке, имело подходящее имя. Состояние потока можно установить заново следующим обра­зом:

cout.state = _good;

Например, так можно проверить, не был ли испорчен поток или допущена операционная ошибка:

if (cout.state&(_bad!_fail)) // не good

Еще одни скобки необходимы, поскольку & имеет более вы­сокий приоритет, чем !.

Функция, достигающая конца ввода, может сообщать об этом так:

cin.state != _eof;

Операция != используется потому, что поток уже может быть испорчен (то есть, state==_bad), поэтому

cin.state = _eof;

очистило бы этот признак. Различие двух потоков можно находить так:

state_value diff = cin.state^cout.state;

В случае типа stream_state (состояние потока) такая раз­ность не очень нужна, но для других похожих типов она оказы­вается самой полезной. Например, при сравнении вектора бит, представляющего множество прерываний, которые обрабатываются, с другим, представляющим прерывания, ждущие обработки.

Следует заметить, что использование полей (#2.5.1) в действительности является сокращенной записью сдвига и маски­рования для извлечения полей бит из слова. Это, конечно, мож­но сделать и с помощью побитовых логических операций, Напри­мер, извлечь средние 16 бит из 32-битового int можно следующим образом:

unsigned short middle(int a) (* return (a>>8)&0xffff; *)

Не путайте побитовые логические операции с логическими операциями:

&& !! !

Последние возвращают 0 или 1, и они главным образом ис­пользуются для записи проверки в операторах if, while или for (#3.3.1). Например, !0 (не ноль) есть значение 1, тогда как ~ 0 (дополнение нуля) есть набор битов все-единицы, который обычно является значением -1.

2. Функция scanf

Обращение к этой функции имеет вид:

scanf (Управляющая_строка,&Имя1,&Имя2,...,&ИмяN);,

где: 1) Имя1,Имя2,...,ИмяN - это имена переменных, значения которых надо ввести. Смысл символа "&" перед именем будет раскрыт ниже; 2) Управляющая_строка - это строка символов, которая задает количество и типы вводимых переменных. Делается это так: в формате указывается символ %, за которым следует буква, определяющая тип вводимой переменной.

    Сочетание %буква является спецификацией преобразования. При вводе мы будем пользоваться следующими спецификациями:

  • %d - ввести целое число;

  • %c - ввести один символ;

  • %s - ввести строку символов.

    Спецификации преобразования должны соответствовать количеству и типу вводимых переменных.

    К счастью, при применении функции scanf() мы ничего не должны знать о смысле символа "&". Необходимо запомнить только два правила.

  1. Если нужно ввести некоторое значение и присвоить его переменной одного из основных типов, то перед именем переменной требуется писать символ &.

  2. Если требуется ввести значение строковой переменной, то использовать символ & не нужно.

    Функция scanf() использует некоторые специальные знаки (пробелы, символы табуляции и символ "новая строка") для разбиения входных символов на отдельные поля. Она согласует последовательность спецификаций преобразования с последовательностью полей, опуская упомянутые специальные знаки между ними.

    При обращении к функции scanf() выполнение программы приостанавливается, и нужно ввести значения для указанных переменных, после чего работа программы продолжается.

    Пример 1.

#include<stdio.h>

main ()

{

int a,b,c,d,e;

/* При вводе каждое число должно */

/* отделяться от другого пробелом */

scanf ("\n %d%d%d%d%d",&a,&b,&c,&d,&e);

printf ("\n %d %d %d %d %d",a,b,c,d,e);

}

Управляющая строка может содержать:

  • пробелы ' ', символы табуляции '\t' и перевода строки '\n', которые просто игнорируются;

  • обычные символы (кроме символа "%"), которые предполагаются совпадающими с очередными (отличными от символов, перечисленных в предыдущем пункте) символами входного потока;

  • спецификации преобразования, состоящие из

    • %,

    • необязательного символа "подавления" присваивания "*",

    • необязательного числа, задающего максимальную ширину поля и

    • символа преобразования.

    Спецификация преобразования управляет преобразованием очередного входного поля. Результат обычно помещается в переменную, на которую ссылается соответствующий параметр. Однако, если присутствует символ "*", то входное поле просто пропускается, и никакого присваивания не производится.

    Перечислим основные символы преобразования:

  • d - десятичное число;

  • x - шестнадцатеричное число;

  • o - восьмеричное число;

  • c - символ;

  • s - строка символов.

Соседние файлы в папке Програмки на C++