Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Подскажите как грамотно решить следующую задачу [D7, WinXP]


Страницы:   1 2

Руслана ©   (2004-12-22 13:07:00) 

Имеется текстовый(test.txt) файл приблизительно такого содержания

@1100
31 40 00 0A B2 40 80 5A 20 01 3F 40 E8 FD B0 12
40 24 C2 43 33 00 F2 43 32 00 D2 C3 32 00 F2 43
31 00 F2 C0 20 00 31 00 C2 43 26 00 F2 43 22 00
F2 C0 56 00 22 00 F2 D2 22 00 F2 D0 20 00 22 00
F2 D0 80 00 22 00 F2 C0 A8 00 21 00 C2 43 24 00
E2 D2 25 00 E2 D3 24 00 E2 D3 25 00 F2 D0 40 00
24 00 F2 D0 40 00 25 00 C2 43 2E 00 F2 43 2A 00
B0 12 80 2C 1F 53 47 57 47 57 47 57 47 57 4C 57
CD 4C 00 00 1D 53 1E 83 EC 23 E9 3F
@FFE0
00 11 48 38 00 11 00 11 D6 37 00 11 86 38 4A 38
00 11 00 11 00 11 40 38 00 11 7E 38 00 11 00 11
@1000
00 00 40 00 00 00 00 00 01 00 00 00 00 00 00 00
0A 01 02 03 04 05 06 07
@FFC0
31 32 38
@FFD0
30 30 30 30 32 32

@1100, @FFE0, @1000 и т.д  - это адреса
31 40 00 0A ... - это данные которые надо записать начиная с соответствующего адреса

Адреса идут неравномерно , т.е. сначало может идти @FFFE, а потом @1000
Максимальный адрес @FFFF, то есть в файле может быть 65536 значений данных (31h, 40h, 00h...)

Как грамотно и максимально быстро записать указанные данные по соответствующим адресам в массив байт
Buffer[0..65535]:Array of byte? Данные в текстовом файле разделены пробелом 31пробел00.


Руслана   (2004-12-23 10:51:00) [1]

Спасибо, попробую.
Указатели я тоже очень люблю :)


begin...end   (2004-12-23 09:03:00) [2]

К [27]: P := StrToInt(S)лучше заменить на P := Low(Buffer) + StrToInt(S).


begin...end   (2004-12-23 08:43:00) [3]

Да, что-то я перемудрил в [20]. Код-то там правильный, только надо добавить проверки для повышения его надёжности, но можно обойтись и без указателей, а оперировать обычными индексами элементов массива. Не занаю, откуда у меня такая любовь к указателям.

Вот код, аналогичный [20] (тоже без проверок):

var
 F: TextFile;
 I, P: Integer;
 S: String;
 Buffer: array [0..65535] of Byte;

begin
 FillMemory(@Buffer, SizeOf(Buffer), $FF);
 AssignFile(F, 'c:\test.txt');
 Reset(F);
 P := Low(Buffer);
 while not EOF(F) do
 begin
   ReadLn(F, S);
   if S[1] = '@' then
   begin
     S[1] := '$';
     P := StrToInt(S)
   end
   else
   begin
     S := StringReplace(S, ' ', '', [rfReplaceAll]);
     for I := 1 to Length(S) div 2 do
     begin
       Buffer[P] := StrToInt('$' + Copy(S, I * 2 - 1, 2));
       Inc(P)
     end
   end
 end;
 CloseFile(F)
end.


Digitman   (2004-12-23 08:24:00) [4]


>  for  i:=0 to 65536 do
>    begin
>    Buffer[i]:=$ff;
>    end;                        // Заполнить масив 0ffh


замени этот цикл одной строчкой
FillChar(Buffer, SizeOf(Buffer), $FF);


Руслана   (2004-12-22 22:11:00) [5]

Согласна :(


begin...end   (2004-12-22 21:54:00) [6]

> [22] Руслана   (22.12.04 21:32)

> Buffer:array[0..6553 5] of byte;


> for  i:=0 to 6553 6do

Ай-яй-яй.


Руслана   (2004-12-22 21:34:00) [7]

А вообще всем кто что-то написал - большое спасибо. Завтра проверю...


Руслана   (2004-12-22 21:32:00) [8]

Вот мой код. В процедуру передается имя файла

procedure LoadtxtFile(TxtFileName:string);
var
Buffer:array[0..65535] of byte;
i:integer;
f:Tstrings;
S,ss: String;
Adress:integer;
k,d,l:integer;
begin

 for  i:=0 to 65536 do
   begin
   Buffer[i]:=$ff;
   end;                        // Заполнить масив 0ffh

f:=Tstringlist.Create;
f.LoadFromFile(TxtFileName);   //  Открыть текстовый файл  
Adress:=$0;

   for i:=0 to f.Count-1 do
 begin
   s:=f.Strings[i];        // Читаем строку из файла
     if S[1]= '@' then     // Проверка на наличие знака адреса
       begin
       Delete(S,1,1);      // Удаляю знак @
       Adress:= StrToInt('$'+S) ;  // Преобразовать строку в адрес
       end
     else
     begin
     d:=1;
     l:= ((Length(S)+1) div 3);
     for k:=1 to l do
     begin
     ss:= Copy(S, d, 2);   // Читаем 2 символа
     d:=d+3;
     Buffer[Adress]:= StrToInt('$'+ss);
     Inc(Adress);
     end;
     end;
 end;

f.Free;

end;


Kair   (2004-12-22 17:30:00) [9]

Я как понял так и написал код в ветке ( http://delphimaster.ru/cgi-bin/forum.pl?n=0&id=1103709382), который почему-то сюда не перешел.

Решение моё. Забил в массив buf: array [0..65535] of array of Byte - для каждого адреса динамический массив с данными.

Вобщем и тут напишу код:


var
 f: TextFile;
 s, ss: String;
 buf: array [0..65535] of array of Byte;
 n: Integer;
begin
n := 0;
AssignFile(f, 'test.txt');
Reset(f);
while not EOF(f) do
 begin
  Readln(f, s);
  if Pos('@', s) > 0 then
   begin
    Delete(s, 1, 1);
    n := StrToInt('$' + s);
   end else
   begin
    if s[Length(s)] #32 then s := s + #32;
    while Pos(#32, s) > 0 do
     begin
      ss := Trim(Copy(s, 1, Pos(#32, s) - 1));
      Delete(s, 1, Pos(#32, s));
      SetLength(buf[n], Length(buf[n]) + 1);
      buf[n, Length(buf[n]) - 1] := StrToInt('$' + ss);
     end;
   end;
 end;
CloseFile(f);
end;


begin...end   (2004-12-22 17:26:00) [10]

> [18] Руслана   (22.12.04 16:31)

Значит, так. Вот набросок кода. Я его особо не тестировал. Здесь нет никаких проверок на корректность данных в файле. Разумеется, в окончательном варианте эти проверки следует добавить.

// Функция, вычисляющая значение указателя
// по смещению относительно другого указателя

function PointerByOffset(Base: Pointer; Offset: Cardinal): Pointer;
begin
 Result := PChar(Base) + Offset
end;

var
 F: TextFile;
 P: Pointer;
 I: Integer;
 S: String;
 B: Byte;
 Buffer: array [0..65535] of Byte;

begin
 AssignFile(F, 'c:\test.txt');
 Reset(F);
 P := @Buffer[0];
 while not EOF(F) do
 begin
   ReadLn(F, S);
   if S[1] = '@' then
   begin
     // В строке указано смещение
     // Формируем новый указатель
     S[1] := '$';
     P := PointerByOffset(@Buffer[0], StrToInt(S))
   end
   else
   begin
     // В строке находятся данные для занесения в память
     // Удаляем пробелы
     S := StringReplace(S, ' ', '', [rfReplaceAll]);
     for I := 1 to Length(S) div 2 do
     begin
       // Получаем из строки очередной байт
       B := StrToInt('$' + Copy(S, I * 2 - 1, 2));
       // Помещаем байт по нужному адресу
       CopyMemory(P, @B, 1);
       // Формируем указатель для размещения следующего байта
       P := PointerByOffset(P, 1)
     end
   end
 end;
 CloseFile(F)
end.


P.S. Если Вам это подойдёт, то спасибом не отделаетесь :-)


Digitman   (2004-12-22 16:49:00) [11]


> Руслана   (22.12.04 16:31) [18]


Так. Постановка задачи стала более-менее ясна.
Теперь - о твоих проблемах и сомнениях .. касаемых существующего решения задачи ..


Руслана   (2004-12-22 16:31:00) [12]

Код вечером брошу - дома он.
П7 - Этот текстовый файл генерит линкер для прошивки микроконтроллера. Понятно что из бинарника быстрей.
begin...end
@1100, @FFE0, @1000 и т.д Память микроконтроллера 64кБ - 65536, организация байтовая.
0000: 55h
0001: ffh

Так вот - то что слева - это адреса, то что справа это данные (код программы, константы, строки и т.д)

таки замечу, что при такой постановке задачи это отнюдь не адреса ... это - смещения отн-но начала некоего массива ..
Разумеется относительные!!! Мне не надо по абсолютным адресам какого либо DIMMa расположить данные!!!
Просто линкер использует такой формат генерации файла. Знак @ просто говорит что за ним находится адрес. В формате Интел Хекс (standart or extended) принят например другой формат

Сформированный массив байт из текстового файла далее будет отправлен в USB на программатор для программирования микроконтроллера.


Руслана   (2004-12-22 16:29:00) [13]

Код вечером брошу - дома он.
П7 - Этот текстовый файл генерит линкер для прошивки микроконтроллера. Понятно что из бинарника быстрей.
begin...end
@1100, @FFE0, @1000 и т.д Память микроконтроллера 64кБ - 65536, организация байтовая.
0000: 55h
0001: ffh

Так вот - то что слева - это адреса, то что справа это данные (код программы, константы, строки и т.д)

таки замечу, что при такой постановке задачи это отнюдь не адреса ... это - смещения отн-но начала некоего массива ..
Разумеется относительные!!! Мне не надо по абсолютным адресам какого либо DIMMa расположить данные!!!
Просто линкер использует такой формат генерации файла. Знак @ просто говорит что за ним находится адрес. В формате Интел Хекс (standart or extended) принят например другой формат

Сформированный массив байт из текстового файла далее будет отправлен в USB на программатор для программирования микроконтроллера.


begin...end   (2004-12-22 15:39:00) [14]

> Руслана   (22.12.04 13:07)

> @1100, @FFE0, @1000 и т.д  - это адреса

А что такое "адреса" в Вашем понимании?


П7   (2004-12-22 14:57:00) [15]

Проблема в чтении и анализе текстового файла или в записи полученных данных в массив? И почему обязательно файл должен быть текстовый? Из бинарника-то оно быстрее будет... (: И не нужно будет 3 байтами (FFпробел) 1 обозначать.


Алхимик   (2004-12-22 13:37:00) [16]


> [8] Руслана   (22.12.04 13:27)
> Разумеется у меня есть свое решение

В студию. Для вскрытия.


TUser   (2004-12-22 13:37:00) [17]


> Поэтому если кто-то напишет свое (необязательно готовое)

А это как?


Digitman   (2004-12-22 13:34:00) [18]


> @1100, @FFE0, @1000 и т.д  - это адреса


таки замечу, что при такой постановке задачи это отнюдь не адреса ... это - смещения отн-но начала некоего массива ..


Людмил   (2004-12-22 13:32:00) [19]

> [8] Руслана   (22.12.04 13:27)

Было бы любопытно взглянуть.


Johnmen   (2004-12-22 13:29:00) [20]

Давай наоборот, ты напишешь, а мы покритикуем :)


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо