Лекция_2._Обработка_симв_инф_Файлы_Программирование_2_семестр (1271738)
Текст из файла
Лекция 2. Обработка символьной информации и документов сложной структуры. Файлы в СИ
2.1. Обработка символьной информации на Си
2.1.1. Символьный тип
Описание символьной переменной а: char а; данные типа char занимают в памяти один байт и принимают значения на множестве символов, допутимых для данного компьютера. Внутренний код байта определяется по кодовой таблице.
Тип сhar рассматривается в Си как тип целое; при желании над переменными типа char можно выполнять арифметические операции.
Символьная константа записывается как соответствующий символ, заключенный в апострофы. Оператор а='а' означает, что символьной переменной с именем а присваивается значение символа а.
Для использования управляющих символов в Си имеются управляющие константы, запись которых в апострофах начинается с наклонной черты (\), например:
\n - перевод строки,
\f - перевод страницы,
\a - звонок,
\0 - нулевой байт (используется для обозначения конца строки).
Если в апострофах после косой черты стоит восьмеричная (начинается с 0 и содержит цифры от 0 до 7) или шестнадцатеричная (начинается с х или Х) константа, то она рассматривается как символ с соответствующим кодом; например, '\0100'-прописная латинская Р.
2.1.2. Работа со строками символов в Си. Строковые литералы.
В Си отсутствует специальный строковый тип. Вместо такого типа используется понятие строкового литерала.
Строковый литерал - последовательность символов, заключенная в двойные кавычки, например, " text". В памяти ЭВМ строковый литерал представляется как массив элементов типа char, в конце которого помещен символ '\0' (нуль-терминатор).
Адрес строкового литерала и интерпретация его как элемента языка зависит от приема его использования.
Строковый литерал может использоваться в Си-программах следующим образом:
1. Для инициализации массивов типа char.
Следующие описания являются идентичными:
char str[6]="слово"; /*6-й символ - нуль-терминатор*/
char str[]="слово";/* 6 символов, последний – нуль-терминатор*/
char str[6]={'с','л','о','в','о', '\0'};
Если длина массива превышает длину литерала, то оставшиеся символы считаются неопределенными для локальных нестатических массивов или равными нулю для глобальных или локальных статистических массивов.
Пример.
void main()
{char a[10]="слово"/*последние 4 символа имеют неопредел.знач.*/...
В этом случае адрес первого символа литерала есть значение имени массива (адрес первого элемента массива). Массив располагается в стеке функций.
2. Для инициализации или присваивания значения переменной типа char *. Например:
char *str1,*str2="text2";...
str1="text1";
Литералы "text1" и "text2" располагаются в сегменте данных программы, значения адресов их первых элементов присваиваются переменным-указателям str1 и str2. Литералы в данном случае рассматриваются как указатели-константы.
Замечание. Недопустимо присваивать значения, в том числе и значения литералов, именам массивов, так как имя массива - это указатель-константа. Например, следующий фрагмент программы неверен:
char str[6];
str="слово";...
3. Для записи выводимого текста в функциях вывода (printf, puts, и т.д.). Литералы, используемые в этих операторах, хранятся в сегменте данных.
4. Последовательности символов, вводимые с помощью функции scanf по форматам s или с помощью функции gets и аналогичных функций, записываются в память как литералы (символ \n не заносится в память, вместо него записывается \0). Адресом литерала становится адрес переменной-указателя или имя символьного массива, в который вводится литерал.
Для ввода и вывода строк в Си можно применять функции scanf и printf с использованием формата s. Существуют также функции ввода и вывода строк символов puts и gets. Они действуют так же, как scanf("%s",string) и printf("%s\n",string), за одним исключением: scanf принимает символы, пока не встретится \n, а передает в память символы до \n или пробела (символы от первого пробела до \n остаются в буфере); gets передает в память все символы до \n.
2.1.3. ПРИМЕРЫ обработки строк
Пример 1. Вычислить количество слов в строке; под словом понимается группа символов, не содержащая пробелов. Слова могут разделяться одним или несколькими пробелами
В приведенной программе мы подсчитываем число "концов слов", т. е. число пар символов "непробел-пробел" или "непробел-конец строки". Алгоритм (блок-схема на рис.11) предусматривает последовательный просмотр символов строки от ее начала, цикл заканчивается на символе '\0'.
#include <stdio.h>
#include <conio.h>
#define NMAX 81 /*максимальная длина стpоки*/
void main()
{char pr[NMAX];/*рассматриваемая строка*/
int k,n,i; /*k-число слов, n-длина стpоки, i-счетчик символов*/
puts(" Введите стpоkу");
gets(pr);
k=0; i=0;
while (pr[i]!='\0')
{if ((pr[i]!=' ') && ((pr[i+1]==' ') || (pr[i+1]=='\0')))
k=k+1;
i=i+1;
};
printf(" Число слов pавно %2d\n",k); getch();
}
Пример 2. Определить, сколько в последовательности А малых латинских букв и сколько в последовательности В цифр.
Пояснения к примеру 2.
Известно, что во всех широко используемых в настоящее время кодовых таблицах символов малые латинские буквы от ‘a’ до ‘z’ расположены друг за другом в порядке возрастания кода. Цифры от ‘0’ до ‘9’ – также расположены подряд. Поэтому надо найти, сколько символов строки А удовлетворяют условию:
‘a’ ≤ A[i] ≤ ‘z’,
и сколько символов строки B удовлетворяют условию:
‘0’ ≤ B[i] ≤ ‘9’.
Так как алгоритмы обработки A и B отличаются только обозначениями и константами, то следует разработать общую функцию обработки, которая должна вычислять количество символов некоторой строки str, расположенных в интервале от с1 до с2. Прототип такой функции Си: int number(char *str, char c1, char c2); ниже приведена программа, выполняющая задание:
#include <stdio.h>
#include <conio.h>
#define NMAX 81 /*максимальная длина стpоки*/
int number(char *str, char c1, char c2);
void main()
{char a[NMAX], b[NMAX];/*заданные строки*/
puts("Input a");
gets_s(a);
puts("Input b");
gets_s(b);
printf(" ka=%d\n",number(a,'a','z'));
printf(" kb=%d\n",number(b,'0','9'));
_getch();
}
int number(char *str, char c1,char c2)
{
int i, k;
k=0; i=0;
while (str[i]!='\0')
{
if ((str[i]>=c1)&&(str[i]<=c2))
k=k+1;
i=i+1;
}
return(k);
}
2.1.4. Функции и макросы для работы с символьной информацией
Макросы для проверки вида символов и преобразования символов содержатся в заголовочном файле <ctype.h>. Примеры обращений к макросам:
isalnum(c) - истина ,если с - буква или цифра;
isalfa(c) - истина, если с - буква;
isascii(c) - истина, если код символа с меньше или равен 127;
tolower(c) - преобразует символ прописной буквы в символ строчной, не изменяя остальные символы; не являющиеся прописными буквами символы не преобразуются;
toupper(c) - преобразует символ строчной буквы в символ прописной (обратная для tolower).
Эти макросы не предназначены для работы с русскими буквами.
Библиотека для работы со строками символов содержит, например, функции: определение длины строки, копирование строк, выделение подстрок, определение вхождения символа или подстроки в строку, сравнение строк, конкатенация (сцепление строк), вывод строк с сообщениями об ошибках и т. д. Прототипы функций содержатся в заголовочном файле <string.h>.
Большинство функций обрабатывают только последовательности символов, заканчивающиеся нуль-терминатором. В примерах программ следующей лекции использованы функции:
-
strlen(const char *s) - возвращает длину в байтах для строки, на которую указывает s, не учитывая нуль-терминатор;
-
strcpy(char *s1, const char *s2) - копирует строку, на которую указывает s2, в строку, на которую указывает s1;
-
strcmp(const char s1, const char* s2) - выполняет сравнение строк, на которые указывают s1 и s2; возвращает 0, если строки одинаковы, и положительное значение, если s1>s2, иначе отрицательное;
-
strncpy(char *s1, const char *s2, int n) - копирует не более n первых символов строки, на которую указывает s2, в строку, на которую указывает s1; если n меньше длины строки s2, то в s1 не переносится символ '\0';
-
strcat(char* str1, const char* str2) – присоединяет к строке str1 строку str2; под str1 должна быть отведена память, достаточная для хранения результата;
-
strstr(const char *s1,const char *s2) - возвращает указатель на место первого вхождения s2 в s1.
При работе с символьной информацией часто требуются функции, преобразующие строку символов в число и числа в строку символов (иначе говоря, внешнее представление числа во внутреннее и наоборот). Прототипы таких функций содержатся в заголовочном файле <stdlib.h>, некоторые из них дублируются в <math.h> и других заголовочных файлах. В примерах следующей лекции будет использоваться функция atof, преобразующая строку символов в значение типа double; ее шаблон:
double atof (const char *s)
Все вышеупомянутые функции, в частности, используются при программировании обработки таблиц. В таких задачах часто требуется:
-
выделить смысловые поля таблицы, т. е. подстроки, с помощью функций strcpy, strncpy;
-
преобразовать некоторые поля из символьного представления в числовое (с помощью функций atof, atoi и др.);
-
проанализтровать символьные поля с помощью функции strstr, strcmp;
-
подготовить строки выходных данных с помощью, например, itoa, gcvt (см. справочную литературу) и strcat.
Программирование обработки табличных данных может также выполняться с использованием структур, которые рассматриваются в следующем параграфе.
2.2. Тип "структура" в Си
Пока мы рассматривали один вид сложных (занимающих несколько ячеек памяти) данных — массив; одним из основных свойств массива является однотипность его компонент. Многие информационно-логические задачи связаны с обработкой документов, содержащих в себе информация разного типа (числовую, символьную и т. д.) Примеры таких документов: платежные ведомости (фамилии и имена - символьная информация, денежные суммы - числовая), карточки больных в поликлинике, библиотечная информация. Для программирования алгоритмов обработки такой информации необходимо иметь сложный тип, объединяющий разнотипные компоненты. Таким типом является структура в Си.
Структурная переменная, или просто структура, состоит из нескольких данных (называемых полями), возможно, разного типа.
С
труктура
тип "структура" (шаблон) | переменная типа "структура" |
Описание шаблона: | Описание структурной переменной |
typedef struct { Тип1 Список1ИменПолей; | ИмяШаблона ИмяПеременной |
Тип2 Список2ИменПолей; | |
. . . | ключевое struct слово не нужно при |
ТипN СписокNИменПолей; | использовании typedef |
} ИмяШаблона | |
или struct ИмяШаблона | struct ИмяШаблона ИмяПеременной |
{ Тип1 Список1ИменПолей;¦ | |
Тип2 Список2ИменПолей; | |
. . . | |
ТипN СписокNИменПолей; | |
} ; |
Пример. Характеристики книги: автор (author), название (title), год издания (year), цена (price), описываются шаблоном BOOK.
typedef struct {char author[20]; char title[44];/*описание*/
int year; float price} BOOK; /*шаблона BOOK*/
Характеристики
Тип файла документ
Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.
Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.
Файлы такого типа обычно разбиты на страницы, а текст может быть форматированным (жирный, курсив, выбор шрифта, таблицы и т.п.), а также в него можно добавлять изображения. Формат идеально подходит для рефератов, докладов и РПЗ курсовых проектов, которые необходимо распечатать. Кстати перед печатью также сохраняйте файл в PDF, так как принтер может начудить со шрифтами.