| 
| 
 | Вопрос # 1 878/ вопрос открыт / | 
 |  Доброго времени суток, уважаемые эксперты!
 Как из текстового файла с множеством строк, заполнить массив так, чтобы каждая строка была отдельный массив из нескольких значений. И вывести информацию в Мемо, для дальнейшего использования.Причем в текстовом файле значения разделенны Табуляцией.
 Заранее огромное спасибо. Файл с текстом прилогаю.
 К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса) 
|  |   Вопрос задал: Felixx (статус: Посетитель)Вопрос отправлен: 5 сентября 2008, 17:30
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, Felixx!Я покажу, как разбить одну строку, а как разбить весь файл - попробуйте догадаться самостоятельно, это очень просто, если использовать TStringList (он как Memo, только не визульный)
 
 var s:string;//одна строка с исходного файла для разбития
     dl:TStringList;
begin
  dl:=TStringList.create;
  try
   dl.delimeter := #9;//код табуляции.
   dl.delimetertext := s;
   //всё, можно пользоваться результатами. например
   //сколко всего элементов нашло
   dl.count
   //Что там храниться в 3 позиции
   dl[2];//незабываем, что счёт с 0 и всё в виде строк. причем кавычки вокруг строк тоже будут убираться
 finally
   dl.free;
 end;
end;
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 5 сентября 2008, 17:58
 Оценка за ответ: 5
 |  
 Мини-форум вопросаВсего сообщений: 19; последнее сообщение — 6 сентября 2008, 16:29; участников в обсуждении: 3. 
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 19:37 [#1]:как объявить массив зависит от того - одинаковое ли количество элементов подразумевается в строках. И еще уточняющий вопрос - что именно и в каком виде Вы хотите выводить в memo? |  
|   | Felixx (статус: Посетитель), 5 сентября 2008, 19:44 [#2]:Если конкретно, то я пытаюсь из этого файла сделать SQL запрос... Сделал следующее:
 В одно мемо загружаю весь файл
 потом по нажатию кнопки выполняю..
 procedure TForm1.Button4Click(Sender: TObject);
 var
 s:string;//одна строка с исходного файла для разбития
 dl:TStringList;
 i:integer;
 begin
 
 for i:=0 to Memo2.Lines.Count-1 do
 begin
 s:= Memo2.Lines[0+i];
 dl:=TStringList.create;
 try
 dl.Delimiter:=#9;
 dl.DelimitedText:=s;
 memo1.Text:=(Memo1.Text+'INSERT INTO `recitems` VALUES');
 memo1.Text:=(Memo1.Text+'('+dl[1]+','+dl[2]+','+dl[8]+','+'0'+');'+#13);
 finally
 dl.free;
 end;
 end;
 end;
 
 Получаются множество запросов в мемо.. и сохраняю в файл.
 
 Но там получается не корректный переход на новую строку после каждого запроса. Подскажите как сделать корректно переход?
 |  
|   | Вадим К (статус: Академик), 5 сентября 2008, 19:52 [#3]:ну зачем писать так хитро memo1.Text:=(Memo1.Text+'('+dl[1]+','+dl[2]+','+dl[8]+','+'0'+');'+#13);
 во первых, надо знать, что под виндовсом перевод строки - это #13#10.
 Но лучше писать так.
 
 var s:string;
begin
...
if dl.count < 9 then ShowMessage('ЧП мирового масштаба, либо просто плохой файл')
else begin
s:='INSERT INTO `recitems` VALUES' +
'('+dl[1]+','+dl[2]+','+dl[8]+','+'0'+');');
Memo1.lines.add(s);
end;Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 19:57 [#4]:Думаю, что лучше сделать следующим образом: перед циклом выполнить: memo1.lines.clear;
 ввести дополнительную переменную s1. В цикле делать:
 s1:='insert into ... values ('+dl[1]+','+...;
 memo1.lines.add(s1);
 Кстати, а почему в запросе нет перечисления полей, которым присваиваются значения? Есть опасность нарваться на неприятность - если порядок полей в таблице не совпадет с порядком перечисления значений.
 |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:00 [#5]:to Вадим К : переменая s уже используется (а то "вопрошающий сделает так как написано"  и получит геморой) |  
|   | Вадим К (статус: Академик), 5 сентября 2008, 20:04 [#6]:и что, будет работать. посмотрите внимательней  После присваивания она уже не нужна и можно использовать снова Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:05 [#7]:to Вадим К:ЧП мирового масштаба не получиться - там стоит try finally end просто строка не добавиться в memo.
 Да и еще to  Felixx: вынесите строки dl:=TStringList.create и dl.free и конструкцию try finally end из цикла и используйте проверку, предложенную Вадим К .
 |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:07 [#8]:to Вадим К:Переменная то уже не нужна, но у Вас написано s:=s+..., то есть все что было в строке s, добавиться в memo |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:07 [#9]:Было написано  Вы поправились |  
|   | Вадим К (статус: Академик), 5 сентября 2008, 20:09 [#10]:to Мережников Андрей Ну раз уж так
  Лучше получить ShowMessage с ругательством, чем просто будет проглочено неверную строку без каких то замечаний.
 Конечно, для релиза эту строку лучше заменить на что то более внятное с выводом номера строки в файле, например.
 А вообще для отладки удобно использовать так называемые "утверждения" - assert
 ----
 Поправился, ибо умею
   Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:15 [#11]:to Вадим К: Про проверку, которую Вы предложили, я уже написал (там где советую вынести создание dl за пределы цикла - зачем переменную много раз создавать, а потом уничтожать? вдруг проц перегреется?  ). На самом деле - зачем лишние тормоза? |  
|   | Felixx (статус: Посетитель), 5 сентября 2008, 20:36 [#12]:Большое спасибо вам за ответы, первую часть того чего хотел реализовал) В конечном результате вышел такой Код:
 
 [code]
 
 procedure TForm1.Button4Click(Sender: TObject);
 var
 s:string;
 dl:TStringList;
 i:integer;
 begin
 
 for i:=0 to Memo2.Lines.Count-1 do
 begin
 s:= Memo2.Lines[0+i];
 dl:=TStringList.create;
 try
 dl.Delimiter:=#9;
 dl.DelimitedText:=s;
 if dl.count < 9 then ShowMessage('Битый файл')
 else
 begin
 s:='INSERT INTO `recitems` VALUES' + '('+dl[1]+','+dl[8]+','+'0'+');';
 Memo1.lines.add(s);
 end;
 finally
 dl.free;
 end;
 end;
 end;
 
 [/code]
 
 Теперь осталось самое сложное думаю..
 например строка:
 INSERT INTO `recitems` VALUES(1,[0(1864)],[4(1869)],0);
 в предпоследнем значении у нас выходит строка [0(1864)],[4(1869)]
 так вот мне нужно что бы то что в скобках [..] писалочь отдеотно в новую строку... например вот так должен был получиться запрос:
 INSERT INTO `recitems` VALUES(1,1666,1864,0,0);
 INSERT INTO `recitems` VALUES(1,1666,1869,4,0);
 
 Это думаю тоже нужно как то в массив впихать ...
 |  
|   | Felixx (статус: Посетитель), 5 сентября 2008, 20:44 [#13]:Поясню, в SQL 1е значение - ID рецепта.
 2е значение - ID Первой вещи для изготовления рецепта.
 3е значение - Количество первой вещи.
 4е значение - если вещ для изготовления рецепта имеет свой рецепт записать его ID , эти ID находятся в dl [2]
 
 Поправочка из вышесказанного... вот правельный запрос:
 INSERT INTO `recitems` VALUES(1,1864,0,0);
 INSERT INTO `recitems` VALUES(1,1869,4,0);
 
 А если например у нас в [..] 5 или 6 вещей требуется то нужно сделать 5-6 запросов для этого ID рецепта..
 Как такое можно реализовать?
 |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 21:57 [#14]:например так: s:='insert into... values('+dl[1]+',[],0)';
 s1:=trim(dl[8]);
 repeat
 x:=pos(']',s1);
 if x=0
 then begin
 s2:=ansireplacestr(s,'[]',s1);
 s1:='';
 end
 else begin
 s3:=copy(s1,2,x-2);
 s1:=copy(s1,x+2,length(s1);//тут надо предусмотреть проверку, чтобы между ] и [ был только один символ
 //разбираем строку s3
 x:=pos('(',s3);
 s4:=leftstr(s3,x-1);
 s3:=rightstr(s3,length(s3)-x);
 x:=pos(')',s3);
 s4:=leftstr(s,x-1)+','+s4;
 s2:=ansireplacestr(s,'[]',s4);
 end;
 memo1.lines.add(s2);
 until s1='';
 
 И все таки - укажите список полей перед values : insert into таблица (список полей) values(список значений); А то переделает кто-нибудь структуру таблицы и всю прогу переписывать
 |  
|   | Felixx (статус: Посетитель), 5 сентября 2008, 22:10 [#15]:Структуру таблицы не переделают, исходный файл тоже))) Программка нужна всего на 1 раз
  
 По сути это из файла клиента игры, мы берем и заполняем таблицу SQL..
 на данный момент реализовал в программе такой вывод SQL:
 
 INSERT INTO `recitems` VALUES(1,1864)],2,0);
 INSERT INTO `recitems` VALUES(1,1869)],2,0);
 INSERT INTO `recitems` VALUES(2,2005)],18,0);
 INSERT INTO `recitems` VALUES(2,1869)],18,0);
 INSERT INTO `recitems` VALUES(2,1870)],18,0);
 INSERT INTO `recitems` VALUES(3,2006)],12,0);
 INSERT INTO `recitems` VALUES(3,1869)],12,0);
 INSERT INTO `recitems` VALUES(3,1872)],12,0);
 INSERT INTO `recitems` VALUES(3,1864)],12,0);
 
 Осталось
 1) Заменить ")]", на" ,"
 2) Огранизовать поиск последнего значения...
 
 Если нужно могу выложить исходники, посмотрите что я там натворил, мож какие получше идеи будут)
 если нужно то выложу...
 |  
|   | Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 22:18 [#16]:заменить )] на запятую можно одной строкой кода: AnsiReplaceStr(memo.text,')]',','); только не забудьте подключить модуль StrUtils;
 "Программка нужна всего на 1 раз" - как знать, а вдруг еще пригодится?
 На будущее советую все таки указывать список полей. Удачи в дальнейшем решении.
 |  
|   | Felixx (статус: Посетитель), 6 сентября 2008, 05:12 [#17]:Всем большое спасибо  вот что у меня получилось... http://plusfile.ru/8003435
 кое что конесчно не реализовал, в том числе проверку на то что с исходного файла нельзя удалять 1ю строку... но принципе работает)
 Может кто - нить что предложит свое?)
 |  
|   | Вадим К (статус: Академик), 6 сентября 2008, 12:23 [#18]:А смысл, если это "одноразовая задача". В таких задачах оправданны любые "грязные трюки", главное, что бы выполнило свою работу. Галочка "подтверждения прочтения" - вселенское зло. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |