Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 5

Автор: Man_Without_Face
Дата сообщения: 06.04.2010 10:27
Frodo_Torbins
Спасибо большое, все работает
Автор: Frodo_Torbins
Дата сообщения: 06.04.2010 10:47
Man_Without_Face
Вы уже читали про юникод в D2009: http://edn.embarcadero.com/article/38446 ? Если еще нет, то очень рекомендую прочитать.
Автор: AviDen
Дата сообщения: 06.04.2010 12:00
EugeneBoss3

Цитата:
Помогите убрать мусор из базы Firebird

Гм, а разве в FB нет SQL-команд backup/restore или аналогичных?
Автор: Odysseos
Дата сообщения: 06.04.2010 12:24
AviDen

Гм, а разве в FB нет SQL-команд backup/restore или аналогичных?

Именно SQL-команд - нет. Есть либо отдельный внешний exe-шник (gbak, или в версиях Firebird 2.0+ - nbackup для инкрементального backup'а), либо т.н. Services API, который доступен из прикладных программ (работа с которым выведена на "верхний уровень", кажется, во всех компонентах доступа к IB/FB).
Автор: Maks150988
Дата сообщения: 06.04.2010 18:54
Доброго времени суток.


Код: const
INI_PROFILE_GENERAL: WideString = 'General';
REG_ROOT_APPPATH: WideString = 'Software\MyApplication\';
REG_GENERAL_PATH: WideString = REG_ROOT_APPPATH + INI_PROFILE_GENERAL;
Автор: akaGM
Дата сообщения: 06.04.2010 19:36
Maks150988
а какой универсальности и/или логики: статической или динамической?

а в зависимости от этого:

1. использование _только_ констант;
2. констант + инициализированных переменных;
3. только ини-переменных;
4. использование ресурсов;
5. пользоваться только кодом;
6. использовать внешную инициализацию, ресурсы;
...
100.

учимся спрашивать...
Автор: Maks150988
Дата сообщения: 06.04.2010 19:45
akaGM

Да я не знаю как объяснить нормально.

Ну есть у меня константы однообразные типа:

bla1 = 'bla\begin';
bla2 = 'bla\end';
bla3 = 'bla\else';

Почему бы это bla отдельно не вынести и просто складывать к нему, да может у меня с километр будет это значение. Ведь с числами такое прокатывает. Это все в глобальной Const в отдельном модуле, чтобы по сто раз одно и тоже не писать, чей потом я может захочу переименовать какую-то переменную на bugaga допустим, нафиг мне надо по всему коду потом рыскать заменять одно и тоже bla.
Автор: AviDen
Дата сообщения: 06.04.2010 19:52
Maks150988

Код:
const
INI_PROFILE_GENERAL = 'General';
REG_ROOT_APPPATH = 'Software\MyApplication\';
REG_GENERAL_PATH: WideString = REG_ROOT_APPPATH + INI_PROFILE_GENERAL;
Автор: akaGM
Дата сообщения: 06.04.2010 20:29
Maks150988
ну вот, нормально уже спросил...
хотя бы так:

Код:
unit MyConst;
interface
const
base_bla = 'bla\';
bla1 = base_bla + 'begin';
bla2 = base_bla + 'end';
bla3 = base_bla + 'else';
implementation
end.
Автор: Maks150988
Дата сообщения: 06.04.2010 21:45
Всем спосибо!
Автор: Bonivur
Дата сообщения: 07.04.2010 16:14
Ноты на грифе гитары обозначаются буквами
C - до, D - ре и.т.д.

имеем двухмерный массив 5x6


E F G A H
H C D E F
G A H C D
D E F G A
A H C D E
E F G A H

задача: найти все возможные сочетания аккорда нот [D A F]
во всех строках массива, во всех возможных положениях, при том,
что ноты аккорда [D A F] не могут находиться на одной строке в найденом
сочетании.
Допустимы варианты с удвоением ноты (например, [D A F A A]
или [D D F F A A] главное, чтобы в найденом сочетании
не была пропущена ни одна из требуемых нот и все найденые
вхождения были бы на разных строках. Необходимо найти также
варианты с пропущенными строками.

при нахождении заполняется дублирующая матрица.

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

в которой вместо 0 помещается символ х. Например, первое
нахождение сочетания может дать такую матрицу

0 х 0 0 0
0 0 х 0 0
0 х 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

или такую

0 0 0 0 0
0 0 х 0 0
0 0 0 0 0
0 0 0 0 х
0 0 0 х 0
0 х 0 0 0

после каждого нахождения сочетания, диаграмма найденного аккорда
выводится на экран, а дублирующая матрица обнуляется.
Автор: Maks150988
Дата сообщения: 07.04.2010 18:04
Всем привет. Мне нужно проверить секцию в ини файле. Сделал код:


Код: function IniFileProfileExistsW(pszFileName, pszAppName: WideString): Boolean;
var
pszbuf : LPWSTR;
workbuf: LPWSTR;
pszText: WideString;
dwRet : DWORD;
begin

Result := FALSE;

GetMem(pszbuf, MAX_PATH);
try
dwRet := GetPrivateProfileSectionNamesW(pszbuf, MAX_PATH, LPWSTR(pszFileName));
if (dwRet <> 0) then
begin
workbuf := pszbuf;
while (workbuf^ <> #0) do
begin
{MessageBoxW(0, LPWSTR(workbuf), nil, MB_OK);}
if (lstrcmpiW(LPWSTR(pszAppName), workbuf) = 0) then
begin
Result := TRUE;
FreeMem(pszbuf, MAX_PATH);
Break
end;
Inc(workbuf, lstrlenW(workbuf) + 1);
end;
end;
finally
FreeMem(pszbuf, MAX_PATH);
end;

end;
Автор: AviDen
Дата сообщения: 07.04.2010 18:12
Maks150988, тебе обязательно нужно работать с unicode-строками? Если нет - прекращай изобретать велосипед и используй TIniFile. А по приведённому коду - примеры смотреть не зазорно, но и читать MSDN тоже надо как бы. А то там такая крамола, что и разбирать лень...
Автор: Odysseos
Дата сообщения: 07.04.2010 18:12
Bonivur

Задачу надо решать именно так, как она поставлена - или, все-таки, с учетом того, что гриф гитары выглядит несколько иначе, нежели


E F G A H
H C D E F
G A H C D
D E F G A
A H C D E
E F G A H


, а именно - вот так:

0 I II III IV V VI

E F F# G G# A B
H C C# D D# E F
G G# A B H C C#
D D# E F F# G G#
A B H C C# D D#
E F F# G G# A B

То есть - задача абстрактная, или Вы на самом деле хотите все аппликатуры для аккорда ре-минор найти?
Автор: volser
Дата сообщения: 07.04.2010 18:13
Maks150988
Почему бы не использовать класс для работы с ини-файлами?
Автор: AviDen
Дата сообщения: 07.04.2010 18:21
Bonivur, нет, ну ты бы ещё попросил всю сессию за тебя сдать, ёлы-палы. С такими задачами полагается сразу же и размер вознаграждения оглашать, что ли.
Автор: Bonivur
Дата сообщения: 07.04.2010 18:37
Odysseos
Я конечно, в курсе какие именно ноты на грифе гитары, но для простоты всякие диезы можно не принимать в расчет. Важно было донести суть задачи. Какая разница какие буквы-ноты? Главное алгоритм. В данном конкретном примере действительно задан поиск аккорда Dm (ре минор).

AviDen
Мне нужен просто общий алгоритм - как подобные задачи решаются.
Автор: Maks150988
Дата сообщения: 07.04.2010 18:53
AviDen
Ну конечно обязательно. Ну я почитал так справку, которая в комплекте с 7 делфи.

Цитата:
The return value specifies the number of characters copied to the specified buffer, not including the terminating null character. If the buffer is not large enough to contain all the section names associated with the specified initialization file, the return value is equal to the length specified by nSize minus two.

Ну значит возвращается количество символов, скопированных в буфер без нультерминатора. А если чего-то там буфер маленький, значит размер результата будет как начальный заданный размер буфера минус 2.


Код: function IniFileProfileExistsW(pszFileName, pszAppName: WideString): Boolean;
var
pszbuf : WideString;
workbuf: LPWSTR;
pszText: WideString;
dwRet : DWORD;
begin

Result := FALSE;

SetLength(pszbuf, MAX_PATH);

dwRet := GetPrivateProfileSectionNamesW(LPWSTR(pszbuf), MAX_PATH, LPWSTR(pszFileName));
if (dwRet <> 0) then
begin
SetLength(pszbuf, dwRet);
workbuf := LPWSTR(pszbuf);
while (workbuf^ <> #0) do
begin
MessageBoxW(0, LPWSTR(workbuf), nil, MB_OK);
Inc(workbuf, lstrlenW(workbuf) + 1);
end;
end;

end;
Автор: volser
Дата сообщения: 07.04.2010 19:37
Maks150988
Я имел ввиду класс TIniFile. Если нужен уникод можно посмотреть реализацию в Delphi 2010. Но поскольку нельзя использовать SysUtils, то он не подходит.
Автор: AviDen
Дата сообщения: 07.04.2010 20:03
Maks150988, да, именно этот абзац я и имел в виду. Ну и? Как с этим согласуется проверка
Код: if (dwRet <> 0) then
Автор: Maks150988
Дата сообщения: 07.04.2010 20:26
AviDen
Да у меня 5 секций, ну ладно, даже если их будет тысяча.


Цитата:
if (dwRet <> 0) then

Да ну вдруг вообще покажет что 0 символов скопируетсмя, ведь ини файл вообще может быть пустым, кто его знает. Тем более у меня вначале указано что результат отрицательный и если функцию вернет нуль, никуда и не пойдем. Буфер pszbuf выделен под список секций, я без понятия сколько надо памяти жахнуть туда, ну взял самое распространенное значение.
Мне значит вернуло какой-то размер скопированных данных, но раз поперли повторы в цикле, значит памяти было выделено достаточно я так понял. Ну я и попытался уменьшить размер этого pszbuf раз такое дело, может я вообще приравниваю криво его к workbuf или чего там надо. Оно непонятно чего-то.
Автор: Odysseos
Дата сообщения: 07.04.2010 21:00
Bonivur

Мне нужен просто общий алгоритм - как подобные задачи решаются.

Полным перебором они решаются.
Автор: Bonivur
Дата сообщения: 07.04.2010 22:26
Odysseos

Цитата:
Полным перебором они решаются.

Если под полным перебором ты имеешь в виду цикл-в-цикле, то пробовал. Все возможные вариатны не находятся. Проблема в том что эти три ноты аккорда могут быть в произвольном порядке и между ними может быть как пустые струны так и просто не звучащие. К тому же на каждой отдельной струне могут быть две ноты входящие в аккорд.
Автор: Odysseos
Дата сообщения: 07.04.2010 22:35
Bonivur

Ну так надо сначала описать все _граничные_условия_ - как то:
- что у нас "басы" (все три басовых струны, или только две E и A, или только E, или нам вообще просто абстрактные аппликатыру нужны);
- что у нас голоса;
- маскимальное расстояние между нотами на разных струнах (а то ведь пальцы не до бесконечности растягиваются, да);
- допустимы ли не звучащие струны (то есть - струны, на которых в диапазоне максимально допустимого расстояния нет ни одной подходящей ноты) посреди "голосов";
- преимущества нот (если нота уже есть в басах - то какую ступень из доступных по расстоянию предпочитать в "голосах")...

Я, собственно, не зря спросил - абстрактная ли задача, или для реального применения.


Добавлено:
Maks150988

Вот код чтения unicode'ного ini-значения любой длины:


Код:
const
BUF_SIZE = 16384;

function ReadIniValueW(const FileName, Section, Ident: WideString): WideString;
var
s_buf: WideString;
len, n: Integer;
begin
s_buf := '';
repeat
len := Length(s_buf) + BUF_SIZE;

SetLength(s_buf, len);
s_buf[len] := High(s_buf[len]);

n := GetPrivateProfileStringW(
PWideChar(Section), PWideChar(Ident), nil,
PWideChar(s_buf), len,
PWideChar(FileName));
until (n < len - 1) or (s_buf[len] <> #0);

if n > 0 then
Result := Trim(Copy(s_buf, 1, n))
else
Result := '';
end;
Автор: Maks150988
Дата сообщения: 07.04.2010 23:03
Odysseos
Ну там конечно да, можно приводить к Unicode через Utf8Encode/Utf8Decode, но у меня уже константы сами WideString и приводить к типам не хочется лишний раз, уж если для функции реестровой подаю константу, то и хочу подавать спокойно в функцию по работе с ини файлами. В ини храню обычный анси, но теперь уже тупо интресно как перечислить все секции с помощью GetPrivateProfileSectionNamesW.
Автор: YuriyRR
Дата сообщения: 07.04.2010 23:36
Maks150988
Если я правильно путаю, то должно быть так

Inc(workbuf, lstrlenW(workbuf)*2 + 1);

а код
Result := TRUE;
FreeMem(pszbuf, MAX_PATH);
Break
Break не отменяет исполнение секции
finally
FreeMem(pszbuf, MAX_PATH);
Автор: Odysseos
Дата сообщения: 07.04.2010 23:50
Maks150988

интресно как перечислить все секции с помощью GetPrivateProfileSectionNamesW

Вот так:

[more]

Код:
procedure ReadIniSectionW(const FileName, Section: WideString; ReadValues: Boolean;
out Idents, Values: TWideStringDynArray);
var
s_section: WideString;

procedure add_ident(const s_ident: WideString);
var
s_buf, s_value: WideString;
i: Integer;
begin
s_buf := Trim(s_ident);
if s_buf <> '' then begin
if ReadValues then
s_value := ReadIniValueW(FileName, s_section, s_buf)
else
s_value := '';

for i := Low(Idents) to High(Idents) do
if WideSameText(s_buf, Idents[i]) then begin
Values[i] := s_value;

Exit;
end;

SetLength(Idents, Length(Idents) + 1);
SetLength(Values, Length(Idents));

Idents[High(Idents)] := s_buf;
Values[High(Values)] := s_value;
end;
end;

var
s_buf: WideString;
p_section: PWideChar;
n, i, len, start_pos: Integer;
begin
s_section := Trim(Section);
if s_section = '' then begin
ReadValues := False;

p_section := nil;
end
else
p_section := PwideChar(s_section);

s_buf := '';
repeat
len := Length(s_buf) + BUF_SIZE;

SetLength(s_buf, len);
s_buf[len] := High(s_buf[len]);

n := GetPrivateProfileStringW(
p_section, nil, nil,
PWideChar(s_buf), len,
PWideChar(FileName));
until (n < len - 2) or (s_buf[len] <> #0);

if n > 0 then begin
start_pos := 1;

for i := 1 to n do
if s_buf[i] = #0 then begin
add_ident(Copy(s_buf, start_pos, i - start_pos));

start_pos := i + 1;
end;

if start_pos <= n then
add_ident(Copy(s_buf, start_pos, n - start_pos + 1));
end;
end;

procedure ReadIniSectionsW(const FileName: WideString;
out Sections: TWideStringDynArray);
var
dummy: TWideStringDynArray;
begin
ReadIniSectionW(FileName, '', False, Sections, dummy);
end;
Автор: Maks150988
Дата сообщения: 08.04.2010 00:56
YuriyRR
Да я вот тоже атк думал.

Odysseos
Ну нет, это как-то грязно. Вот сделал, на гуглокоде сишный пример понятный попался.


Код: function IniFileProfileExistsW(pszFileName, pszAppName: WideString): Boolean;
var
pszBuf: Array [0..MAX_PATH] of WideChar;
pBuf : LPWSTR;
dwRet: DWORD;
begin

Result := FALSE;

dwRet := GetPrivateProfileSectionNamesW(pszBuf, SizeOf(pszBuf), LPWSTR(pszFileName));
pBuf := pszBuf;

while (pBuf <> nil) and (pBuf^ <> #0) do
begin
if (lstrcmpiW(LPWSTR(pszAppName), pBuf) = 0) then
begin
Result := TRUE;
Break;
end;
Inc(pBuf, lstrlenW(pBuf) + 1);
end;

end;
Автор: Odysseos
Дата сообщения: 08.04.2010 02:00
Maks150988

Во-первых - грязно в каком, простите, смысле? Неоптимально? (Стоило бы обосновать, где именно.) Непонятно? (А никто и не обещал.) Или что?

Во-вторых - GetPrivateProfileSectionNamesW - это просто обертка для все той же GetPrivateProfileStringW, с равными nil параметрами lpAppName и lpKeyName.

В-третьих - Ваш код, списаный c какого-то C-примера, как отреагирует на то, что суммарная длина всех секций в ini будет больше, чем MAX_PATH?

В-четвертых - почему Вы считаете, что WinAPI-функция поиска конца PWideChar-строки (lstrlenW) будет быстрей, чем просто проход в цикле по всем символам? Там есть что-то, что M$ может сделать оптимальней, чем просто посимвольным перебором в цикле? (Заметьте - сравнение идет не по подстроке, где и действительно есть, чего оптимизировать, а по отдельному символу.)

...Короче говоря - я предложил заведомо рабочее решение (из рабочего проекта). Не нравится - не пользуйтесь.
Автор: Maks150988
Дата сообщения: 08.04.2010 06:33
Odysseos
Ну желательно меньшим кодом "отделаться", но я ваш пример сохранил, есть кое-что интересное.
Даже если и обертка, то зря чтоли функция существует, раз выдумали ее - будем пользоваться.
Не проблема, в цикле тогда надо увеличивать буфер и сравнивать значение, а не меньше ли возврат на 2, пока не достигнем нужного размера. Тем более у вас в коде так вообще заранее выделяется большой буфер, какая разница, можно и тут заведомо огромный сделать и с лихвой хватит.

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Clipper 5


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.