Лысаков. Основы программирования (1247269), страница 9
Текст из файла (страница 9)
Также можно создавать и указатели на>>>>>>>><<<<<<<<pVasya->Name;pVasya->Surname;pVasya->Group;pVasya->Birth_year;}76www.phys.nsu.ru6.3.Списки данныхСпискиданныхявляютсявнекоторомродеальтернативойдинамическим массивам. В некоторых задачах, например база данныхРис. 11. Односвязный списоко студентах университета или телефонная книга, пользователь самзачастую не знает, какое количество записей у него будет. Таким образом,нужен иной инструмент, позволяющий по ходу программы изменятьРазберем, каким образом будет выглядеть элемент односвязногоколичество элементов в некоей базе данных.
Таким инструментомсписка, содержащий данные о студенте университета (описанные выше) ии являются списки данных.указатель на следующий элемент списка.Список — это упорядоченная последовательность связанных данных,связанных между собой. При этом списки бывают двух основных видов,в зависимости от характера связей элементов: односвязные и двусвязные.Для хранения списка, и организации работы с ним достаточно лишьодного указателя, который будет хранить адрес первого элемента списка.struct Student{char Name[80];char Surname[80];int Group;int Birth_year;Зная первый элемент, вы всегда сможете последовательно пройти посписку и извлечь любой элемент.Student* pNext;};Помните, что если вы измените значение указателя начала списка(например перейдете к другому элементу в односвязном списке), то выЗаметим, что если программа компилируется с использованием С-можете навсегда потерять первый элемент.
Поэтому на практике, никогдакомпилятора, в типе указателя необходимо указывать не просто имеяне работают с указателем на начало списка, а создают временныеструктуры, а именно с указанием того что это структура. Это связано с темуказатели.что определение структурного типа еще не закончено.struct Student* pNext;6.3.1. Односвязный список данныхОдносвязный список характеризуется наличием одной связи у соседних6.3.2. Двусвязный список данныхэлементов. Другими словами, каждый элемент знает об одном соседеДвусвязный список отличается наличием двух связей у каждого(рис. 11).
По такому списку можно передвигаться только последовательноэлемента. При этом организуется двунаправленность списка (рис. 12).в одном направлении: от начала к концу.Другими словами, зная любой элемент списка, можно получитьинформацию как о следующем элементе списка, так и о предыдущем.7778www.phys.nsu.ruvoid PrintAll(Student* pBegin){if (pBegin == NULL){printf("No elements\n");return;}Рис.12. Двусвязный списокStudent* pCur = pBegin;Для управления списком необходимо знать только первый егоdo{элемент — начало списка.
Последний элемент определяется по признакуcoutcoutcoutcoutтого, что следующего за ним не существует, т. е. указатель равен NULL(рис. 13).}<<<<<<<<pCur->Name;pCur->Surname;pCur->Group;pCur->Birth_year;pCur = pCur->pNext;}while(pCur != NULL);6.3.4. Добавление элемента в существующий списокРазберемнапримереодносвязногоспискастудентовпроцессдобавления элемента и реализуем для этого функцию.Рис.13. Указатель на начало двусвязного спискаВ качестве входных параметров функция должна получить указатель насуществующий список, собственно указатель на добавляемый элемент иномер, которым он должен стать в списке.Если следующего элемента не существует, то указатель pnextПри добавлении элемента в список возможны три различных ситуации:•необходимо задать равным NULL.список пуст, соответственно независимо от номера, элементстановится первым;6.3.3.
Распечатка элементов спискаФункция для распечатки существующего списка может выглядетьследующим образом (в качестве параметра функция получает указатель напервый элемент списка):•элемент необходимо вставить в конец списка;•элемент вставляется в середину списка.Помните, что если элемент оказывается последним, то необходимо вполе указателя на следующий элемент прописать NULL.7980www.phys.nsu.ruvoid AddElement(Student* pBegin,Student* pAdd, int number){// Если список был пуст - на первое местоif(pBegin == NULL){pBegin = pAdd;pAdd->pNext = NULL;return;}// Ищем в списке элемент// за которым должны вставитьint n = 0;Student* pCur = pBegin;for(n = 0; n < number; n++)pCur = pCur->pNext;// Если нужно вставить последнимif(pCur->pNext == NULL){pCur->pNext = pAdd;pAdd->pNext = NULL;return;}// Определяем следующий элементStudent* pNext = pCur->pNext;// Вставляем элемент в списокpCur->pNext = pAdd;pAdd->pNext = pNext;}7.
Работа с файламиВ данном пособии рассматривается подход к файловым операциям,основанный на языке С..Первоначально язык С был реализован в операционной системе UNIX.Как таковые, ранние версии С (да и многие нынешние) поддерживаютнабор функций ввода/вывода, совместимый с UNIX. Этот набор иногданазывают UNIX-подобной системой ввода/вывода или небуферизованнойсистемой ввода/вывода.
Однако когда С был стандартизован, то UNIXподобные функции в него не вошли — в основном из-за того, чтооказались лишними. Кроме того, UNIX-подобная система может оказатьсянеподходящей для некоторых сред, которые могут поддерживать язык С,но не эту систему ввода/вывода.В этой главе описана работа с файловой системой в языке С. В языке Ссистема ввода/вывода реализуется с помощью библиотечных функций, ане ключевых слов. Благодаря этому система ввода/вывода является оченьмощной и гибкой. Например, во время работы с файлами данные могутпередаваться или в своем внутреннем двоичном представлении или втекстовом формате, то есть в более удобочитаемом виде. Это облегчаетзадачу создания файлов в нужном формате.Библиотека С поддерживает три уровня ввода-вывода: потоковый вводвывод, ввод-вывод нижнего уровня и ввод-вывод для консоли и портов.7.1.Потоки и файлыПеред тем как начать изучение файловой системы языка С, необходимоуяснить, в чем разница между потоками и файлами.
В системеввода/вывода С для программ поддерживается единый интерфейс, неОбратите внимание, что в приведенном примере не производитсяобработка ситуаций с некорректным номером элемента.зависящий от того, к какому конкретному устройству осуществляетсядоступ. То есть в этой системе между программой и устройствомнаходится нечто более общее, чем само устройство. Такое обобщенноеустройство ввода или вывода (устройство более высокого уровня8182www.phys.nsu.ruабстракции) называется потоком, в то время как конкретное устройство7.1.3.
Двоичные потокиназывается файлом. (Впрочем, файл — тоже понятие абстрактное.) ОченьДвоичный поток — это последовательность байтов, которая взаимноважно понимать, каким образом происходит взаимодействие потоков иоднозначно соответствует байтам на внешнем устройстве, причемфайлов.никакого7.1.1.
Потокипреобразованиясимволовнепроисходит.Крометого,количество тех байтов, которые пишутся (читаются), и тех, которыеФайловая система языка С предназначена для работы с самымиразными устройствами, в том числе терминалами, дисководами инакопителями на магнитной ленте. Даже если какое-то устройство сильноотличается от других, буферизованная файловая система все равнопредставит его в виде логического устройства, которое называетсяхранятся на внешнем устройстве, одинаково. Однако в конце двоичногопотока может добавляться определяемое приложением количествонулевых байтов. Такие нулевые байты, например, могут использоватьсядлязаполнениясвободногоместавблокепамятинезначащейинформацией, чтобы она в точности заполнила сектор на диске.потоком.
Все потоки ведут себя похожим образом. И так как они восновном не зависят от физических устройств, то та же функция, которая7.1.4. Файлывыполняет запись в дисковый файл, может ту же операцию выполнять и наВ языке С файлом может быть все что угодно, начиная с дисковогодругом устройстве, например, на консоли. Потоки бывают двух видов:файла и заканчивая терминалом или принтером. Поток связывают стекстовые и двоичные.определенным файлом, выполняя операцию открытия.
Как только файлоткрыт, можно проводить обмен информацией между ним и программой.7.1.2. Текстовые потокиНо не у всех файлов одинаковые возможности. Например, к дисковомуТекстовый поток — это последовательность символов. В стандарте Ссчитается, что текстовый поток организован в виде строк, каждая изкоторых заканчивается символом новой строки.
Однако в конце последнейстроки этот символ не является обязательным. В текстовом потоке потребованиюбазовойсредымогутпроисходитьопределенныепреобразования символов. Например, символ новой строки может бытьзаменен парой символов — возврата каретки и перевода строки. Поэтомуможет и не быть однозначного соответствия между символами, которыепишутся (читаются), и теми, которые хранятся во внешнем устройстве.Кроме того, количество тех символов, которые пишутся (читаются), и тех,которые хранятся во внешнем устройстве, может также не совпадать из-завозможных преобразований.83файлу прямой доступ возможен, в то время как к некоторым принтерам —нет.