Тотальная неудачница и убийца жёстких дисков.
#post-id: 2837-03-37
#original-date: 2.05.2008 Fri
#original-time: 3:37 AM
#original-day: 2837
#original-host: WinXP Prof SP2 (Build 2600)
Освоила функцию strtok() ^^ Когда в какой-то статье про QuickBasic был код, реализующий эту функцию на QB, я не могла понять, что она делает, а слово "токен" вообще меня вгоняло в ступор. Нынче оно попрежнему вгоняет меня в ступор, но теперь я понимаю принцип действия ^^
Это пример из Инета ^^ А вот что там было написано про другую версию функции:
The strtok_r() function is thread-safe and stores its state in a user-supplied buffer instead of possibly using a static data area that may be overwritten by an unrelated call from another thread.
Я всё искала её в VC++, но не нашла, даже в книжке Джефри Рихтера пыталась найти что-то что было про это ^^ А потом вспомнила, что вообще-то для проекта можно выбирать версию библиотеки C, в том числе и многопоточную, так что стало ясно, что там всё предусмотрено ^^
http://www.opengroup.org/onlinepubs/000095399/functions/strtok.html
Вот код на VB:
Функция получает каталог и создаёт его. Тоесть он может состоять из нескольких подкаталогов, и все они будут созданы. Я где-то в какой-то библиотеке вроде ShlWAPI.DLL видела такое, но не нашла. Пришлось писать самой.
А вот как это на C++:
CUniversalString - это класс-контейнер для строки. Конструктор с char* создаёт внутренний буфер и копирует в него строку. Конструктор с цифрой создаёт буфер заданной длины. Alloc - пересоздаёт буфер, SizeA - возвращает его размер, ValueA - сам буфер, а ещё класс кастуется к LPSTR.
На самом деле там два буфера, и класс создан для перекодировки ANSI-UNICODE, но это не одна его задача. Кроме того, класс буду переписывать - два буфера одновременно - это расточительно...
Кстати, заметьте разницу в размере кода. Да, кое-что уже реализовано в виде отдельных функций, но на VB всё равно кода много не прибавилось. За это я и люблю VB.
#original-date: 2.05.2008 Fri
#original-time: 3:37 AM
#original-day: 2837
#original-host: WinXP Prof SP2 (Build 2600)
Освоила функцию strtok() ^^ Когда в какой-то статье про QuickBasic был код, реализующий эту функцию на QB, я не могла понять, что она делает, а слово "токен" вообще меня вгоняло в ступор. Нынче оно попрежнему вгоняет меня в ступор, но теперь я понимаю принцип действия ^^
#include <string.h>
...
char *token;
char *line = "LINE TO BE SEPARATED";
char *search = " ";
/* Token will point to "LINE". */
token = strtok(line, search);
/* Token will point to "TO". */
token = strtok(NULL, search);
Это пример из Инета ^^ А вот что там было написано про другую версию функции:
The strtok_r() function is thread-safe and stores its state in a user-supplied buffer instead of possibly using a static data area that may be overwritten by an unrelated call from another thread.
Я всё искала её в VC++, но не нашла, даже в книжке Джефри Рихтера пыталась найти что-то что было про это ^^ А потом вспомнила, что вообще-то для проекта можно выбирать версию библиотеки C, в том числе и многопоточную, так что стало ясно, что там всё предусмотрено ^^
http://www.opengroup.org/onlinepubs/000095399/functions/strtok.html
Вот код на VB:
Option Explicit
'====================================================================
Public Sub Main()
MsgBox CreateComplexDirectory("App\Test\Win32\..\Data\")
MsgBox CreateComplexDirectory("App/Test/Win16/Data")
End Sub
' Принимаются и прямые слэши.
Private Function CreateComplexDirectory(ByVal Path As BStr) As Boolean
Dim Elements() As BStr
Dim TMP As Long
Dim RC As Long
Dim NewPath As BStr
Path = Replace(Path, "/", "\")
Path = asGetFullFileName(Path)
If Right(Path, 1) = "\" Then Path = asRemoveBackslash(Path)
If Path = "" Then Exit Function
Elements = Split(Path, "\")
For TMP = LBound(Elements) To UBound(Elements)
If NewPath = "" Then
NewPath = Elements(TMP)
Else
NewPath = asBuildFileName(NewPath, Elements(TMP))
End If
If Not asIsDirectoryExist(NewPath) Then
RC = CreateDirectory(NewPath, 0)
If RC = 0 Then Exit Function
End If
Next TMP
CreateComplexDirectory = True
End Function
Функция получает каталог и создаёт его. Тоесть он может состоять из нескольких подкаталогов, и все они будут созданы. Я где-то в какой-то библиотеке вроде ShlWAPI.DLL видела такое, но не нашла. Пришлось писать самой.
А вот как это на C++:
#include <AJP System.H>
#include <AJP Console.H>
#include <xShlWAPI.H>
#include <string.h>
//===================================================================
BOOL __IsDirectory(char *FileName)
{
DWORD Attribs = GetFileAttributes(FileName);
if (Attribs == 0xFFFFFFFF)
return FALSE;
else {
if (Attribs & FILE_ATTRIBUTE_DIRECTORY)
return TRUE;
else
return FALSE;
}
}
BOOL __IsFileOrDirectoryExist(char *FileName)
{
// GetLongPathName() и GetShortPathName() работают и с масками,
// возвращая первый соответствующий файл. Поэтому использовать эти
// функции нельзя, ведь мы ищем реальный файл. Зато
// GetFileAttributes() возвращает ошибку, если файла нет.
DWORD Attribs = GetFileAttributes(FileName);
if (Attribs == 0xFFFFFFFF)
return FALSE;
else
return TRUE;
}
BOOL __IsDirectoryExist(char *FileName)
{
if (__IsFileOrDirectoryExist(FileName))
return __IsDirectory(FileName);
else
return FALSE;
}
//===================================================================
BOOL CreateComplexDirectory(char *szPath)
{
CUniversalString ucPath(szPath);
CUniversalString ucFullPath(10);
CUniversalString ucNewPath(10);
int TMP = 0;
// Заменяем все прямые слэши обратными...
for (TMP = 0; TMP < lstrlen(ucPath); TMP++) {
if (ucPath.ValueA[TMP] == '/') ucPath.ValueA[TMP] = '\\';
}
// Теперь преобразуем в абсолютный путь...
DWORD RC = GetFullPathName(ucPath, 0, ucFullPath, (LPSTR*)&TMP);
if (RC == 0) return FALSE;
ucFullPath.Alloc(RC + 1);
RC = GetFullPathName(ucPath, RC, ucFullPath, (LPSTR*)&TMP);
if (RC == 0 || RC > ucFullPath.SizeA()) return FALSE;
// И удаляем последний бэкслэш...
PathRemoveBackslash(ucFullPath);
// Теперь режем и на составляющие...
ucNewPath.Alloc(ucFullPath.SizeA() + 10);
char *Token = strtok(ucFullPath, "\\");
if (Token == NULL) return FALSE;
for ( ; Token != NULL; ) {
if (lstrlen(ucNewPath) == 0)
lstrcpy(ucNewPath, Token);
else {
PathAddBackslash(ucNewPath);
lstrcat(ucNewPath, Token);
}
if (!__IsDirectoryExist(ucNewPath)) {
RC = CreateDirectory(ucNewPath, NULL);
if (RC == 0) return FALSE;
}
Token = strtok(NULL, "\\");
}
return TRUE;
}
//===================================================================
int main()
{
SetCurrentDirectory("C:\\Мои документы\\VCPP\\TempProject\\");
cout << CreateComplexDirectory("App\\Test\\Win32\\..\\Data\\") << endl;
cout << CreateComplexDirectory("App/Test/Win16/Data") << endl;
return 0;
}
CUniversalString - это класс-контейнер для строки. Конструктор с char* создаёт внутренний буфер и копирует в него строку. Конструктор с цифрой создаёт буфер заданной длины. Alloc - пересоздаёт буфер, SizeA - возвращает его размер, ValueA - сам буфер, а ещё класс кастуется к LPSTR.
На самом деле там два буфера, и класс создан для перекодировки ANSI-UNICODE, но это не одна его задача. Кроме того, класс буду переписывать - два буфера одновременно - это расточительно...
Кстати, заметьте разницу в размере кода. Да, кое-что уже реализовано в виде отдельных функций, но на VB всё равно кода много не прибавилось. За это я и люблю VB.