Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.12.2009, 21:13   #1
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию Проблемы с PChar (Считывание из ini файла)

Всем привет.
Вот у меня такая проблема
Есть структура
Код:
tRec = record
    s1, s2, s3, s4: pChar;
  end;
есть
процедура считывания и заполнения указателей в list: tList
Код:
procedure TForm1.FormCreate(Sender: TObject);
var
iniFile: tMemIniFile;
pr: ^tRec;
c: integer;
begin
   list := tList.Create;
   iniFile := tMemIniFile.Create(extractFilePath(application.ExeName)+'file.ini');
   for c := 0 to 12 do
   begin
      new(pr);

      pr.s1 := pChar(iniFile.ReadString('000', '1', '(S 1---)'));
      pr.s2 := pChar(iniFile.ReadString('000', '2', '(S 2---)'));
      pr.s3 := pChar(iniFile.ReadString('000', '3', '(S 3---)'));
      pr.s4 := pChar(iniFile.ReadString('000', '4', '(S 4---)'));

      list.Add(pr);
   end;
   iniFIle.Free;
end;
и ещё есть процедура отображения
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
c: integer;
pr: ^TRec;
begin
   listBox1.Clear;
   for c := 0 to List.Count - 1 do
   begin
      pr := list.Items[c];
      listBox1.Items.Add(intToStr(c));
      listBox1.Items.Add('A>'+pr.s1);
      listBox1.Items.Add('B>'+pr.s2);
      listBox1.Items.Add('C>'+pr.s3);
      listBox1.Items.Add('D>'+pr.s4);
   end;
end;
Проблема в том, что происходят проблемы. Те кто в курсе поймут о чём я.
Причём если в tRec все переменные типа string То всё ОК.

В аттаче полный проэкт. (В Delphi 7 полная неразбериха)

Вложения
Тип файла: rar Новая папка.rar (7.4 Кб, 10 просмотров)
Altera вне форума Ответить с цитированием
Старый 17.12.2009, 21:27   #2
Д'якон
Форумчанин
 
Регистрация: 05.12.2007
Сообщений: 236
По умолчанию

pChar - имеет размер 4 байта, какие проблемы?
Д'якон вне форума Ответить с цитированием
Старый 17.12.2009, 23:57   #3
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Код:
pr.s1 := pChar(iniFile.ReadString('000', '1', '(S 1---)'));
Если рассуждать логически и рационально, то можно выделить несколько этапов:
1. Формирование строк (адреса в памяти) для '000', '1', '(S 1---)'
2. Выделение в памяти "типа" String (локально) как результата для iniFile.ReadString
3. Вызов iniFile.ReadString
4. Получения адреса первого "символа" результата вызова iniFile.ReadString который "записался" ранее зарезервированное место п. 2
5. pr.s1 хранит адрес пункта 4
6. list.Add(pr); - сохранение адреса на адрес на адрес так сказать. не важно.
7. ret - он же end; данной функции, освобождение локально выделенной памяти пункт 2.
8. Теперь по сути, место в памяти куда указывает pr.s1 может модифицироватся как угодно системой, либо резервироватся самой программой, т.к. оно было освобождено.

Цитата:
Причём если в tRec все переменные типа string То всё ОК.
Думаю ясно почему так все ок.

Рещение
Выделять память под PCHAR надо, а не просто тыкать куда попало.

Дополнение
Если
Код:
pr: ^TRec;
то помоему это плохой тон потом писать
Код:
pr.s1 :=
тогда уже (pr^).s1
p.s. извените может немного напутал куда ставить оператор разименования, давно дельфи не использую

Последний раз редактировалось BOBAH13; 18.12.2009 в 00:00.
BOBAH13 вне форума Ответить с цитированием
Старый 18.12.2009, 08:21   #4
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

Ладно, попробую. Дааа, работа с указателями, это головная боль. А при pChar счетчик ссылок есть?
-----------
Не работает. Вернее результат другой, но все равно не то.
Код:
      pr^.s1 := pChar(iniFile.ReadString('000', '1', '(S 1---)'));
      pr^.s2 := pChar(iniFile.ReadString('000', '2', '(S 2---)'));
      pr^.s3 := pChar(iniFile.ReadString('000', '3', '(S 3---)'));
      pr^.s4 := pChar(iniFile.ReadString('000', '4', '(S 4---)'));

Последний раз редактировалось Altera; 18.12.2009 в 10:12.
Altera вне форума Ответить с цитированием
Старый 18.12.2009, 10:50   #5
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Цитата:
Сообщение от Altera Посмотреть сообщение
Ладно, попробую. Дааа, работа с указателями, это головная боль. А при pChar счетчик ссылок есть?
-----------
Не работает. Вернее результат другой, но все равно не то.
Код:
      pr^.s1 := pChar(iniFile.ReadString('000', '1', '(S 1---)'));
      pr^.s2 := pChar(iniFile.ReadString('000', '2', '(S 2---)'));
      pr^.s3 := pChar(iniFile.ReadString('000', '3', '(S 3---)'));
      pr^.s4 := pChar(iniFile.ReadString('000', '4', '(S 4---)'));
Я в шоке лично, других слов не могу щас сказать. А то что я распинался по пунктам расписал, Вы решили опустить и вообще не читать ?

Цитата:
А при pChar счетчик ссылок есть?
Что имеется ввиду ? Я не понял. Инкремент/Дикремент чтоли ?
BOBAH13 вне форума Ответить с цитированием
Старый 18.12.2009, 13:10   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

за PChar вы следите сами, счетчика нет.(вы же память выделяете, вы же должны освобождать)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 18.12.2009, 14:40   #7
Dzmitry Loktseu
Пользователь
 
Регистрация: 17.12.2009
Сообщений: 18
По умолчанию

А нафига весь этот гемор, можно сделать проще. Как-нибудь так, например:

Код:
unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs;

type
  TForm4 = class(TForm)
    Button1: TButton;
    lb_Items: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FItems: TObjectList;
  public
    { Public declarations }
  end;

  TItem = class(TObject)

    type
      TParams = record
        Param1, Param2, Param3, Param4: PChar;
      end;

  private
    FParams: TParams;
  public
    constructor Create(AParam1, AParam2, AParam3, AParam4: PChar);
    {  }
    property Params: TParams read FParams write FParams;
  end;

var
  Form4: TForm4;

implementation

uses IniFiles;

{$R *.dfm}

{ TItem }

constructor TItem.Create(AParam1, AParam2, AParam3, AParam4: PChar);
begin
  with FParams do
  begin
    Param1 := AParam1;
    Param2 := AParam2;
    Param3 := AParam3;
    Param4 := AParam4;
  end;
end;

{ TForm4 }

procedure TForm4.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  lb_Items.Clear;
  for I := 0 to FItems.Count - 1 do
    with TItem(FItems[I]).Params do
      lb_Items.Items.Add(Format('[%d]: Param1: %s; Param2: %s; Param3: %s; Param4: %s',
        [I, Param1, Param2, Param3, Param4]));
end;

procedure TForm4.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  FItems := TObjectList.Create;
  with TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini')) do
    try
      FItems.Add(TItem.Create(PChar(ReadString('Params', 'Param1', '')),
        PChar(ReadString('Params', 'Param2', '')),
        PChar(ReadString('Params', 'Param3', '')),
        PChar(ReadString('Params', 'Param4', ''))));
    finally
      Free;
    end;
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
  FItems.Free;
end;

end.
Dzmitry Loktseu вне форума Ответить с цитированием
Старый 18.12.2009, 20:08   #8
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

Ничего не легче.
Реализовали так
Код:
function strToPChar(const S: string): PChar;
var
ASize: Integer;
begin
  ASize := (Length(S) + 1) * SizeOf(Char);
  getMem(result, ASize);
  FillChar(result^, aSize, 0);
  move(PChar(S)^, result^, Length(S) * SizeOf(Char));
end;
Altera вне форума Ответить с цитированием
Старый 18.12.2009, 20:13   #9
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

А размер и состав экзешников не сравнивали?
Компилятор все эти "извраты" должен приводить к одному и тому же виду...
mihali4 вне форума Ответить с цитированием
Старый 18.12.2009, 20:27   #10
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

2mihali4, это вы типа над нами глумитесь?
Цитата:
Компилятор все эти "извраты" должен приводить к одному и тому же виду...
Возможно что так и есть, а может и нет... Во всяком случае меня это мало волнует. несколькими байтами больше или меньше. Главное что бы работало корректно.
Altera вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
c++ считывание с файла. tsergey Помощь студентам 20 24.04.2010 23:30
Создание и считывание .ini файлов Патрон Общие вопросы Delphi 4 21.04.2008 03:25
Проблемы с Ini-файлами Азазель Общие вопросы Delphi 6 08.09.2007 19:24
Access violation на строке вида StrLCopy(PChar(st1),PChar(st2),10); malor Общие вопросы Delphi 1 11.07.2007 13:39
проблемы с INI delphi Общие вопросы Delphi 4 10.04.2007 00:28