Слайд 1Строковый тип данных
В языке С для строк не предусмотрено отдельного
типа данных, строки могут определяться следующим образом:
как строковые константы;
как массивы
символов;
через указатель на символьный тип;
как массивы строк.
Любая последовательность символов, заключенная в двойные кавычки ” ”, рассматривается как строковая константа. Одинарные кавычки ‘ ‘ задают отдельный символ.
Для корректного вывода любая строка должна заканчиваться нуль-символом '\0', целочисленное значение которого равно 0. При объявлении строковой константы нуль-символ добавляется к ней автоматически. Так, последовательность символов, представляющая собой строковую константу, будет размещена в оперативной памяти компьютера, включая нулевой байт.
Слайд 2Под хранение строки выделяются последовательно идущие ячейки памяти. Таким образом,
строка представляет собой массив символов. Для хранения кода каждого символа
строки отводится 1 байт (тип char).
Строковые константы размещаются в статической памяти. Начальный адрес последовательности символов в двойных кавычках трактуется как адрес строки. Строковые константы часто используются для осуществления диалога с пользователем в таких функциях, как printf().
Слайд 3этом случае имена m2 и m3 являются указателями на первые элементы массивов:
m2 - эквивалентно &m2[0]
m2[0]
- эквивалентно ‘I’
m2[3] - эквивалентно ‘e’
Для задания строки можно использовать указатель на символьный
тип:
Слайд 4Здесь m3 является константой-указателем. Нельзя изменить m3, так как это означало бы изменение
положения (адреса) массива в памяти, в отличие от m4.
Для указателя можно
использовать операцию увеличения (перемещения на следующий символ): m4++
Иногда в программах возникает необходимость описание массива символьных строк. В этом случае можно использовать индекс строки для доступа к нескольким разным строкам:
Слайд 5Инициализация выполняется по правилам, определенным для массивов. Тексты в кавычках
эквивалентны инициализации каждой строки в массиве. Запятая разделяет соседние последовательности.
Кроме
того, можно явно задавать размер строк символов, используя описание, подобное такому: char text[4][25]
Разница заключается в том, что такая форма задает «прямоугольный» массив, в котором все строки имеют одинаковую длину.
Описание же char* text[4] определяет свободный массив, где длина каждой строки определяется тем указателем, который эту строку инициализирует. Свободный массив не тратит память напрасно.
Слайд 6Операции со строками
Большинство строковых операций языка С, работает с указателями.
Для размещения в оперативной памяти строки символов необходимо:
выделить блок оперативной
памяти под массив;
проинициализировать строку.
Для выделения памяти под хранение строки могут использоваться функции динамического выделения памяти. При этом необходимо учитывать требуемый размер строки:
Слайд 7Вывод строк можно осуществлять через printf:
Для вывода строк также может
использоваться функция puts:
int puts (char *s);
которая печатает строку s и переводит курсор на новую строку
(в отличие от printf). Для вывода символов может использоваться функция
char putchar(char);
Для ввода строки может использоваться функция scanf(). Однако она предназначена скорее для получения слова, а не строки. Если применять формат "%s" для ввода, строка вводится до (но не включая) следующего пустого символа, которым может быть пробел, табуляция или перевод строки. Для ввода строки, включая пробелы, используется функция:
char* gets(char *s);
Слайд 8Количество символов, считываемых gets(), не ограничивается. Поэтому программист должен сам
следить за тем, чтобы не выйти за границы массива, на
который указывает str. Поэтому вместо неё можно использовать более безопасную версию функции:
char* fgets(char *s, size_t n, stdin);
Где n – максимальное количество символов, выделеных в буфере s, а stdin – стандартный поток ввода.
Для ввода символов может использоваться функция
char getchar();
которая возвращает значение символа, введенного с клавиатуры.
Слайд 9Основные функции стандартной библиотеки string.h
Слайд 11Следует иметь в виду, что все эти функции не производит
проверки границ, поэтому программист должен сам позаботиться о том, чтобы
заполняемый символьный массив не был переполнен.
Рассмотрим пример замены в тексте строки на другую строку той же длины:
Слайд 14Параметры запуска
При создании консольного приложения в языке С, автоматически создается
функция main следующего вида:
int main(int argc, char** argv)
Если программу запускать
через командную строку, то есть возможность передать какую-либо информацию этой программе, указывая аргументы через пробел:
Диск:\путь\имя.exe аргумент1 аргумент2 аргумент3
Параметр argc указывает количество переданных аргументов, а argv является массивом указателей на строки – сами аргументы. Причем argc всегда не меньше 1, так как первым аргументом всегда передаётся полный путь к исполняемому файлу и полное имя.
Слайд 15В среде Dev-C++ аргументы запуска можно задать в меню выполнить
-> параметры…
Слайд 17Компиляция программ
Исходный C файл — это всего лишь текстовый файл с
С кодом, который невозможно запустить как программу или использовать как
библиотеку. Поэтому каждый исходный файл требуется скомпилировать в исполняемый файл, динамическую или статическую библиотеки.
Компиляция — это процесс трансляции программы, составленной на исходном языке высокого уровня, в эквивалентную программу на низкоуровневом языке, близком к машинному коду, или непосредственно на машинном языке и последующую сборку исполняемой машинной программы.
Слайд 18Процесс компиляции программ на языке C обычно состоит из следующих
этапов:
1) Препроцессинг – подготовка исходного текста программы для дальнейшей компиляции.
На данном этапе происходит удаление всех комментариев и модификация программы в соответствии с заданными препроцессорными директивами (сами директивы также удаляются).
2) Компиляция – на данном этапе выполняется преобразование (трансляция) модифицированной на предыдущем шаге программы в ассемблерный код.
3) Ассемблирование – Так как процессоры исполняют команды только в бинарном виде, необходимо перевести ассемблерный код в машинный с помощью ассемблера, сохраняя его в объектном файле.
Объектный файл — это созданный ассемблером промежуточный файл, хранящий кусок машинного кода программы. Этот кусок, еще не связанный вместе с другими кусками машинного кода в конечную выполняемую программу, называется объектным кодом. Объектных файлов может быть много и нужно их всех соединить в единый исполняемый файл.
Слайд 194) Компоновка - компоновщик (линкер) связывает все объектные файлы и статические
библиотеки в единый исполняемый файл. Процесс связывания происходит с помощью таблицы
символов. При этом возможны ошибки связывания: например если функция была объявлена, но не определена, ошибка обнаружится только на этом этапе.
Таблица символов — это структура данных, создаваемая самим компилятором и хранящаяся в самих объектных файлах. Таблица символов хранит имена переменных, функций, объектов и т.д., где каждому идентификатору (символу) соотносится его тип и область видимости. Также таблица символов хранит адреса ссылок на данные и процедуры в других объектных файлах. Именно с помощью таблицы символов и хранящихся в них ссылок линкер будет способен в дальнейшем построить связи между данными среди множества других объектных файлов и создать единый исполняемый файл из них.
После этого этапа получается исполняемый файл, который можно уже запустить на компьютере. После запуска исполняемая программа загружается в память компьютера и начинает выполнение. На данном этапе также возможна подгрузка динамических библиотек.
Слайд 20Препроцессор
Компилятор
Ассемблер
Компоновщик
(Линкер)
Исходный код *.с
Модифицированный
исходный код
Ассемблерный
код
Объектный
код
Исполняемый
файл
Объектный
код других модулей
Объектный
код статических библиотек