- •1 Структурная схема эвм. Основные функциональные устройства машины.
- •2. Определение алгоритма. Свойства алгоритмов.
- •Алфавит
- •Функция стандартного вывода printf()
- •Функция стандартного ввода scanf()
- •Формат оператора switch:
- •Обработка одномерных массивов
- •Void swap(int & a, int & b)
- •Void swap(int * a, int * b)
- •33. Критерии качества программ
Void swap(int & a, int & b)
Амперсанды перед именем переменной означают, что эта переменная является не локальной переменной, а ссылкой на переменную, указанную в качестве параметра при вызове функции. Теперь при вызове swap(p,q) переменные a и b являются синонимами для переменных p и q, и изменение их значений влечет изменение значений p и q. А вот вызывать функцию в виде swap(3,5) уже нельзя, поскольку 3 и 5 — это константы, и сделать переменные синонимами констант нельзя.
Однако в языке C (не C++) вообще не было такого понятия, как передача параметров по ссылке. Для того, чтобы реализовать функцию, аналогичную swap в рассмотренном примере, необходимо было передавать адреса переменных p и q, а сама функция при этом должна быть объявлена, как
Void swap(int * a, int * b)
Поскольку в этом случае функция swap знает физические адреса в оперативной памяти переменных p и q, то разыменовав эти адреса функция swap сможет изменить значения самих переменных p и q.
Теперь вспомним, что в C++ массивы и указатели — это почти одно и то же. А поскольку передача массива по значению, то есть создание копии всего массива является трудоемкой операцией (особенно для больших массивов), то вместо массива всегда передается указатель на его начало. То есть два объявления функции void f(int A[10]) и void f(int * A) абсолютно идентичны. В любом случае функция f получит указатель на начало массива, а, значит, будет способна изменять значения его элементов.
27. Строки символов в языке программирования с++.
Символьные строки представляют один из наиболее полезных и важных типов данных. В языке С++ символьная строка является символьным массивом, который заканчивается нуль-символом (\0). Если строка должна содержать N символов, то в описании нужно указать N+1 элемент.
Для работы со строками существует специальная библиотека, описание которой находится в файле string.h. Рассмотрим наиболее часто используемые функции из этой библиотеки.
strlen (s) - определяет длину строки (без нуль-символа). s – указатель на строку символов. strcat (s1, s2) – объединяет две с троки. s1, s2 – указатели на строку символов. Копия второй строки присоединяется к концу первой, и это объединение становится новой первой строкой. Строка s2 остается без изменения, а s1должна быть достаточно большой, чтобы разместить две строки. strcmp (s1, s2) – сравнивает содержимое двух строк. s1, s2- указатели на строку символов. Эта функция возвращает 0, если строки одинаковые. Если строки разные, то функция возвращает разницу в кодах у первой пары несовпадающих символов. strcpy (s1, s2) – копирова ние строки: строка, на которую указывает второй аргумент, копируется в строку, на которую указывает первый. strchr (s, c) – ищет в строке s первое вхождение символа с и возвращает указатель на этот символ, если не обнаружит, то возвращает NULL. strstr (s1, s2) – ищет в строке s1 первое вхождение подстроки s2 и возвращает указатель на найденную подстроку, если не обнаружит, то возвращает NULL.
28. Стpуктуpы и объединения в языке программирования с++.
Структуры и объединения.
Синтаксис структур. Структуры в языке С аналогичны массиву тесно связанных атрибутов. Однако, в отличие от массива, структура позволяет иметь смешанные атрибуты различных типов данных. Структура создается при помощи ключевого слова struct, за которым следует имя_типа (имя структуры) и список элементов. Описание структуры заканчивается точкой с запятой, т.к. оно является оператором:
struct имя_типа { тип_элемента1 имя_элемента1; тип_элемента2 имя_элемента2; тип_элемента3 имя_элемента3; … };
Пример описания структуры:
struct stboat { char type[16]; // тип char model[16]; // модель char title[20]; // имя int year; // год выпуска double price; // цена };
Эта структура описывает новый тип данных stboat и содержит три текстовых поля, одно целое и одно действительное. С описанной структурой не связывается никакая переменная. Для создания новой переменной используется оператор (слово struct является необязательным):
struct имя_структуры имя-переменной;
Для вышеприведенного примера можно создать переменную used_boat:
struct sboat used_boat;
Если со структурой связывается только одна переменная, то ее можно объявить непосредственно в описании структуры перед точкой с запятой. Имя_типа в этом случае можно опустить:
struct { char type[16]; // тип char model[16]; // модель char title[20]; // имя int year; // год выпуска double price; // цена } used_boat;
Доступ к элементам структуры. Для обращения к отдельным элементам структуры используется операция обращения к члену структуры – “точка”. Она разделяет имя структурной переменной и имя поля, например
used_boat.year=1955; printf(“%lf”,used_boat_price);
Элементы структуры обрабатываются также, как и любые другие переменные С, необходимо только использовать операцию “точка”. Можно создавать массивы структур и указатели на структуру, для обращения к элементам структуры предусмотрен оператор “->” (стрелка, он состоит из знаков минус и больше).
sboat boat_array[10]; boat_array[3].year=1980; sboat *pboat; pboat=&used_boat; pboat->price=12570.25;
Передача структур в функции. В функцию информация о структуре может передаваться как по значению, так и по ссылке. В первом случае в функцию передается копия структуры, что может снизить эффективность программы. При передаче по ссылке копирование не выполняется, однако функция получает доступ к элементам структуры и может их изменять. Можно также использовать указатели на структуру. Структуры и битовые поля. В языке С имеется возможность доступа к отдельным разрядам в более крупном типе данных, например в байте. Это полезно, например для изменения масок, установки флагов и т.д. В этом случае описание структуры выглядит следующим образом:
struct имя_типа { тип_элемента1
имя_поля1:колич_бит1,
имя_поля2:колич_бит2, имя_поля3:колич_бит3, …; тип_элемента2 … };
В таких структурах можно использовать только целочисленные типы:
struct keybits { unsigned char shift :1, ctrl :1, scrool:1, lock :1; };
Объединения. Объединения – еще один тип данных, которые можно использовать различным образом. К примеру, некоторые данные в одном случае могут рассматриваться как целые, а в другом – как числа с плавающей точкой. По виду объединения напоминают структуры. Объединение тоже содержит несколько типов данных, однако эти данные занимают одну и ту же область памяти. Объединение создается при помощи ключевого слова union:
union имя_типа { тип_элемента1 имя_элемента1; тип_элемента2 имя_элемента2; тип_элемента3 имя_элемента3; … };
К членам объединения можно обращаться так же, как и к членам структур, либо через операцию “точка”, либо через операцию “->” – для указателей:
union many_types ( char c[4]; int ivalue[2]; float fvalue; } type1; type1.fvalue=1.5; printf(“%i %i”,type1.ivalue[0],type1.ivalue[1]);
Дополнительные средства (typedef и enum). При помощи оператора typedef можно связать новые типы данных с существующими:
typedef double real;
После такого описания можно использовать real вместо double. Использовать typedef необходимо с осторожностью. Слишком много новых типов могут ухудшить читаемость программы. Перечисляемый тип данных enum позволяет определить список последовательных целых чисел, каждое из которых имеет собственное имя. Объявление перечисляемого типа выглядит следующим образом:
enum имя_типа {имя1=знач1, имя2=знач2, имя3=знач3, …}переменная;
Здесь имя1, имя2,… – это имена констант. Им можно присваивать целочисленные значения. Если значения отсутствуют, то предполагается, что они последовательно увеличиваются на единицу, начинаясь с нуля. Память под эти константы во время выполнения не выделяется, поэтому удобно использовать этот оператор для создания констант, если не указывать имя_типа и переменную:
enum (с28=28, с29,с30,c31);
Тип enum часто используется, когда информацию можно представить списком целых значений, подобно номерам дней недели или месяцев в году:
enum months
{Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec}
current_month;
current_month=Dec; //используется константа 12 int diff=(int)current_month-2; //тип enum автоматически не преобразуется в int
Поскольку имена эквивалентны последовательным целым значениям, то с ними можно выполнять арифметические операции. Фактически в данном примере переменной current_month присваивается целочисленное значение 12.
29. Битовые поля в языке программирования с++.
Элементом структуры может быть битовое поле, обеспечивающее доступ к отдельным битам памяти. Вне структур битовые поля объявлять нельзя. Нельзя также организовывать массивы битовых полей и нельзя применять к полям операцию определения адреса. В общем случае тип структуры с битовым полем задается в следующем виде:
struct { unsigned идентификатор 1 : длина-поля 1;
unsigned идентификатор 2 : длина-поля 2; }
длинна - поля задается целым выражением или константой. Эта константа определяет число битов, отведенное соответствующему полю. Поле нулевой длинны обозначает выравнивание на границу следующего слова.
Пример:
struct { unsigned a1 : 1;
unsigned a2 : 2;
unsigned a3 : 5;
unsigned a4 : 2; } prim;
Структуры битовых полей могут содержать и знаковые компоненты. Такие компоненты автоматически размещаются на соответствующих границах слов, при этом некоторые биты слов могут оставаться неиспользованными.
Ссылки на поле битов выполняются точно так же, как и компоненты общих структур. Само же битовое поле рассматривается как целое число, максимальное значение которого определяется длиной поля.
В отличие от других языков программирования язык Си обеспечивает доступ к одному или нескольким битам в байте или слове. Внутри структур и объединений могут в качестве их компонентов использоваться битовые поля. Каждое битовое поле представляет целое или беззнаковое целое значение, занимающее в памяти фиксированное число битов (от 1 до 16). Битовые поля могут быть только элементами структур, объединений и классов, т. е. они не могут быть самостоятельными объектами программ. Битовые поля не имеют адресов, нет указателей и ссылок на битовые поля. Они не могут объединять-ся в массивы. Назначение битовых полей обеспечить удобный доступ к от-дельным битам данных. Чаще всего битовые поля используют при работе с флажками, которые могут принимать только два значения, что позволяет экономить память.
Синтаксис описания структуры с битовыми полями следующий: struct <имя>{ <тип поля> имя поля1: длина в битах; <тип поля> имяполя2: длина в битах; <тип поля> имяполяN: длина в битах; }
Имя поля может быть пропущено, тогда соответствующее количество байтов не используется (пропускается). Обычно эта возможность использу-ется для изменения порядка размещения битовых полей, выравнивая их по границам слов: struct w{ int a:9; int :7; int b:9; };
30. Классы памяти. Область действия имен в языке программирования с++.
В языке C все переменные и функции должны быть объявлены до их использования. Объявление переменной устанавливает соответствие имени и атрибутов переменной, вызывает выделение памяти для хранения ее значения. Место размещения переменной в памяти программы задается с помощью класса памяти (класса хранения) переменной. В зависимости от места размещения переменной в памяти определяется время жизни и область видимости переменной. Класс памяти задается спецификатором класса памяти.
В языке C имеется 4 класса памяти:
- extern (внешние переменные);
- auto (автоматические переменные);
- register (регистровые переменные);
- static (статические переменные);
Класс памяти
Класс памяти определяет:
место размещения переменной (ОП или регистры)
область действия имени (идентификатора), связанного с переменной
видимость объекта
время существования
тип компоновки (связывания)
Явно задать класс памяти можно с помощью спецификаторов: auto, register, static, extern.
Область действия (ОД) имени
ОД – это часть программы, в которой можно обращаться к данному имени (сфера действия имени в программе).
Рассмотрим все случаи:
Имя определено в блоке (локальные переменные): ОД - от точки определения до конца блока;
Формальные параметры в определении функции (форм. пар. - это локальные переменные функции) : ОД параметров – блок тела функции;
Метки операторов: ОД – функция;
Глобальные объекты: ОД - вся программа от точки их определения или от точки их описания;
Формальные параметры в прототипе функции: ОД- прототип.
31. Текстовые файлы в языке программирования с++. Под файлом понимается именованная область внешней памяти или логическое устройство потенциальный источник или приемник информации [10]. Основное отличие внешней памяти ЭВМ от оперативной памяти ? возможность сохранения информации при отключении ЭВМ. Информация сохраняется в виде файлов, доступ к которым поддерживает операционная система ЭВМ. Поддержка операционной системы состоит в том, что в ней имеются средства:
создания файлов; уничтожения файлов; поиска файлов на внешнем носителе; чтения и записи из файлов и в файлы; открытия файлов; закрытия файлов; позиционирования файлов.
Любой сколько-нибудь развитый язык программирования должен содержать средства для организации хранения информации на внешних запоминающих устройствах и доступа к этой информации. Язык С++ не лишен таких возможностей.
Любой файл в С++ имеет три характерные особенности:
у файла есть имя, это дает возможность работать с несколькими файлами одновременно;
содержит компоненты одного типа (типом может быть любой тип, кроме файлового);
длина вновь создаваемого файла никак не ограничена при объявлении и ограничивается лишь емкостью внешних устройств памяти.
Обращение к файлу производится через указатель на файл, который необходимо описать следующим образом:
FILE *< имя >;
Здесь < имя > - идентификатор указателя на файл; FILE - имя типа, определенного в файле stdio.h, являющегося структурой, описывающей характеристики файла, суть которых в данном пособии не рассматривается.
Например, можно привести такие описания: FILE * in, *out, *cur;
В зависимости от способа описания можно выделить текстовые файлы и двоичные (типизированные). Вид файла определяет способ хранения информации в файле.
Текстовый файл можно представить как набор строк произвольной длины. Для деления на строки используется управляющий символ \n. Он является файлом последовательного доступа. Логически текстовый файл можно представить как именованную цепочку байтов, имеющую начало и конец. Чтение (или запись) из файла (в файл) ведется байт за байтом от начала к концу. Перед первым обращением к функциям ввода-вывода указатель файла стоит в его начале и указывает на первый компонент. После каждого чтения или записи указатель сдвигается на заданное количество байт. Такой способ доступа называется последовательным. Текстовые файлы оказываются переносимыми с одного типа компьютера на другой, если символы, содержащиеся в файле, принадлежат стандартному набору символов (т. е. не используются дополнительные символы, такие, например, как символы псевдографики фирмы IBM) [6].
Двоичные файлы это последовательность значений типа char. Использование двоичных файлов делает программы немобильными при переносе из одной среды в другую. Любой набор данных может быть представлен как набор символов, но такое представление может изменяться при переходе от одной реализации Си к другой.
Рассмотрим текстовые файлы. Каждой программе доступны два стандартных файла stdin (клавиатура) и stdout (экран). Это - текстовые файлы. Любые другие файлы становятся доступными после выполнения специальных процедур. Рассмотрим основные функции для работы с текстовыми файлами.
Функция открытия файла: FILE *fopen (char *filename, char *type)
Эта функция возвращает указатель на файл, который открывается. Если файл открыть нельзя, то функция возвращает пустой указатель NULL. char *filename указатель на строку символов, содержащую имя файла и, если необходимо, путь к нему. char *type указатель на строку символов, определяющую тип открываемого файла. Допустимы следующие значения этой переменной [6]:
r - открыть уже существующий файл на ввод; w - cоздать новый файл или очистить уже существующий файл и открыть его на вывод; a - cоздать новый файл для вывода или осуществить вывод в конец уже существующего файла; r+- открыть уже существующий файл для обновления, которое будет проводиться с начала файла; w+- cоздать новый файл или очистить уже существующий файл для обновления его содержимого; a+- cоздать новый файл или подстроиться в конец существующего для обновления его содержимого.
Дополнительно к каждой из приведенных строк можно добавить символ b, указывающий на то, что открывается двоичный файл. Если добавлен символ t или символ отсутствует, то открывается текстовый файл.
Примеры открытия файла: FILE * in, *out; in=fopen (input.txt, r); out=fopen (c:\\users\\output.txt, w);
При заполнении файла после последней записи автоматически помещается невидимый специальный признак "конец файла" (end of file). Существует функция feof(f), тестирующая конец файла. Функция feof(f) возвращает значение истина, если действительно встретился признак "конец файла"; пока это не произойдет, значение feof(f) будет ложь.
fclose(FILE * stream) - функция закрытия файла, на который указывает указатель на файл stream. Функция fclose() выполняется автоматически по отношению ко всем открытым файлам при нормальном за-вершении программы.
Для чтения и записи информации из файла или в файл используется очень много функций. Например, функции fscanf и fprintf, анало-гичные уже знакомым функциям scanf и printf, но в качестве первого параметра в них выступает указатель на файл.
Текстовый файл можно создать, используя любой текстовый редактор, в том числе и встроенный текстовый редактор интегрированной среды Borland C++.
32. Структурное программирование в языке программирования с++.
Технология структурного программирования в самой краткой формулировке есть нисходящее проектирование, т.е. выстраивание текста программы, точнее алгоритмической компоненты, от общего к частному, от внешней конструкции к внутренней. Естественно, что надо знать, из чего выстраивать. В идеале, у опытного программиста действительно очередная нужная конструкция появляется «из головы». Но это не значит, что он не имеет общего плана действий и обобщенного представления процесса, который реализуется проектируемой программой.
Именно поэтому в 3.1 технология программирования была обозначена как заключительный этап выстраивания программы из имеющегося набора фрагментов. Перед этим необходимо пройти другие этапы:
· формулировка целей (результатов) работы программы;
· образное представление процессы ее работы (образная модель);
· выделение из образной модели фрагментов: определение переменных и их смыслового наполнения, стандартных программных контекстов.
Любая программа представляет собой структуру, построенную из трёх типов базовых конструкций:
последовательное исполнение — однократное выполнение операций в том порядке, в котором они записаны в тексте программы;
ветвление — однократное выполнение одной из двух или более операций, в зависимости от выполнения некоторого заданного условия;
цикл — многократное исполнение одной и той же операции до тех пор, пока выполняется некоторое заданное условие (условие продолжения цикла).
В программе базовые конструкции могут быть вложены друг в друга произвольным образом, но никаких других средств управления последовательностью выполнения операций не предусматривается.
Повторяющиеся фрагменты программы (либо не повторяющиеся, но представляющие собой логически целостные вычислительные блоки) могут оформляться в виде т. н. подпрограмм (процедур или функций). В этом случае в тексте основной программы, вместо помещённого в подпрограмму фрагмента, вставляется инструкция вызова подпрограммы. При выполнении такой инструкции выполняется вызванная подпрограмма, после чего исполнение программы продолжается с инструкции, следующей за командой вызова подпрограммы.
Разработка программы ведётся пошагово, методом «сверху вниз».
Сначала пишется текст основной программы, в котором, вместо каждого связного логического фрагмента текста, вставляется вызов подпрограммы, которая будет выполнять этот фрагмент. Вместо настоящих, работающих подпрограмм, в программу вставляются «заглушки», которые ничего не делают. Полученная программа проверяется и отлаживается. После того, как программист убедится, что подпрограммы вызываются в правильной последовательности (то есть общая структура программы верна), подпрограммы-заглушки последовательно заменяются на реально работающие, причём разработка каждой подпрограммы ведётся тем же методом, что и основной программы. Разработка заканчивается тогда, когда не останется ни одной «затычки», которая не была бы удалена. Такая последовательность гарантирует, что на каждом этапе разработки программист одновременно имеет дело с обозримым и понятным ему множеством фрагментов, и может быть уверен, что общая структура всех более высоких уровней программы верна. При сопровождении и внесении изменений в программу выясняется, в какие именно процедуры нужно внести изменения, и они вносятся, не затрагивая части программы, непосредственно не связанные с ними. Это позволяет гарантировать, что при внесении изменений и исправлении ошибок не выйдет из строя какая-то часть программы, находящаяся в данный момент вне зоны внимания программиста.
