Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Символьные и строковые данные.
1.Символьные константы. ‘a’, ’A’, ’+’ – имеют внутренний код ‘\n’, ’\t’, ’\n’, ’\0’ и прочие Символьные константы можно использовать как целочисленные операнды 2. Строковые константы. “привет!” “строка \n символ” Все символы строки занимают по 1 байту, в конце компилятор ставит завершающий нуль. Символ ‘z’- 1байт, тогда как строка “z”- 2 байта. 3.Символьные переменные. char s, z; ● Ввод и вывод символьных данных и строк в языке C. scanf(“%c”,&z); printf(“%c”,z); int getchar();//читает из исходного потока например с клавиатуры по 1 символу за 1 обращение и возвращает этот символ int putchar(int c); z=getchar(); //после нажатия клавиши enter putchar(z);//выводит символ на экран и возвращает его ● Строки переменные. Строкового типа в языке C нет. Строки хранятся в массивах символов, но в отличии от символьного массива, в конец строки добавляют завершающий ноль - ‘0’. Присваивать значение массиву символом операцией присваивания нельзя! А так можно: 1.Инициализация. Краткая: char a[]=”привет”; При компиляции в конец строки ставится завершающий ноль. Обычная: char a[]={‘п’,’р’,’и’…’0’}; Примечание: при формировании строки пользователь не должен забывать ставить завершающий нуль в конце строки! 2.Ввод. char a[80]; char*b;//в массив a можно ввести строку scanf(“%s”,a);//по указателю b можно выделить динамическую память под строку, а потом ввести строку Специальные операторы ввода-вывода строк в языке C. puts(str1);//выведет “введите фамилию” //функция puts выводит символы до тех пор, пока не встретит завершающий нуль, вместо завершающего нуля поставит символ перевода строки. Если завершающего нуля нет, программа зацикливается gets(name);//эта функция считывает набранную на клавиатуре строку до символа ‘\n’, он вводится при нажатии enter. При этом количество считанных символов не должно превышать число 79. Пусть оно меньше 79, тогда символ перевода строки отбрасывается, и вместо него ставится завершающий ноль. На этом выполнение функции gets заканчивается. Если вводимая строка превышает 79 символов, то функция введет 79 символов, а затем поставит завершающий нуль. Остальная часть строки будет отброшена. В случае неудачи функция puts возвращает признак конца файла EOF(end of file), которое бывает разное (0,1,-1) ,в основном, зависит от операционной системы. В случае неудачи gets возвращает константу NULL Ввод вывод символов в языке C++ cin.unsetf( ← сбросить установка флага)(ios( ← класс)::skipws( ← флаг));//отменяется действие флага, который заставляет при вводе пропускать символы разделители, в данном случае пробелы cin>>z;//оператор cin>>z при каждом выполнении обновляет значение z, последнее значение “.”, по ней происходит выход из цикла В языке C++ для работы с символами имеются специальные функции. cin.get//считывает очередной символ с клавиатуры cout.put(c)//выводит символ из переменной c на экран. Последний введенный в c символ – это константа EOF ● Ввод и вывод строк в C++. 1.Способ №1. char word[20]; cin>>word;//максимальное количество введенных символов 19, 20 символ – завершающий нуль 2. Способ №2 - специальная функция. char s[80]; … cin.getline(s, 80,’\n’); //или так, так как перевод строки действует по умолчанию cin.getline(s, 80);//функция может считать 79 символов,80 для завершающего нуля AnsiString - в билдере; char* - в C и C++. AnsiString str1=”привет”;//’\n’ → str[1] char str2[]=”привет”;//’\n’ → str[0] обе строки заканчиваются нулем Преобразование строки AnsiString в char*: (строка типа AnsiString).c_str(); Обратное: (AnsiString)(строка типа char*)//преобразование типа ● Библиотека обработки символов. Библиотека <ctype.h> содержит функции. ● Функции преобразования строк. Библиотечные функции обработки строк в файле <stdlib.h>: double atof(const char*p);//преобразует строку p в число типа double int atoi(const char*p);//преобразует строку p в целое число типа int long atoi(const char*p);//преобразует строку p в целое число типа long int Библиотечные функции обработки строк в файле <string.h>: 1. Char*strcpy (char *s1, const char*s2); - копирует строку s2 в строку s1, возвращает строку s1 2. Unsigned strlen (const char *str); возвращает длину строки 3. Int strcmp (const char *s1, const char *s2); - возвращает целое число >0, =0, <0, если s1>s2, =, < 4. Функция конкатенации (соединения) строк Char strcat (char *s1, const char *s2); 5. Функция, разбивающая строку на лексемы Char strtok (char *s1, const char s2); (s1 – строка, s2 – символ)
Классы Это пользовательские типы данных. Причиной появления классов являются недостатки структурного типа. Struct time class time { {int h, m, s; public: } time(); функции t; void settime(int, int, int); открытая (интерфейсная часть) класса void printtime(); возможен доступ извне private: int h; // 0-23 int m; // 0-59 закрытая (доступ внутри класса) int s; // 0-59 }; данные-элементы public: (открытый) private: (закрытый) protected: (защищенный) - спецификаторы доступа time() – конструктор, вызывается автоматически при создании объекта класса void settime – устанавливает новое время void printtime – выводит время
Недостатки: 1. Разрешена всего одна операция – присваивание 2. Структуры не могут быть выведены как единое целое 3. Инициализация структур не обязательна, поэтому появляются объекты с неопределенными свойствами 4. Пользователь имеет прямой доступ к элементам структур, поэтому при инициализации возможна ошибка 5. Если нужно изменить реализацию структурного типа, то необходим просмотр всей программы, что требует большого времени
Примечание: 1. Данные элементы класса не могут получить начальные значения в теле класса, где они объявлены, получают в конструкторе и/или функциях 2. Функции элементы имеют прямой доступ к данным элементам класса, поэтому они могут не иметь параметров 3. Каждая функция элемент может быть определена в теле класса, условие – она должна быть короткой 4. Для идентификации функции используется запись <имя класса>:: 5. В общем случае класс должен иметь деструктор ~ time(); - деструктор предназначен для разрушения созданного конструктором объекта, в примере деструктора нет, он создается автоматически, правильно разрушает объект, т.к. объект использует статическую память, случае динамической памяти – наличие деструктора в классе – обязательно 6. Реализацию класса можно изменять до тех пор, пока не придется изменять интерфейсную часть класса, это упрощает модификацию программы 7. В классах принято отделять объявление от реализации, размещая их в разных файлах Примечание: 1. Переменные, объявленные в функции-элементе, известны только этой функции и имеют область действия – только эту функцию. Если имя такой переменой совпадает с именем данного элемента класса, то доступ к данному элементу класса внутри функции будет такой - <имя класса>::<имя данного элемента класса> 2. При этом доступ к закрытым данным-элементам класса принято контролировать специальными функциями – функциями доступа. Void seth (int); - для установки часов int geth() {return h;}
● Отделение интерфейса от реализации в классах Для этого используют директивы: 1. #ifndef – проверка неопределенности идентификатора 2. #endif – окончание предыдущей директивы В целом это условные директивы 3. #define – определение идентификатора или макроса Макрос – операция обозначаемая символьными строками #define имя_константы (идентификатор макроса) значение_константы (замещающий текст)
Заголовочный файл содержит только объявление класса структуры функции, исполняемых операторов в нем нет, можно включать только очень короткие функции, они имеют признак inline. ● Обслуживающие функции утилиты Обслуживающие функции утилиты - предназначены для обслуживания других функций элементов класса, нет смысла включать их в открытую часть класса, помещают в закрытую, доступ к ним через интерфейс, т.е. через открытую часть класса.
● Конструкторы Каждый класс по технологии должен иметь хотя бы один конструктор, если его нет, создается автоматически, класс создает объект с неопределенными, т.е. неизвестными свойствами, для задания определенных свойств необходима соответствующая функция-элемент. Рекомендуется в составе класса иметь конструктор с умолчанием, вызывается он без указания параметров, затем функция-элемент переопределяет свойства объекта. список инициализации, если он есть, то объект создается в два этапа – первый – конструктором с умолчанием задаются нулевые параметр, затем второй этап – из списка инициализации передаются значения параметров в переопределенный конструктор, соответствующие параметры модифицируются. Наиболее верный вариант. ● Динамически создаваемый объект Как любая переменная объект класса может создаваться как статически, так и динамически, в последнем случае он будет частично или полностью находится в динамической памяти.
● Конструктор с параметрами Конструктор с параметрами: с параметрами m1 инициализирует данный элемент в mem1, параметром m2 инициализирует память выделенную по указателю mem2.
● Деструктор По выходу из функции динамическая память остается занятой, при последующих вызовах dd будет утечка памяти, в итоге программа зависнет. Для того, чтобы динамическая память освобождалась в то же самое время, когда уничтожается объект нужен деструктор.
Определение деструктора Template <class T> Dyn <T>:: ~ dyn () {cout << “Деструктор:” << mem1 << ‘| << *mem2<< endl; Delete mem2; }
Деструктор, как и конструктор, вызывается автоматически.
Вывод: обычно деструкторы вызываются в последовательности, обратной вызову конструкторов, исключение для статических локальных объектов. ● Присваивание По умолчанию присваивание выполняется как побитовое копирование. Для переменных и объектов, находящихся в статической памяти, такое присваивание выполняется верно, для динамически - нет. Для того, чтобы пользоваться известными знаками операций для объектов класса в такой же записи, как для стандартных типов, операции нужно перегружать, для этого используются функции – операции, отличие – имя функции-операции состоит из слова operator, а затем знак операции. В функции создаются два локальных объекта А и В и выполняется присваивание В=А, по выходу из функции эти объекты должны разрушаться, предположим объект В разрушается первым, при разрушении объекта будет вызван деструктор который освободит динамическую память, адрес находится в mem2, следовательно память под разыменованным А будет освобождена, затем уничтожается объект А, при его разрушении будет вызван деструктор, но память уже освобождена и правильный вызов деструктора для А будет ошибочным, следовательно неправильно выполняется операция присваивания. |
Последнее изменение этой страницы: 2019-05-08; Просмотров: 179; Нарушение авторского права страницы