При добавлении записей в таблицу dBase выдает ошибку!?

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Ответить
Vet_chv
Сообщения: 17
Зарегистрирован: 16 июн 2006, 13:04
Контактная информация:

Помогите разобраться с глюком. Читаю данные из тхт файла построчно и записываю их в таблицу dBase. После добавления нескольких записей выдает ошибку Invalid pointer operation. Не могу понять в чем причина.

Dbf1.TableName:= ifl;
Dbf1.FieldDefs.Add('MES',ftSmallInt,0,false);
Dbf1.FieldDefs.Add('NSC',ftInteger,0,true);
Dbf1.FieldDefs.Add('FIO',ftString,50,true);
Dbf1.FieldDefs.Add('SUMMA',ftFloat,0,true);
Dbf1.CreateTable;
Dbf1.Active:= true;
Dbf1.Edit;

While not Eof(f) do
begin
readln(f,s);
Dbf1.FieldByName('MES').AsInteger:= mes;
Dbf1.FieldByName('NSC').AsInteger:= strtoint(prov(copy(s,15,5)));
Dbf1.FieldByName('FIO').AsString:= TrimRight(copy(s,46,100));
Dbf1.FieldByName('SUMMA').AsFloat:= StrTofloat(copy(s,39,7))/100;
Dbf1.Append;
kz:= kz+1;
end;


kz - подсчитывает количество свормировавшихся записей в таблице.
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Перед разбором строки, считанной readln(f,s), проверяй ее длину.
Vet_chv
Сообщения: 17
Зарегистрирован: 16 июн 2006, 13:04
Контактная информация:

Спасибо за подсказку. Только что именно значит проверять длину: считать её длину? Или думаешь, что строка может оказаться слишком длинной? Дело в том что тхт-файл чётко определенной структуры, все строки одной длины.
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Скорее слишком короткой: представь, что в конце стоит лишний перевод строки - Eof(f) вернет True, а readln(f,s) считает пустую строку...
Я бы не полагался на структуру файла.
Vet_chv
Сообщения: 17
Зарегистрирован: 16 июн 2006, 13:04
Контактная информация:

Проверял, версия не подтвердилась. Кроме того, иногда ошибка выскакивает на разных записях (то их получается допустим 23 то 27). :(

Привожу полный код, может что другое обнаружишь. Спасибо за помощь.

Код: Выделить всё

function prov(ss:string): string;
  var
  p: string;
  j: integer;
  c: array[0..4] of char;
  spec: set of char;
  begin
    p:= ss;
    spec:= ['\','/','-'];
    strpcopy(c,p);
   for j:= 1 to length(c) do
    begin
     if c[j] in spec then
      begin
       Result:= '0';
       break;
      end
     else Result:= ss;
    end;
  end;


procedure TForm1.Button1Click(Sender: TObject);
var
 f: TextFile;
 i,mes,kz: integer;
 s,zsum,ifl: string;
begin
kz:= 0;
 For i:= 0 to FIleListBox1.Items.Count-1 do
    begin
     AssignFile(f, FileListBox1.Items.Strings[i]);
     Reset(f);
     readln(f,s);
     ifl:= copy(s,2,3)+'.dbf';
     mes:= strtoint(copy(s,19,2));
   if length(inttostr(FileListBox1.Items.Count)) = 2 then
     ifl:= 'P'+inttostr(FileListBox1.Items.Count)+copy(s,19,2)+ifl
        else ifl:= 'P'+'0'+inttostr(FIleListBox1.Items.Count)+copy(s,19,2)+ifl;
     zsum:= copy(s,78,3)+' '+copy(s,81,3)+','+copy(s,84,2);
   if copy(zsum,1,2) = '00' then zsum:= copy(zsum,3,8)
       else zsum:= copy(zsum,2,9);
     Label4.Caption:= 'Çàãàëüíà ñóìà: '+zsum;

Dbf1.TableName:= ifl;
Dbf1.FieldDefs.Add('MES',ftSmallInt,0,false);
Dbf1.FieldDefs.Add('NSC',ftInteger,0,true);
Dbf1.FieldDefs.Add('FIO',ftString,50,true);
Dbf1.FieldDefs.Add('SUMMA',ftFloat,0,true);
Dbf1.CreateTable;
Dbf1.Active:= true;
Dbf1.Edit;

While not Eof(f) do
  begin
   readln(f,s);
Dbf1.FieldByName('MES').AsInteger:= mes;
Dbf1.FieldByName('NSC').AsInteger:= strtoint(prov(copy(s,15,5)));
ShowMessage(inttostr(length(TrimRight(copy(s,46,100)))));
Dbf1.FieldByName('FIO').AsString:= TrimRight(copy(s,46,100));
Dbf1.FieldByName('SUMMA').AsFloat:= StrTofloat(copy(s,39,7))/100;
Dbf1.Append;
kz:= kz+1;
  end;

Dbf1.Active:= false;
Label3.Caption:= 'ʳëüê³ñòü çàïèñ³â: '+inttostr(kz);
end;
end;

Vet_chv
Сообщения: 17
Зарегистрирован: 16 июн 2006, 13:04
Контактная информация:

При ошибке компилятор указывает на строку
Dbf1.FieldByName('NSC').AsInteger:= strtoint(prov(copy(s,15,5)));
Возможно, проблема в функции prov, только не разберу какая.
Vet_chv
Сообщения: 17
Зарегистрирован: 16 июн 2006, 13:04
Контактная информация:

Ещё раз убеждаюсь в одной истине: обсуждение проблемы с другим упорядочивает мысли!
В функии prov не нужно было строку загонять в массив, всего-то на всего. :lol:
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Я бы добавил: строка Result:= '0' в ней выглядит сомнительно :)
Аватара пользователя
Игорь Акопян
Сообщения: 1440
Зарегистрирован: 13 окт 2004, 17:11
Откуда: СПБ
Контактная информация:

проверить наличие в строке подстроки удобнее через Pos ;)
имхо проблема именно в длинне строки...
Если строка у тебя будет 17 символов - функция copy(s,15,5) вернёт последние 2 символа
и ещё: в хэлпе про StrPCopy - The destination buffer must have room for at least Length(Source)+1 characters.
Изображение
Vet_chv
Сообщения: 17
Зарегистрирован: 16 июн 2006, 13:04
Контактная информация:

'строка Result:= '0' в ней выглядит сомнительно'

Не а! Дело в том, что я пишу конвертер txt->dbf. У нас тут есть какая-то досовская утилитка, которая это делает (но она ужасно неудобна, и далеко не совершенна). А я пишу её аналог под Win. В файле dbf поле NSC имеет числовой тип, а в тхт файле, в значениях для этого поля втречаются спец знаки (я их включил в set). Досовская прога в таких случаях ставит 0. Чем нужно было бы заменять неизвестно. Но такой вариант позволяет работать в дальнейшем. :wink:
Ответить