![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Файл и динамический массив
d3777 © (2006-04-05 18:07:00)есть текстовый файл. в нём матрица чисел(несколько столбцов- m, и много-много строк - n). вопрос: как динамически выделить под него массив, точнее как определить размер этого массива?
для определения кол-ва стобцов делал read(F, W[m]) до конца первой строки - но это помоему не выход.
а со строками вообще не понял как. просто устанавливал с запасом. но это тоже не выход: так как кол-во строк от файла к фалу изменяется от 2 до 1048576.
заранее спасибо
Юрий Зотов (2006-04-06 13:16:00) [1]> Algol (06.04.06 12:31) [38]
Кстати, по той же причине, из кода выкинуто все, не относящееся к сабжу напрямую. В рабочей же программе надо предусмотреть, чтобы даже при возникновении ошибки освобождались все ресурсы. В частности, чтобы закрывался файл.
Юрий Зотов (2006-04-06 13:10:00) [2]> Algol (06.04.06 12:31) [38]
Это пример, а не рабочая программа. Основное требование к примеру - он должен быть как можно более понятным. Так он и написан.
Algol (2006-04-06 12:31:00) [3]2ЮЗ
А зачем вы каждый раз открываете/закрываете файл?
Мне кажется во-первых это лишние операции, занимающие время, а во-вторых, это может помешать операционке оптимизировать доступ к файлу, при повторном его чтении. Я не прав?
Deka (2006-04-06 11:25:00) [4]Можно организовать одномерные массивы соотвествующие строкам. Такой массив создается при чтении строки. А сам массив добалять в список. При таком решении получится список массивов и однопроходная схема загрузки. Думаю что с памятью больших накладок не получится.
Можно еще попробовать определившись со структурой файла отобразить часть его в память и работать с ним как с готовым массивом.
Хотя наверное это вариант слишком сложен. Из пушки по воробьям, однако. Зато решается проблема нехватки памяти при большом файле.
Anatoly Podgoretsky (2006-04-06 09:05:00) [5]d3777 © (06.04.06 00:57) [26]
"В конце концов размер файла деленый на количество элементов в строке * 2 (один символ на пробел)"
может количество символов в строке подсчитывать?
но попадаются и односимвольные элементы массива (например просто 0),
0 один символ, разделитель 1 символ, итого два и еще есть запас за счет разделителей строк. Так ты не мудри а прочитай первые сто (или сколько считаешь нужным) строк, аппроксимируй и результат умножь на коэффициент.
Юрий Зотов © (06.04.06 01:51) [27]
Не то слово
Германн (2006-04-06 02:32:00) [6]
> d3777 © (06.04.06 02:27) [34]
>
> в ручную надо страницу периодически обновлять
Через сколько ms советуешь её обновлять?
d3777 (2006-04-06 02:27:00) [7]в ручную надо страницу периодически обновлять
Германн (2006-04-06 02:18:00) [8]Оп-ля :(
А как это? Прочитал, ответил. И узнал, что уже в прошлом веке все прочитали и кто-то ответил???
Германн (2006-04-06 02:13:00) [9]
> d3777 © (06.04.06 02:01) [28]
>
> 2Юрий Зотов ОГРОМНЕЙШЕЕ СПАСИБО за этот листинг!!!!!!!!
> !!!!!!!!!!!!!!!!!
>
> но только вот есть по моему маленькая загвоздка - столбцы
> могут быть разделены несколькими пробелами :(
>
А ты уверен, что загвоздка есть?
По-моему строка while (i <= Length(S)) and (S[i] in Separators) do
Inc(i);
её решает.
d3777 (2006-04-06 02:12:00) [10]ещё раз спасибо!!!!! и ещё раз извиняюсь за свою невнимательность
Юрий Зотов (2006-04-06 02:07:00) [11]> d3777 © (06.04.06 02:01) [28]
Хоть ста пробелами, тысячей табуляторов и еще чем угодно в каком угодно количестве, хоть одновременно, хоть в любом наборе.
Внимательно посмотрите код, там есть цикл:
while (i <= Length(S)) and (S[i] in Separators) do
Inc(i);
который пропустит любой набор любых разделителей в любом сочетании.
d3777 (2006-04-06 02:04:00) [12]извиняюсь!!!!!!!!!! разобрался!!!!!! нет проблем :)
d3777 (2006-04-06 02:01:00) [13]2Юрий Зотов ОГРОМНЕЙШЕЕ СПАСИБО за этот листинг!!!!!!!!!!!!!!!!!!!!!!!!!
но только вот есть по моему маленькая загвоздка - столбцы могут быть разделены несколькими пробелами :(
Юрий Зотов (2006-04-06 01:51:00) [14]
procedure TForm1.FormCreate(Sender: TObject);
const
FileName = 'C:\Numbers.txt';
Separators = [ #9, ' ']; // Добавьте сюда любые возможные разделители
var
F: TextFile;
i, j, M, N: integer;
S: string;
A: array of array of integer;
begin
// 1. Создаем файл, не вручную же его набивать
AssignFile(F, FileName);
Rewrite(F);
for i := 0 to 99 do // 100 строк
begin
for j := 0 to 8 do // 9 столбцов
Write(F, i, j, ' ');
WriteLn(F, i, 9) // и еще один, 10-й столбец
end;
CloseFile(F);
// 2. Определяем кол-во столбцов N
AssignFile(F, FileName);
Reset(F);
ReadLn(F, S);
i := 1;
N := 0;
repeat
while (i <= Length(S)) and (S[i] in Separators) do
Inc(i);
if i <= Length(S) then
begin
Inc(N);
while (i <= Length(S)) and not (S[i] in Separators) do
Inc(i)
end
until
i > Length(S);
// 3. Определяем кол-во строк M
M := 1;
while not EoF(F) do
begin
ReadLn(F, S);
Inc(M)
end;
CloseFile(F);
// 4. Заполняем массив повторным чтением файла.
AssignFile(F, FileName);
Reset(F);
SetLength(A, M, N);
for i := 0 to M - 1 do
begin
for j := 0 to N - 1 do
Read(F, A[i, j]);
ReadLn(F)
end;
CloseFile(F)
end;
И какие проблемы? Задачка для школьников, как видите.
d3777 (2006-04-06 00:57:00) [15]2Anatoly Podgoretsky
Вот это не очень понятно:
"В конце концов размер файла деленый на количество элементов в строке * 2 (один символ на пробел)"
может количество символов в строке подсчитывать?
но попадаются и односимвольные элементы массива (например просто 0),
но наверно коэффициент запаса всё сгладит.......
З.Ы. вот я и пытаюсь найти этот разумный алгоритм :)
Джо (2006-04-06 00:47:00) [16]> и вообще, как определить вдруг там не таб, а несколько
> пробелов?
Символ табулятора имеет код 9, пробела — 32.
Anatoly Podgoretsky (2006-04-06 00:45:00) [17]Тогда аппроксимирование размера файла на количество строк, например по первым ста строкам с запасом на ошибку, например умножить расчетную величину на 1.3-1.5 и обрезанием по окончанию. Пересылки не будет, перераспределения не будет. Формат файла у тебя характерный длина чисел меняется незначительно. В конце концов размер файла деленый на количество элементов в строке * 2 (один символ на пробел), сработает даже для односимволным чисел. Все что нужно это избежать перераспределение памяти в процессе чтения файла. Будет максимальная скорость и не будет резкого расхода памяти при перераспределении при каждой иттерации. Просто нужен разумный алгоритм.
d3777 (2006-04-06 00:20:00) [18]2Anatoly Podgoretsky
уже привёл в другом месте :)
Anatoly Podgoretsky (2006-04-06 00:18:00) [19]Привел бы формат файла, строк так 10 и максимальный предполагаемый размер файла. А то чего гадать.
d3777 (2006-04-06 00:16:00) [20]замерил.........хех.............практика показала что второй вариант отметается сразу же (только у меня значения у первого около 1000тиков, у второго около 20000)
а иеперь глупый вопрос (просто никогда этим раньше не занимался):
1. Читаем первую строку целиком в строчную переменную S. Элементарный парсинг этой строки даст кол-во столбцов в массиве (кол-во разделителей плюс единица).
реализацию вот этого. точнее как табы искать в строке? и вообще, как определить вдруг там не таб, а несколько пробелов?