Форум: "Основная";
Текущий архив: 2002.07.04;
Скачать: [xml.tar.bz2];
ВнизПоиогите разобраться Найти похожие ветки
← →
Igit (2002-06-21 21:10) [0]Поиогите разобраться
procedure setignor;
var ignored_ini:TextFile;
IgnorSoft: array of PChar;
z:integer; //количество путей
begin
// Finalize(ignored_ini);
AssignFile(ignored_ini, "ignored.ini");
reset(ignored_ini);
SetLength(IgnorSoft,z); //длина масива равна количеству путей
z:=0;
while SeekEof(ignored_ini)=false do //остальное до конца файла это пути
begin
Readln(ignored_ini, IgnorSoft[z]); //вот здесь ошибка "illegal type in Read/Readln statement"
z:=z+1;
end;
CloseFile(ignored_ini);
end;
Нужно заполнить массив длиной z (1-ая строка ignored.ini) путями - остальные строки.
Если IgnorSoft: array of String; , то всё работает, но мне нужно IgnorSoft: array of PChar;
Или подскажите как переделать String в PChar.
← →
jedi (2002-06-21 21:18) [1]uses SysUtils;
var
A: array[0..79] of Char;
S: String;
begin
S := "Honk if you know Blaise.";
StrPCopy(A, S);
end;
ili prostoe privedenie tipov
← →
aus (2002-06-21 22:04) [2]первое что в голову пришло...
Если тебе именно в Array of PChar нужно считать, попробуй читать сначала в string, а потом преобразовывать в pchar.
var s: string;
..........
readln(ignored_ini,s);
ignorSoft[z] := pchar(s);
.............
← →
Anatoly Podgoretsky (2002-06-21 22:52) [3]А память Пушкин будет выделять?
← →
Igit (2002-06-22 09:36) [4]Память?
← →
Anatoly Podgoretsky (2002-06-22 09:52) [5]IgnorSoft: array of PChar;
IgnorSoft[z]);
← →
Igit (2002-06-22 12:31) [6]Ок, я сделал так:
var: IgnorSoft_PCar: array of PChar;
const z = 3;
begin
SetLength(IgnorSoft_PCar, z);
открываю ignored_ini для чтения
............................
z:=0;
while SeekEof(ignored_ini)=false do //пока файл не кончился
begin
Readln(ignored_ini, s);
IgnorSoft_PCar[z]:=PChar(s);
z:=z+1;
end;
end.
............................
После первого выполнения цыкла:
s="NetCaptor"
z=0
IgnorSoft_PCar("NetCaptor", nil, nil)
После второго выполнения цыкла:
s="Elma"
z=1
IgnorSoft_PCar("Elma", "Elma", nil)
После третьего выполнения цыкла:
s="Delphi 5"
z=2
IgnorSoft_PCar("Delphi 5", "Delphi 5", "Delphi 5").
Но мне нужно после третьего чтобы было так:
IgnorSoft_PCar("NetCaptor", "Elma", "Delphi 5")
Я никак не могу понять, что я делаю не так.
← →
Юрий Зотов (2002-06-22 13:06) [7]Сохранять PChar"ы в файле? Бессмыслица. В следующем сеансе все эти PChar"ы окажутся недействительными. Сохранять надо строки, их же и читать, а в PChar преобразовывать уже готовую строку.
И зачем делать это в стиле старого доброго Паскаля, если Вы работаете в Delphi, где есть готовый TStringList с его SaveToFile и LoadFromFile? А также TIniFile с его готовой поддержкой секционирования и методами чтения/записи.
Ошибка же у Вас в том, что смысла PChar Вы, извините, не понимаете. PChar - это указатель на строку, адрес ее тела (то есть, первого символа), вот и все.
Вы читаете строку S и адрес ее первого символа заносите в первый элемент массива. Все ОК. Далее Вы снова читаете строку S и адрес ее первого символа заносите во второй элемент массива. НО ЧТО ИМЕННО ЗАПИСАЛОСЬ ВО ВТОРОЙ ЭЛЕМЕНТ? ТОТ ЖЕ САМЫЙ АДРЕС, ЧТО И В ПЕРВЫЙ. А ЧТО ПОЛУЧИЛОСЬ В ПЕРВОМ ЭЛЕМЕНТЕ? В НЕМ ОСТАЛСЯ ТОТ ЖЕ АДРЕС, ЧТО И БЫЛ, И ОН ПО-ПРЕЖНЕМУ УКАЗЫВАЕТ НА ПЕРВЫЙ СИМВОЛ СТРОКИ - НО СТРОКА-ТО УЖЕ ДРУГАЯ!!!!
Поэтому, сколько бы раз Вы не прогоняли цикл, ВСЕ ЭЛЕМЕНТЫ МАССИВА БУДУТ ВСЕГДА СОДЕРЖАТЬ ОДНО И ТО ЖЕ - АДРЕС ПЕРВОГО ЭЛЕМЕНТА СТРОКИ. А ТЕЛО СТРОКИ ВСЕГДА БУДЕТ РАВНО ПОСЛЕДНЕМУ СЧИТАННОМУ ИЗ ФАЙЛА. И ПОЭТОМУ ВСЕ PChar"ы В МАССИВЕ ВСЕГДА БУДУТ ДАВАТЬ ОДНО И ТО ЖЕ.
В чем Вы уже и убедились.
Поэтому, либо выделяйте память под КАЖДУЮ строку ручками (а потом не забудьте ее освободить), либо просто используйте TStringList и не мучайтесь.
← →
Igit (2002-06-22 14:36) [8]>2 Юрий Злотов
Большое спасибо, что разъясноли мне всё, вы правы - я НЕПРАВИЛЬНО понимал (подразумевал) слово "PChar". Но теперь, когда всё понял, я не могу понять как осуществить свою идею.
А идея у меня вот какая:
У меня есть файл "ignored.ini". В нем записаны текстовый заголовки окон программ. Я порверяю есть ли хотябы одно окно с таким заголовком и если есть значит моя программа остонавливается на например 500мс. и проверяет снова. Если окон с таким заголовком нет, то программа делает свои дела. Я это делаю так:
function prover_ignor : bool;
var n:integer;
begin
prover_ignor:=false;
n:=0;
while n<z do
if findwindow(nil, IgnorSoft_PCar[n])<>0 then
begin
prover_ignor:=true;
break;
end
else
n:=n+1;
end;
А вот чтобы заполнить массив вы уже видели как я хотел сделать.
Выходит я понял вас так : "Какой длины массив IgnorSoft_PCar: array of PChar столько строк должно и быть, то есть я должен создавать строки динамически". Но я НЕ ЗНАЮ, и НИ МОГУ ДАЖЕ ПРЕДПОЛОЖИТЬ КАК ЭТО ОСУЩЕСТВИТЬ.
Программа вся написана на API. Извините за занудность, я только учусь.
С Уважением IGIT
← →
Igit (2002-06-22 14:38) [9]там (выше) в первом предложении опечатка :)
← →
Юрий Зотов (2002-06-22 16:20) [10]1. Вот далеко не самый лучший, но зато самый простой вариант.
uses
..., Classes;
function WindowExists: boolean;
var
i: integer;
begin
Result := False;
with TStringList.Create do
try
LoadFromFile("Ignored.ini");
for i := 0 to Count - 1 do
if FindWindow(nil, PChar(Strings[i])) <> 0 then
begin
Result := True;
Break
end
finally
Free
end
end;
2. Вот вариант посложнее, но зато соответствующий Вашему желанию не использовать объекты VCL, а использовать только чистый Паскаль и API. Будет работать в Delphi 4 и старше (использован динамический массив, которые появились в Delphi 4).
var
Captions: array of PChar;
procedure ReadCaptions; // Вызвать в начале программы
var
F: TextFile;
S: string;
begin
AssignFile(F, "Ignored.ini");
Reset(F);
while not EoF(F) do
begin
ReadLn(F, S);
if S <> "" then
begin
// Добавляем к массиву новый элемент
SetLength(Captions, Length(Captions + 1));
// Выделяем память под тело будущей строки
// и полученный адрес заносим в этот новый элемент
GetMem(Captions[High(Captions)], Length(S) + 1);
// Копируем в эту память тело прочитанной из файла
// строки вместе с завершающим нулем
CopyMemory(Captions[High(Captions)], @S[1], Length(S) + 1)
end
end;
CloseFile(F)
end;
function WindowExists: boolean;
var
i: integer;
begin
Result := False;
for i := Low(Captions) to High(Captions) do
if FindWindow(nil, Captions[i]) <> 0 then
begin
Result := True;
Break
end
end;
procedure ClearCaptions; // Вызвать в конце программы.
vаr
i: integer;
begin
// Освобождаем память, занимаемую телами строк. Нисходящий
// цикл не обязателен, но для менеджера памяти так лучше.
for i := High(Captions) downto Low(Captions) do
FreeMemory(Captions[i], Length(String(Captions[i])) + 1);
// Освобождаем память, занимаемую самим массивом
Captions := nil
end;
← →
Юрий Зотов (2002-06-22 16:53) [11]Тоже опечатка.
:о)
Конечно, в процедуре ReadCaptions должно быть не
SetLength(Captions, Length(Captions + 1));
а
SetLength(Captions, Length(Captions) + 1);
Вообще, советую рассматривать этот код не как абсолютный, а как пример работы с динамическими массивами, указателями, динамической памятью, PChar и String. Поняв его, Вы всегда напишете нужный код сами, для любого конкретного случая.
← →
Igit (2002-06-22 21:47) [12]>2 Юрий Зотов
Спасибо большое, работает. Разобраться попробовал, но не всё понял, наверно потому что вечер и уставший, попробую завтра, если что-то не будет доходить (такой уж я :( , то спрошу:))
← →
Igit (2002-06-22 23:33) [13]>2 Юрий Зотов
Спустя два часа...
Igit (довольный): Я понял!!!
..................................
Что то мне вдруг в голову залетело после мучительного раздумья и я сделал так:
var captions:array of string;
z: integer;
procedure ReadCaptions; // Вызвать в начале программы
var
F: TextFile;
begin
AssignFile(F, "Ignored.ini");
Reset(F);
readln(f, z);
SetLength(Captions, z);
while not EoF(F) do
z:=0;
begin
ReadLn(F, Captions[z]);
z:=z+1;
end;
CloseFile(F)
end;
function WindowExists: boolean;
var
i: integer;
begin
Result := False;
i:=0;
while i<z do
if FindWindow(nil, PChar[Captions[i]) <> 0 then
begin
Result := True;
Break
end else n:=n+1;
end;
Ну как?
← →
Юрий Зотов (2002-06-23 06:54) [14]Нормально. Это самое "паскалевское" решение - использовать массив не просто указателей, а строк и тем самым почти всю работу по распределению памяти возложить на компилятор.
Но есть одно "но" - слишком легко ломается.
Беру файл Ignored.ini, редактирую его вручную, в первую строку записываю, например, -7, сохраняю. Все, программа работать не будет: SetLength(Captions, -7) не пройдет.
Если это не критично, можно оставить и так. Только если уж число строк в файле теперь стало заранее известно, то оба цикла while стоит заменить на for - они гораздо быстрее работают. И где-то в конце желательно очистить массив (хотя при завершении программы система все равно освободит всю память, которую она использовала, но все же это хороший стиль).
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.07.04;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.009 c