Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.16.137.108] |
|
Сообщ.
#1
,
|
|
|
Стандартная библиотека С. Функции библиотеки string.h Для обработки строк в программах, написанных на С, применяют билиотеку string.h. В нее входит достаточно большое количество функций. Перед этой библиотеки использованием следует ее подключить: #include <string.h> Создание строк Для создания (не в памяти, аих инициализации) строк применяют функции strcpy и strcat, а также несколько их аналогов. Перед использованием функции strcpy (STRing CoPY) следует проверить, выделена ли память под обе строки. Объявление функции копирования строк: char *strcpy(char *dest, const char *src); wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); char *strncpy(char *dest, const char *src, size_t maxlen); wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t maxlen); Общее их значение таково: строка, находящаяся в src помещается в dest. Если Вы хотите ограничить количество копируемых символов (это бывает полезно, когда длина строки ограничена) следует использовать функцию strncpy. Функции возвращают указатель на полученную строку. Для того, чтобы прибавить к строке другую, программисты используют функцию strcat (STRing conCATenate). Объявление функции добавления строк: char *strcat(char *dest, const char *src); wchar_t *wcscat(wchar_t *dest, const wchar_t *src); Эти функции добавляют строку src в конец строки dest. За счет того, что функции возвращают указатель на полученную строку, имеется возможность использовать вложенные вызовы. Премер использования функций создания строк. #include <alloc.h> //или #include <stdlib.h> #include <string.h> #include <stdio.h> int main() { char *s, *s1, *s2; s1 = strdup(" text0 "); s2 = strdup(" text1 "); s = malloc(128); *s="\0"; //Я инициализирую строки так это - намного быстрее вызовов strcpy strcat(s,s1); //Функция strcat strcat(s,s2); printf("%s\n", s); free(s1); free(s2); free(s); return 0; } Вы увидите на экране " text0 text1 text2 ". Здесь мы познакомились с функцией strdup (STRing DUPclicate). Это аналог функции strcpy, но помимо копирования строки, она выделяет память и возвращает указатель на нее. Ее вызов эквивалентен вызовам malloc и strcpy, поэтому Про strdup надо написать следующее: блок памяти, выделенный для размещения дубликата строки, необходимо вручную удалять при помощи функции free. В string.h она объявлена так: char *strdup(const char *s); wchar_t *_wcsdup(const wchar_t *s); С использованием этих функций связано много подводных камней. Например, иногда под одну из строк не выделена память, это распространенная ошибка. Сравнее строк и поиск подстрок. Сравнее строк представлено в С функциями strcmp, strncmp, strncmpi (strnicmp) , strcmpi (stricmp). Следует заметить, что функции strcmpi и stricmp, а также strncmpi и strnicmp идентичны. Самый простой способ сравнить две строки, использовать функцию strcmp (STRing CoMPare). Эта функция сравнивает две строки без учета регистра. Протитипы функций выглядят так: int strcmp(const char *s1, const char *s2); int wcscmp(const wchar_t *s1, const wchar_t *s2); Для всех функций сравнения существует единое правило возращаемого значения: Результат Возвращаемое значение Строка s1 меньше строки s2 <0 Строка s1 равна строке s2 =0 Строка s1 больше строки s2 >0 Для того, чтобы сравнивать строки c учетом регистра, следует использовать функцию stricmp или strcmpi. Следует сделать важную оговорку: регистр определяется только для латиницы. Объявлена эта функция так: int stricmp(const char *s1, const char *s2); int _wcsicmp(const wchar_t *s1, const wchar_t *s2); int strcmpi(const char *s1, const char *s2); Я не оговариваю возвращаемые значения этих функций, так как они такие же, как и для strcmp. Если вы хотите ограничить количество сравниваемых символов, используйте функции с содержащие в названии букву 'n': int strncmp(const char *s1, const char *s2, size_t maxlen); int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t maxlen); /* Без учета регистра */ int strncmpi(const char *s1, const char *s2, size_t n); int wcsncmpi(const wchar_t *s1, const wchar_t *s2, size_t n); Для того, чтобы найти какую-то подстроку в данной строке, необходимо использовать функции strstr (общая) и strchr (для символов), strspn, strpbrk. Для того, чтобы найти подстроку, программисты обычно используют функцию strstr (STRing in STRing). Объявлена она так: char *strstr(const char *s1, const char *s2); Главное замечание состоит в том, что эти прототипы верны только для С, в С++ первый параметр объявляется без спецификатора const. Возвращает эта функция указатель на первое вхождение s2 в s1 или NULL, если s2 не содержится в s1. Если вам необходимо найти не подстроку, а один из символов строки, используйте функцию strchr (STRing includes CHaR). Ее прототип: /* Для С */ char *strchr(const char *s, int c); //Для С++ const char *strchr(const char *s, int c); //или char *strchr( char *s, int c); wchar_t *wcschr(const wchar_t *s, int c); Эта функция возвращает указатель на первое вхождение символа c в s. Для нахождения последнего вхождения этого символа, применяйте strrchr. Если Вам необходимо найти один из множества символов, используйте функцию strpbrk. Как и у strchr, для С и С++ прототип разный. /* C */ char *strpbrk(const char *s1, const char *s2); //C++ const char *strpbrk(const char *s1, const char *s2); char *strpbrk(char *s1, const char *s2); wchar_t * wcspbrk(const wchar_t *s1, const wchar_t *s2); Возвращаемым значением является указатель на первое вхождение одного из символов из s2 в строку s1. Функция strspn объявлена так: size_t strspn(const char *s1, const char *s2); size_t wcsspn(const wchar_t *s1, const wchar_t *s2); Эта функция возвращает число первых символов, строки s1, которые входят в множество символов s1 (последовательность безразлична). Функция strcspn возвращает индекс первого символа в s1, который принадлежит множеству символов s2. size_t strcspn(const char *s1, const char *s2); size_t wcscspn(const wchar_t *s1, const wchar_t *s2); Общие замечания. Прочие функции Для того, чтобы вычислить длину строки, следует использовать функцию strlen (STRing LENgth) вместо оператора sizeof. size_t strlen(const char *s); size_t wcslen(const wchar_t *s); Возвращает эта функция длину строки s. Иногда функцию strlen используют в циклах, в качестве ограничивающего аргумента. Если Вы хотите оптимизировать свой код, Вам необходимо заранее сосчитать длину строки, а затем использовать полученную переменную в цикле. Это позволит Вам сэкономить время на вызов функции и подсчет длины. Если длина не статична, можно менять полученную переменную в цикле. Если Вам необходимо проверить строку на наличие в ней символов, не обязательно пользоваться функцией strlen. Достаточно проверить первый символ: *s==0 вместо strlen(s)==0. Для того, чтобы перевернуть строку, используйте функцию strrev (STRing REVerse). char *strrev(char *s); wchar_t *_wcsrev(wchar_t *s); Функция возвращает указатель на перевернутую строку. Для того, чтобы заполнить строку символами (например тире), достаточно вызова strnset. char *strnset(char *s, int ch, size_t n); wchar_t *_wcsnset(wchar_t *s, wchar_t ch, size_t n); Возвращается указатель на buf, заполненный символом ch длиной в n символов. Для того, чтобы изменить регистр букв в строке применяются функции strlwr и strupr (только латиница). Прототип функции strlwr (STRing LoWeR). char *strlwr(char *s); wchar_t *_wcslwr(wchar_t *s); Прототип функции strupr (STRing UPpeR). char *strur(char *s); wchar_t *_wcsupr(wchar_t *s); Эти функции возвращают указатель на s. Что не вошло в эту статью? Во-первых, сюда не вошло описание работы со строками, как с массивами char (создание в памяти). Во-вторых не вошли функции strtok (STRing TOKen), strtol и другие функции конвертации строк. В-третьих, здесь описана работа со строками только смомощью стандартных библиотек С. Автор: myaut. Соавторство: Adil, trainer. |
Сообщ.
#2
,
|
|
|
Функции библиотеки dir.h Функции библиотеки io.h, отвечающие за управление файлами на диске Часть 1. Управление файлами и каталогами на диске. Для работы с файлами и каталогами в стандартной библиотеке С предусмотрена билиотека dir.h Из-за того, что на всех платформах API, отвечающее за эти функции различно, горазда удобнее использовать эти функции, решающие проблему переносимости. Сделаю сразу несколько оговорок. Так как С - мультиплатформенный язык, а UNIX/LINUX не поддерживает систему наименования дисков Windows, то за 0 принимают текущий диск, за 1 диск, соответствущий в Windows/DOS путю 'A:', 2 - 'B:' и т. д. Если вы работаете в среде DOS, Вы можете заметить, что некоторые функции переопределены с префиксом _dos. Для их использования необходимо подключить заголовочный файл dos.h Для некоторых функций может потребоваться stdio.h #include <io.h> #include <dir.h> Управление именами файлов Для того, чтобы сформировать путь или поделить его на строки, содержащие устройство (диск), каталог, имя файла и расширение, необходимо использовать соответсвенно функции fnmege (File Name MERGE) и fnsplit (File Name SPLIT) Давайте раcсмотрим их прототипы: void fnmerge(char *path, const char *drive, const char *dir, const char *name, const char *ext); void _wfnmerge(wchar_t *path, const wchar_t *drive, const wchar_t *dir, const wchar_t *name, const wchar_t *ext ); int fnsplit(const char *path, char *drive, char *dir, char *name, char *ext); int _wfnsplit(const wchar_t *path, wchar_t *drive, wchar_t *dir, wchar_t *name, wchar_t *ext ); Длина строк, используемых в этих функциях ограничена. По стандартам ANSI C она равна: Константа 16 бит 32 бита Описание MAXPATH 80 256 Путь MAXDRIVE 3 3 Устройство, включая двоеточие. MAXDIR 66 260 Каталог, включая начальные и конечные обратные слеши (\) MAXFILE 9 256 Имя, без расширения MAXEXT 5 256 Расширение, включает точку Таким образом, чтобы использовать эти функции, необходимо объявить массивы строк длиной в MAX* символов: char path[MAXPATH]; strcpy(path, "C:\\WinNT\\explorer.exe"); /*path содержит C:\WinNT\explorer.exe*/ char drive[MAXDRIVE]; char dir[MAXDIR]; char file[MAXFILE]; char ext[MAXEXT]; fnsplit(path,drive,dir,file,ext); /* Переменная Значение * drive c: * dir \WinNT\ * file explorer * ext .exe */ file[0]=0; /*Очистка имени файла и разширения*/ ext[0]=0; fnmerge(path,drive,dir,file,ext); /*Теперь в path строка C:\WinNT\*/ Для переименования или переименования файла на диске применяют функцию rename. int rename(const char *oldname, const char *newname); int _wrename(const wchar_t *oldname, const wchar_t *newname); Эта функция перемещает/переименовывает файл из пути oldname в newname и возращает -1 или нуль, если операция проведена успешно. Создание и удаление файлов и каталогов Для того, чтобы создать каталог достаточно вызова функции mkdir. Ее преимущество в том, что если в нее передать дополнительный параметр, она доступна в UNIX-системах. Единственный ее параметр - путь к каталогу. int mkdir(const char *path); int _wmkdir(const wchar_t *path); Как и функция rename, при ошибке она возвращает -1, а при успехе - 0. Для того, чтобы удалить созданный раннее каталог достаточно вызова rmdir. К каталогу, который удаляем предъявляются три требования: - он должен буть пустым - он не является текущей рабочей директорией - он не является корневым каталогом int _rmdir(const char *path); int _wrmdir(const wchar_t *path); Для того, чтобы создать файл на диске, используйте функцию _creat, которая создает новый или обрезает существующий файл. Она, как и многие функции io.h работает с файлами с помощью "хэндлов", и поэтому после нее следует вызвать функцию close. Тип файла (текстовый или двоичный) задается глобальной переменной _fmode (O_TEXT или O_BINARY соответственно). Если вы не хотите обрезать старый файл, воспользуйтесь функцией creatnew. int creatnew(const char *path, int mode /*или int attrib*/); При ошибке возвращает -1, при успехе нуль. Первый параметр указывает на путь к файлу, второй на требуемые аттрибуты: Атрибут Объяснение FA_RDONLY Только для чтения FA_HIDDEN Скрытый FA_SYSTEM Системный int _creat(const char *path, int amode); int _wcreat(const wchar_t *path, int amode); Первый параметр - путь к создаваемогу файлу, второй - режим файла. Файл пожет быть открыт и для записи, и для чтения, и для обеих операций. Значение режима Доступ S_IWRITE Разрешение на запись S_IREAD Разрешение на чтение S_IREAD|S_IWRITE Разрешение на запись и чтение Эти константы храняться в библиотеке sys/stat.h Для того, чтобы настроить разрешения для каталога (аналогично режиму файла), используйте функцию chmod. int chmod(const char *path, int amode); int _wchmod(const wchar_t *path, int amode); Функция устанавливает режим amode для каталога path. Для того, чтобы узнать режим файла, используйте функцию access. int access(const char *filename, int amode); int _waccess(const wchar_t *filename, int amode); Определяет возможен ли доступ к файлу filename при режиме amode. Значение Объяснение 6 Возможно ли чтение и запись 4 Возможно ли чтение 2 Возможна ли запись 1 Выполнение (игнорируется) 0 Проверить только на наличие Функция access возвращает значение 0, если файл имеет заданный режим mode. Возвращаемое значение -1 свидетельствует о том, что названный файл не существует или недоступен в заданном amode. Существует два способа удалить файл: через функцию _unlink или remove. int remove(const char *filename); int _wremove(const wchar_t *filename); Функция удаляет файл filename и возвращает нуль при успехе. Ее аналог - функция _unlink еще не утверждена стандартом ANSI C. int _unlink(const char *filename); int _wunlink(const wchar_t *filename); Замечание: если файл открыт, следует закрыть его перед удалением. Работа с переменными окружения Для того, чтобы узнать текущее состояние Дисковой ОС следует воспользоваться функциями, управляющими окружением. Вот, что входит в окружение. Для того, чтобы управлять текущим диском, используются функции getdisk/setdisk. int getdisk(void); int setdisk(int drive); getdisk возвращает текущий диск (0 - 'A', 1 - 'B', ...) В setdisk передается номер диска, который должен стать текущим, а возвращаемым значением является количество доступных дисков. Для того, чтобы узнать текущий путь (prompt) используют функцию getcwd. Если Вам нужно установить путь, следует использовать системную команду cd. char *getcwd(char *buf, int buflen); wchar_t *_wgetcwd(wchar_t *buf, int buflen); Эта функция помещает строку длиной до buflen с текущим путем в buf и возвращает указатель на buf. Если произошла ошибка, фйнкция возвращает NULL и устанавливает переменную errno. Для того, чтобы получить прочие перпменные окружения, следует указать параметр env в main: int main(int argc, char* argv[], char* env[]) { ... } Одной из важнейших переменных MSDOS является переменная PATH. Прежде, чем искать в текущем каталоге файл, DOS обращается в пути, установленные в PATH. Для того, чтобы узнать, существует ли такой файл С предусматривает функцию searchpath. char *searchpath(const char *file); wchar_t *wsearchpath( const wchar_t *file ); Ищет файл file в каталогах окружения, возращает путь к файлу или NULL, если такового не существует. Автор: myaut. Добавлено в : Часть вторая - упавление файлами с помощью дескрипторов. В первой части этой статьи мы уже познакомились с "хэндлами" (handles, descriptors, дескрипторы). Цитата Она, как и многие функции io.h работает с файлами с помощью "хэндлов", и поэтому после нее следует вызвать функцию close. Давайте поподробнеее разберемся с ними. Одной из основных функций является функция open. Эта функция открывает файл по имени path с различными флагами. Флаг указывает функции, какие действия необходимо производить при открытии, а также какие действия разрешены с дескриптором (access) и какие - с файлом (mode): , , для установки режима файла int open(const char *path, int access [, unsigned mode]); int _wopen(const wchar_t *path, int access [, unsigned mode]); Функция возвращает дескриптор файла. Его следует хранить в переменной типа int: int hFile=open("file.txt", O_TEXT | O_RDONLY); Флаг Объяснение O_APPEND Указатель на файл перемещен в конец файла перед каждой операцией записи. O_CREAT Новый файл создан и открыт для записи (аналог _creat). O_EXCL Возвращается значение ошибки, если существует файл, определяемый по path-имени. Только с O_CREATE. O_RDONLY Файл открыт только для чтения; если задается этот флаг, может быть выбран либо флаг O_RDWR, либо O_WRONLY. O_RDWR Файл открыт одновременно для чтения и записи; если задается этот флаг, может быть выбран либо флаг O_RDONLY, либо O_WRONLY. O_TRUNC Существующий файл открыт и усечен к длине 0; этот файл должен иметь разрешение на запись. Содержимое файла уничтожается. O_WRONLY Файл открыт только для чтения; если задан этот флаг, должен быть задан также либо флаг O_RDONLY, либо O_RDWR. O_BINARY Файл открыт в двоичном режиме. O_TEXT Файл открыт в текстовом режиме О разрешениях файла (S_*) говорилось в предыдущей части. Для того, чтобы использовать совместный доступ используют функцию _sopen. , , , int _sopen(char *path, int access, int shflag[, int mode]); int _wsopen(wchar_t *path, int access, int shflag[, int mode]); Эта функция отличается от open параметром shflag (SHare FLAG), этот флаг указывает, какой доступ к файлу имеют другие программы. Он может принимать одно из следующих значений: Значение Описание SH_COMPAT Режим совиестимости SH_DENYRW Запрет на запись и на ятение SH_DENYWR Запрет только на запись SH_DENYRD Запрет только на чтение SH_DENYNONE Разрешает чтение/запись SH_DENYNO Аналогично SH_DENYNONE Если разрешения _sopen действуют во всей ОС, то для блокировки от других процессов используют функции lock/unlock или locking. Для работы с ними в DOS предварительно следует загрузить share.exe int lock(int handle, long offset, long length); Функция блокирует дутпер байтов в файле handle начиная с байта offset. При успехе функция возвращает 0. Для разблокирорования области файла, применяют функцию unlock. int unlock(int handle, long offset, long length); Если Вам нужны расширенные параметры блокировки, используйте функцию locking: int locking(int handle, int cmd, long length); Она блокирует первые length байтов файла handle способом cmd. Значение Действия locking LK_LOCK Блокирует область, при невозможности сделать это, повторяет операцию через 10 секунд LK_RLCK Тоже, что и LK_LOCK. LK_NBLCK Блокирует область, при невозможности сделать это, отказывается от блокировки. LK_NBRLCK Тоже, что и LK_NBLCK. LK_UNLCK Разблокирует ранее заблокированную область. После того, как мы открыли файл, провели с ним каки-нибудь действия, его следуе закрыть функцией close. Единственный параметр этой функции - дескриптор, полученный с помощью функции open: close(hFile). int close(int handle); Как и многие функции, при успехе она возвращает 0, при ошибке - -1. Для того, чтобы сделать копию файла с новым именем, применяют функцию dup2. int dup2(int oldhandle, int newhandle); Она копирует данные из oldhandle в newhandle. Возвращает newhandle. Важными функциями также являются read и write. Первая считывает данные из файла, вторая их записывает, однако они не относятся к функциям управления файлами на диске напрямую, и о них я расскажу позже. |
Сообщ.
#3
,
|
|
|
Часть вторая - управление файлами с помощью дескрипторов.
В первой части этой статьи мы уже познакомились с "хэндлами" (handles, descriptors, дескрипторы). Цитата Она, как и многие функции io.h работает с файлами с помощью "хэндлов", и поэтому после нее следует вызвать функцию close. Давайте поподробнеее разберемся с ними. Одной из основных функций является функция open. Эта функция открывает файл по имени path с различными флагами. Флаг указывает функции, какие действия необходимо производить при открытии, а также какие действия разрешены с дескриптором (access) и какие - с файлом (mode): , , для установки режима файла int open(const char *path, int access [, unsigned mode]); int _wopen(const wchar_t *path, int access [, unsigned mode]); Функция возвращает дескриптор файла. Его следует хранить в переменной типа int: int hFile=open("file.txt", O_TEXT | O_RDONLY); Флаг Объяснение O_APPEND Указатель на файл перемещен в конец файла перед каждой операцией записи. O_CREAT Новый файл создан и открыт для записи (аналог _creat). O_EXCL Возвращается значение ошибки, если существует файл, определяемый по path-имени. Только с O_CREATE. O_RDONLY Файл открыт только для чтения; если задается этот флаг, может быть выбран либо флаг O_RDWR, либо O_WRONLY. O_RDWR Файл открыт одновременно для чтения и записи; если задается этот флаг, может быть выбран либо флаг O_RDONLY, либо O_WRONLY. O_TRUNC Существующий файл открыт и усечен к длине 0; этот файл должен иметь разрешение на запись. Содержимое файла уничтожается. O_WRONLY Файл открыт только для чтения; если задан этот флаг, должен быть задан также либо флаг O_RDONLY, либо O_RDWR. O_BINARY Файл открыт в двоичном режиме. O_TEXT Файл открыт в текстовом режиме О разрешениях файла (S_*) говорилось в предыдущей части. Для того, чтобы использовать совместный доступ используют функцию _sopen. , , , int _sopen(char *path, int access, int shflag[, int mode]); int _wsopen(wchar_t *path, int access, int shflag[, int mode]); Эта функция отличается от open параметром shflag (SHare FLAG), этот флаг указывает, какой доступ к файлу имеют другие программы. Он может принимать одно из следующих значений: Значение Описание SH_COMPAT Режим совиестимости SH_DENYRW Запрет на запись и на ятение SH_DENYWR Запрет только на запись SH_DENYRD Запрет только на чтение SH_DENYNONE Разрешает чтение/запись SH_DENYNO Аналогично SH_DENYNONE Если разрешения _sopen действуют во всей ОС, то для блокировки от других процессов используют функции lock/unlock или locking. Для работы с ними в DOS предварительно следует загрузить share.exe int lock(int handle, long offset, long length); Функция блокирует дутпер байтов в файле handle начиная с байта offset. При успехе функция возвращает 0. Для разблокирорования области файла, применяют функцию unlock. int unlock(int handle, long offset, long length); Если Вам нужны расширенные параметры блокировки, используйте функцию locking: int locking(int handle, int cmd, long length); Она блокирует первые length байтов файла handle способом cmd. Значение Действия locking LK_LOCK Блокирует область, при невозможности сделать это, повторяет операцию через 10 секунд LK_RLCK Тоже, что и LK_LOCK. LK_NBLCK Блокирует область, при невозможности сделать это, отказывается от блокировки. LK_NBRLCK Тоже, что и LK_NBLCK. LK_UNLCK Разблокирует ранее заблокированную область. После того, как мы открыли файл, провели с ним каки-нибудь действия, его следуе закрыть функцией close. Единственный параметр этой функции - дескриптор, полученный с помощью функции open: close(hFile). int close(int handle); Как и многие функции, при успехе она возвращает 0, при ошибке - -1. Для того, чтобы сделать копию файла с новым именем, применяют функцию dup2. int dup2(int oldhandle, int newhandle); Она создает дополнительный дескиптор newhandle файла, указываемого oldhandle и возвращает его. Важными функциями также являются read и write. Первая считывает данные из файла, вторая их записывает, однако они не относятся к функциям управления файлами на диске напрямую, и о них я расскажу позже. Автор myaut. Соавторство CBP. |
Сообщ.
#4
,
|
|
|
Имхо, dup2() очень неудачно здесь описан
|
Сообщ.
#5
,
|
|
|
Обсуждение здесь: Стандартная библиотека С. Раньше надо было думать
|
Сообщ.
#6
,
|
|
|
Часть третья - получение информации о файле.
Так как ФС помимо имени файла хранит еще много различных параметров, я приведу несколько методов получения их. Первый - использование поиска файлов по маске. Для не обязательно иметь конкретное имя файла. Поиск файлов по маске Для того, чтобы создать свой файловый броузер программисты используют метод, называемый поиском файлов по маске. Он заключается в том, что в текущей папке находятся все файлы, удовлетворяющие данной маске. При каждом новом вызове функций программа получает данные о следующем файле. Как правило, для реализации этого метода требуется три функции: - Инициализация поиска. Поиск первого файла. - Поиск n-нного файла (в цикле) - Завершение поиска. Для операционной системы MSDOS этими функциями соответственно являются _dos_findfirst, _dos_findnext. Заключительная функция отсутствует, поиск завершает _dos_findnext. Если Вы примените этот метод в Win32, Вам потребуются функции WinAPI FindFirstFile, FindNextFile, FindClose. Для UNIX - систем следует воспользоваться библиотекой dirent.h и функциями opendir, readdir, closedir и rewinddir. Нже будет рассмотрен пример для DOS. Для того, чтобы начать поиск следует указать маску поиска, параметры поиска и место в памяти, куда будут помещаться выходные данные. или struct find_t { char reserved[21]; /* резерв */ char attrib; /* атрибуты файла */ int wr_time; /* время создания */ int wr_date; /* дата создания */ long size; /* размер файла */ char name[13]; /* имя 8.3 */ }; unsigned findfirst(const char *pathname, int attrib, struct find_t *ffblk); /* В некоторых компиляторах - _dos_findfirst */ Маской является приблизительное наименование файла, например: Маска Объяснение *.* Все файлы с расширением * Все файлы *.txt Все файлы txt ????? Файлы с именем из пяти букв *.? Все файлы с расширением из одной буквы a* Все файлы, начинающиеся с буквы 'a' a?? Все файлы с именем из трех букв, первая из которых 'a' В качестве параметра attrib передаются параметры (атрибуты) файла. Они могут объединяться: FA_HIDDEN | FA_RDONLY. Следует обратиться к справке вашего компилятора, чтобы узнать полный список названий атрибутов. Атрибут Альтернативное название Объяснение FA_NORMAL _A_NORMAL Нормальный FA_RDONLY _A_RDONLY Только для чтения FA_HIDDEN _A_HIDDEN Скрытый FA_SYSTEM _A_SYSTEM Системный FA_LABEL _A_VOLID Метка тома FA_DIREC _A_SUBDIR Папка FA_ARCH _A_ARCH Архивный Когда найден первый файл, следует вызвать функцию findnext. или /* В некоторых компиляторах - _dos_findnext */ unsigned findnext(struct find_t *ffblk); Вот пример поиска файлов в текущей папке (MSDOS/BC5). find_t files[128]; /*До 128 файлов*/ struct find_t ffblk; int maxfiles = 0; int done; done = _dos_findfirst("*.*",_A_NORMAL|_A_SUBDIR,&ffblk); /*Поиск файлов и папок*/ while (!done) { maxfiles++; if(maxfiles==120) break; memcpy(&files[maxfiles],&ffblk, sizeof(find_t)); done = _dos_findnext(&ffblk); } Функции stat, fstat Второй метод - файловая статистика. В С она реализована с помощью функций fstat (stat) int fstat(int handle, struct stat *statbuf); int stat(const char *path, struct stat *statbuf); int _wstat(const wchar_t *path, struct stat *statbuf); Главое отличие fstat от stat заключается в том, что для нее имя файла не обязательно, а достаточно дескриптора (про дескрипторы мы говорили во вотрой части статьи). Второй параметр - указатель на структуру, хранящую файловую статистику. Эта структура принимает такой вид: struct stat { short st_dev; //Дескриптор устройства или номер файла на диске short st_ino; short st_mode; //Режим дескриптора short st_nlink; int st_uid; int st_gid; short st_rdev; long st_size; //Размер в байтах long st_atime; //Файловое время: для NTFS/HPFS - время последнего доступа к файлу long st_mtime; //Файловое время: для NTFS/HPFS - время последней модификации файла long st_ctime; //Файловое время: для NTFS/HPFS - время создания файла }; Для того, чтобы проверить режим дескриптора также объявлены макросы: S_ISDIR(m) - проверяет на директорию S_ISCHR(m) - проверяет на устройство S_ISBLK(m) - проверяет на специальный тип блока S_ISREG(m) - проверяет на файл S_ISFIFO(m) - проверяет на специальный режим FIFO Проверка каждого аттрибута по-отдельности Для некоторых аттрибутов проверку можно провести специальными функциями, например filelength возвращает длину файла handle, getftime позволяет получить дату и время создания файла. |
Сообщ.
#7
,
|
|
|
Краткое знакомство с фукциями math.h Наверное, все знакомы с программой Калькулятор из Microsoft® Windows® и ее режимом "Инженерный". В состав стандартной библиотеки С входит огромное количество математических функций, аналогичных действиям из инженерного калькулятора. Я построил эту статью несколько иначе, чем все предыдущие статьи. abs - абсолютное значение (модуль) acos, acosl - арккосинус asin, asinl - арксинус atan, atanl - арктангенс atan2, atan2l - арктангенс2 cabs, cabsl - абсолбтное значение комплексного числв ceil, ceill - округление вверх, наименьшее целое, не меньшее х cos, cosl - косинус cosh, coshl - косинус гиперболический exp, expl - экспонента fabs, fabs - абсолютный модуль дроби floor, floorl - округление вниз, наибольшее целое, не большее х fmod, fmodl - остаток от деления, аналог операции % frexp, frexpl - разделяет число на мантиссу и экспоненту hypot, hypotl - гипотенуза labs - модуль длинного целого ldexp, ldexpl - произведение числа на два в степени exp log, logl - логарифм натуральный log10, log101 - логарифм лесятичный modf, modfl - разделяет на целую и на дробную часть poly, polyl - полином pow, powl - степень pow10, pow10l - степень десяти sin, sinl - синус sinh, sinhl - синус гиперболический sqrt, sqrtl - квадратный корень tan, tanl - тангенс tanh, tanhl - тангенс гиперболический Для работы с псевдослучайными числами применяются функции stdlib.h randomize (инициализирует генератор) и rand (генерирует число). Для некоторых компьютеров randomize будет неэффективен и гораздо лучше будет использовать функцию srand, использующую системное время. Для псевдослучайных чисел, не ограниченных RAND_MAX можно написать собственный макрос: #define rand2(a, b) (rand()%b-a)+a Генерирует псевдослучайное число между a и b. Автор myaut. Соавторство CBP, Zergling. |
Сообщ.
#8
,
|
|
|
Наверное не
#define rand2(a, b) (rand()%b)+a , а #define rand2(a, b) (rand()%(b-а))+a |
Сообщ.
#9
,
|
|
|
Функции библиотеки alloc.h Часть 1. Выделение и освобождение памяти Указатели появились достаточно давно. Их преимущество над массивами заключалось в том, что работа с ними была более быстрой, а занимаемая ими область памяти могла быть в любой момент освобождена. Однако, использование указателей таит в себе много подводных камней. Достаточно большой процент ошибок составляют ошибки перераспредения памяти. Давайте теперь размеремся, какие функции выделения и освобождения предоставляет нам стандартная библиотека С. Наибольшей популярностью пользуется функция malloc. Она выделяет память из "кучи" (специальная область памяти, которая используется для динамически-выделяемой памяти) и возвращает ее пользователю. При ошибке она возвращает указатель на ничто, то есть NULL. void *malloc(size_t size); Выделяет блок памяти из памяти, предоставленной программе, размером size. Если Вы хотите использовать память под массивы, используйте функцию calloc. Она идеально подходит для выделения массивов, но следует помнить, что "близкие" указатели имеют предел по используемой памяти - 64К, для более массивных выделений следует применять "далекие" указатели (far) и функции farmalloc/farcalloc + farfree. Так как такие блоки памяти имеются только в 16-битных средах, я не буду рассказывать о них. void *calloc(size_t nitems, size_t size); Выделяет память под nitems элементов, каждый из которых занимает по size байтов. При неудаче возвращает NULL. Память, которая выделенна функциями malloc, calloc, realloc, после окончания работы с ней следует освободить, во избежание утечки. Для этого предусмотрена функция free. void free(void *block); Очищает block. Ничего не возвращает. Для более быстрого доступа к памяти (например для временных объектов) применяют функцию alloca. void *alloca(size_t size); Выделяет память стека размером size. Память автоматически освобождается при выходе из функции. Если Вам надо изменить размер выделенной памяти, воспользуйтесь функцией realloc. После того, как Вы выделили память функциями realloc, malloc или calloc, ее следует очитстить функцией free. void free(void* block); Очищает block. В С++ предусмотрены конструкции new и delete. По моему мнению, они более удобны, и поэтому в настоящий момент вышеперечисленные функции не так популярны. К тому же, их проще отлаживать. |
Сообщ.
#10
,
|
|
|
Функции библиотеки mem.h Часть 2 - функции работающие с областью памяти. Мы уже узнали, как выделять и оцищать память. Помимо определяемых пользователем инструкций по обработки памяти, стандартная библиотека С предоставляет нам несколько полезных функций. Все они располагаются в библиотеке mem.h и в целом аналогичны функциям для работы со строками string.h Общий тип указателя - void*, иногда в качестве параметров можно передать указатель на статическую память: struct mystruct s1={0}; struct mystruct s2; memcpy(&s2, &s1, sizeof mystruct); Функции заполнения памяти. В стандартной библиотеке С предусмотрено три типа заполнения памяти: копирование, перемещение и заполнение по шаблону. Первые две операции схожи, давайте рассмотрим их. Прототип memcpy (MEMory CoPY): void *memcpy(void *dest, const void *src, size_t n); void *_wmemcpy(void *dest, const void *src, size_t n); Функция копирует n байтов из src в dest. Эти две области не могут перекрываться в памяти. В первом случае области памяти не перекрываются, во втором случае они имеют общие байты, то есть перекрываются. Если в Вашей программе имеет место второй случаю, используйте функцию memmove (MEMory MOVE), однако она несколько более медленная, чем memcpy. void *memmove(void *dest, const void *src, size_t n); Она, как и memcpy копирует n байтов из src в dest. Эти две области могут перекрываться в памяти. Для того, чтобы выставить дополнительное ограничение по копированию (например, до первого вхождения байта c), используйте функцию memccpy. Если вы хотите заполнить все байты данной области памяти одинаково, используйте memset. void *memset(void *s, int c, size_t n); void *_wmemset(void *s, int c, size_t n); Заполняет n байтов блока s значением c. Для сравнения двух областей памяти используется функция memcmp. int memcmp(const void *s1, const void *s2, size_t n); Сравнивает n байтов блока s1 с блоком s2. Правило возращаемого значения: Результат Возвращаемое значение Блок s1 меньше блока s2 <0 Блок s1 равна блока s2 =0 Блок s1 больше блока s2 >0 Для поиска определенного байта в области памяти, используйте функцию memchr. Как мы увидели, некоторые функции для работы со строками имеют аналоги, работающие с памятью. |
Сообщ.
#11
,
|
|
|
Ну что, продолжим?
Краткое знакомство с макросами библиотеки ctype.h Давайте кратко познакомимся с макросами библиотеки ctype.h, отвечающих за работы с символами: проверку на группу символов и приведение регистра (мы уже рассмотрели функции приведения строки к верхнему или нижнему регистру в первой статье). Следует сделать два важных замечания: isalnum, iswalnum - проверка на латинскую букву или цифру* isalpha, iswalpha - проверка на латинскую букву* isascii, iswascii - проверка на символ из набора ASCII iscntrl, iswcntrl - проверка на управляющий символ isdigit, iswdigit - проверка на десятеричную цифру isgraph, iswgraph - проверка на печатаемый симол (исключая пробел) islower, iswlower - проверка на букву в нижнем регистре* isprint, iswprint - проверка на печатаемый симол (включая пробел) ispunct, iswpunct - проверка на символ пунктуации isspace, iswspace - проверка на пробельный символ (пробел, новая строка или табуляция) isupper, iswupper - проверка на букву в верхнем регистре* isxdigit, iswxdigit - проверка на десятичную цифру toascii - конвертация в символ набора ASCII _tolower - конвертация буквы к нижнему регистру* tolower - конвертация буквы к нижнему регистру если это буква и она в верхнем регистре* _toupper - конвертация буквы к верхнему регистру* toupper - конвертация буквы к верхнему регистру если это буква и она в нижнем регистре* * - необходима установка локализации Автор: myaut. Соавторство: Flex Ferrum. |
Сообщ.
#12
,
|
|
|
Форматированный ввод-вывод в C. Спецификаторы формата функций вывода и системные символы. Перед тем как рассказывать о вводе-выводе средствами стандартной библиотеки С, я решил подготовить предварительную статью и рассказать в ней о комбинациях символов, которые могут применяться внутри самой строки, в качестве указания функции или компилятору. Системные символы Так как переход на новую строку, символ табуляции, перевод каретки и прочие системные символы могут использоваться IDE или компилятором, то для включения этих системных символов внутрь строки достаточно добавления комбинации символа обратного слеша и определенного выражения или номера символа. Комбинация Результат \n Символ переход на новую строку \r Символ перевода каретки \t Табуляция горизонтальная \v Табуляция вертикальная \f Переход на следующую логическую страницу \a Сигнал пользователю. Он может выражаться как в виде звука, так и визуальным путем. \\ Обратный слеш \' Одинарная кавычка \" Двойная кавычка \? Вопросительный знак \x... Символ с номером ..., записанным в шестнадцатиричном формате \... Символ с номером ..., записанным в восьмеричном формате Спецификаторы формата функций вывода Когда функция форматированного ввода или вывода печатает строку, она не может знать, в каком порядке ей переданы аргументы (особенности va_list и структуры памяти x86-компьютеров), для этого программист включает в строку так называемые спецификаторы формата, которые говорят функции что выводить и как. Они начинаются с символа процент (%). %[флаги][ширина][.точность][F|N|h|hh|l|ll|L|I|t|j|z|I64|I32|w]тип Флаги могут записываться в любой последовательности и в любой комбинации. Если вы выберете флаг минус (-), то установите выравнивание влево в отведенном с помощью параметра "ширина" поле, если же нет, все выводимые данные будут выравниваться вправо. Заполнение происходит либо нулями, либо пробелами. Флаг + обязует функцию форматированного вывод вывести знак числа, если же совместно с этим флагом задан флаг "пробел", то последний флаг будет игнорироваться. Флаг "пробел" означает, что если выводится положительное число, вместо знака ничего не выводится: ставится пробел, если же отрицательное, то ставится знак минус. Флаг "решетка" (#) неодинаков для всех типов. Спецификатор ширины применяется для ограничения размеров выводимого поля. Если Вы укажете число в качестве параметра, то будет выводится по крайтей мере количество символов, данное числу, а оставшиеся заполнятся пробелами. Если перед числом указать нуль ("0"), то оставшиеся позиции будут заполняться нулями. Если указать параметр "*", то шириной поля будет являться число, равное значению следующему аргументу из списка, при этом аргумент должен быть целого типа и будет игнорироваться при печати. То есть в следующем коде: int symbolCount=0; int uID = 7581125; int uID2 = 5862458; scanf("%i\n",&symbolCount); printf("%*i\n%16i",uID, symbolCount&0xF, uID2); число uID будет выведено в поле шириной, указаннной в symbolCount, а uID2 будет иметь посто- янную ширины в 16 символов. С помощью параметра точности можно задать усечение количества символов и изменение позиции десятичной точки. Если Вы указываете параметры целого типа, вы не можете указать, какой конкретно тип выводится (длинный, короткий), если непосредственно перед типом не указать одну из следующих букв Символ Результат N* Ближний указатель F* Дальний указатель h short int (signed или unsigned) hh** char (signed или unsigned) l long (signed или unsigned) ll** long long (signed или unsigned) j** intmax_t, uintmax_t z** size_t t** ptrdiff_t L long double w*** wchar_t вместо char I32*** __int32 I64*** __int64 I*** ptrdiff_t, size_t * Только компиляторы Borland ** Только ISO/IEC 9899:1999 (C99) *** Только компиляторы Microsoft И наконец, неполный список всех типов. Символ Результат d Целый целый десятичный i Целый целый десятичный O Целый целый восьмеричный u Целый целый десятичный беззнаковый x Целый целый шестнадцатиричный с цифрами в нижнем регистре X Целый целый шестнадцатиричный с цифрами в верхнем регистре f Дробный действительный с фиксированной точкой (точностью можно указать ее позицию) a* Дробный действительный шестнадцатиричный с фиксированной точкой с цифрами в нижнем регистре A* Дробный действительный шестнадцатиричный с фиксированной точкой с цифрами в верхнем регистре e Дробный действительный экспонентациальный: выводятся мантисса и экспонента, разделяемые символом e E Дробный действительный экспонентациальный: выводятся мантисса и экспонента, разделяемые символом E g Дробный действительный экспонентациальный компактный с символом e G Дробный действительный экспонентациальный компактный с символом E c Символ символ s Строка строка n Указатель на int в ячейку памяти, на которую ссылается аргумент, записывается количество символов, которые функция уже напечатала p Указатель на void выводится значение указателя (сегмент:область) * Только ISO/IEC 9899:1999 (C99) При вводе возможностей гораздо меньше. Из параметров предусмотрена только ширина, флаг "*" (он обозначает следующее: аргумент считывается, но в память не заносится). Конкретизация типов ограничена h, l, I64, L в компиляторах Microsoft и F, N, h, l, L в компиляторах Borland. Примечание: если Вы не уверены в том, что компилятор поддерживает одну из приведенных выше возможностей, обратитесь к помощи за более подробной информацией. Также следует обратиться к стандартам С. |
Сообщ.
#13
,
|
|
|
Функции библиотеки stdio.h Часть 1. Потоки stdin и stdout Функция printf (PRINT Formatted) предназначеня для форматированного вывода строки на экран. Для перехода на новую строку достаточно символа '\n'. Как правило, количество аргументов переменное, но так как синтаксис С не позволяет вызывать функцию, передавая ей бесконечно большое количество аргументов, то для написания собственных функций придется воспользоваться списком аргументов va_list и функцией vprintf. В стандарте C99 предусмотрена возможность использования va_list в макросах. int printf(const char *format[, argument, ...]); int wprintf(const wchar_t *format[, argument, ...]); int vprintf(const char *format, va_list arglist); int vwprintf(const wchar_t *format, va_list arglist); Выводит строку format в поток stdout, учитывая все спецификаторы формата. Аналогично, функция scanf считывет данные, вводимые пользователем из потока stdin. int scanf(const char *format[, address, ...]); int wscanf(const wchar_t *format[, address, ...]); int vscanf(const char *format, va_list arglist); Главным отличием от printf является то, что в качестве необязательных аргументов scanf получает указатели. Простой вывод строки осуществляется функцией puts (PUT String): - только в С++ int puts(const char *s); int _putws(const wchar_t *s); Выводит строку s в поток стандартного вывода и добавляет символ новой строки. Для того, чтобы вывести символ на экран следует использовать макрос putchar - он эквивалентен вывозову putc с параметром stdout. Аналогично, предусмотрены функции getc и getchar. Функция gets считывает символы из потока stdin, пока не встретит EOL (End-Of-Line, конец строки), и добавляет в конец полученной строки нуль-терминатор. Количество вводимых символов не ограничено. Гораздо разумнее использовать fgets, ограничивающую ввод, передавая ей в качестве пара- метра stdin. В С++ для вывода предусмотрен класс cout, а для ввода - cin. Для сравнения: C: printf("%s wrote: %s","myaut","Hello, world"); C++: cout<<"myaut"<<" wrote:"<<"Hello, world"; |
Сообщ.
#14
,
|
|
|
Функции библиотеки stdio.h Часть 2. Работа с файлами В предыдущей части мы рассмотрели стандартный потоки stdin и stdout*, однако в С также предусмотрены потоки пользователя-программиста, использующиеся для работы с файлами. Все эти потоки имеют тип указателя на структуру FILE. Для того, чтобы использовать их, необходим сначала открыть или создать файл. - только для _fdopen FILE *fopen(const char *filename, const char *mode); FILE *_wfopen(const wchar_t *filename, const wchar_t *mode); FILE *_fdopen(int handle, char *type); FILE *_wfdopen(int handle, wchar_t *type); Функция создает поток для файла filename с режимом mode, и возвращает указатель на файловый поток. Функция _fdopen вместо имени файла использует в качестве параметра дескриптор. О них мы говорили во второй статье. Функция fopen предусматривает 6 режимов доступа: Значение Описание r Открыть только для чтения. w Создать для записи; если файл существует, он будет полностью переписан. a Добавить; открыть для записи в конец файла, если файл отсутствует, создать и открыть для записи. r+ Открыть для обновления: чтение и запись. w+ Создать новый файл для обновления: чтение и запись, если он существует, он будет перезаписан. a+ Открыть (или создать, если таковой не существует) для обновения в конце файла. Помимо этого, необходимо выбрать один из дополнительных режимов: t - режим текстового файла b - режим бинарного файла c - при очистке буфера функцией fflush, сохранять его на диск n - отключение флага commit S,R - различные оптимизации для ввода-вывода T,D - различные опции для работы с временными файлами. Опции t и d не зависят от глобальной переменной _fmode. Так как при открытии некоторого файла выделяется память, его следует сохранить, а затем очистить память. Оба этих этапа работы с файлом исполняет функция fclose. int fclose(FILE *stream); Большинство функций работы с файлом аналогичны тем, что мы рассмотривали. Единственные отличие: необходмо указывать указатель на файловый поток. Эти функции, как правило, начинаются с префикса "f". Для бинарных файлов предусмотрены функции fread и fwrite. size_t fread(void *ptr, size_t size, size_t n, FILE *stream); Функция fread считывает в ptr данные, размером size за n итераций из потока stream. Суммарные объем данных - n*size. Функция возвращает общий объем данных, которые были считаны из потока. size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream); Функция fwrite записывает в поток stream данные из массива ptr, длина которого - n элемнтов, а размер каждого элемента - size. Функция возвращает общий объем данных, которые были записаны в поток. Необязательно считывать данные из самого начала. Для перемещения внутри файла существует функция fseek. int fseek(FILE *stream, long offset, int whence); Функция смещает внутренний указатель файла на offset байтов относительно параметра, указанного в параметре whence. Параметр whence может быть равен: SEEK_CUR - относительно текущей позиции SEEK_SET - относительно начала файла SEEK_END - относительно конца файла При успехе возвращаемым значением будет нуль. Если вам необходимо вернуться в начало файла, используйте rewind, являющююся эквивалентом вызова fseek(stream, 0L, SEEK_SET). long int ftell(FILE *stream); Функция ftell вззвращает текущую позицию в файле. Аналогично, fgetpos подучает файловую позицию, а fsetpos ее записывает * - Помимо этих двух потоков существует также поток stderr - стандартный поток вывода ошибок. |
Сообщ.
#15
,
|
|
|
Функции библиотеки stdio.h Часть 3. Прочие полезные функции Если Вы работаете с большим количеством файловых потоков, Вам будет полезна функция fcloseall. Она закрывает все ранее созданные потоки. Исключения составляют потоки, использующиеся для внутренних целей: stdin, stdout, stderr и т. п. int fcloseall(void); Функция возвращвет общее количество закрытых потоков или EOF при ошибке. Если Вы хотите использовать дескрипторы для работы с файлами в комбинации с файловыми потоками Вам будут полезны макрос fileno функция fdopen. Последнюю мы рассмотрели в предыдущей части; вот прототип fileno: int fileno(FILE *stream); Возвращает дескриптор файла stream. Функция freopen позволяет перенаправлять потоки, то естьприменять новые настройки имени файла и флагов для данного потока. Также существует возможность перенаправлять вызовы стандартных потоков в файл. FILE *freopen(const char *filename, const char *mode, FILE *stream); FILE *_wfreopen(const wchar_t *filename, const wchar_t *mode, FILE *stream); При успехе пренаправления потока stream в файл filename с параметрами mode функция возвращает перенаправленный stream, при неуспехе - NULL. Также существует возможность принимать и записывать в поток целое с помощью функций getw и putw. Полный список функций ввода-вывода находиться здесь: http://myautfiles.nm.ru/io_table.htm |