C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
FileRead в массив
Serjoga
Отправлено: 25.11.2006, 15:24


Ученик-кочегар

Группа: Участник
Сообщений: 9



Привет всем.
У меня такая проблема: Имеется массив int massiv[100]. Имеется файл Koord.txt в котором записаны числа. Нужно эти числа записать в массив. При попытке сделать это билдер ругается на несоответсвие типов в массиве и переменной куда записываются числа(FileRead(fname, &buff, 1)), тоесть в buff (int buff). Подскажите как это правильно сделать пожалуйста.
BadMan
Отправлено: 25.11.2006, 17:45


Дежурный стрелочник

Группа: Участник
Сообщений: 37



В лоб (если файл двоичный) так:
CODE

//Объявление
int Massiv[100];

// Запись
FileWrite(Handle,Massiv,sizeof(Massiv));

// Чтение
FileRead(Handle,Massiv,sizeof(Massiv));

Но если файл текстовый — надо читать построчно, преобразовывать в число и записывать в массив


Отредактировано BadMan — 25.11.2006, 17:47
Serjoga
Отправлено: 25.11.2006, 17:56


Ученик-кочегар

Группа: Участник
Сообщений: 9



А если у меня в файле много цифр и нужно записывать в массив по 1? Например в massiv[0] первую цифру из файла? В файле несколько строк.
Например:
102030...
111213...
121314...
BadMan
Отправлено: 25.11.2006, 19:11


Дежурный стрелочник

Группа: Участник
Сообщений: 37



QUOTE (Serjoga @ 25.11.2006, 17:56)
... В файле несколько строк...

Почему я и уточнял: файл текстовый или двоичный.
При работе с текстовым файлом такой вариант не пройдет — надо считывать построчно.
Если числа строго одинаковой длины и в каждой строке конкретное количество этих чисел, то можно использовать некое подобие хеширования и позиционировать указатель в файле исходя из номера нужного числа.
Если нет — то тут перебор строк, возможно некое индексирование и т.п.
Для того, чтобы определится со степенью наворотов нужно знать насколько большой файл предполагается обрабатывать — сколько в нем будет чисел.
Serjoga
Отправлено: 25.11.2006, 19:58


Ученик-кочегар

Группа: Участник
Сообщений: 9



Немного обьясню что я хочу сделать.
Есть DrawGrid в нём нужно закрасить некоторые клетки в другой цвет. Координаты этих клеток хочу хранить в отдельном файле. Потом просто через цикл брать эти значения из файла помещать их в массив и закрашивать клетки...вот...Как взять целую строчку я знаю а как посимвольно без понятия
BadMan
Отправлено: 25.11.2006, 20:32


Дежурный стрелочник

Группа: Участник
Сообщений: 37



Тогда можно сделать что-то в этом роде:
CODE

// Структура записывается в начало файла
Typedef struct
{
int ColCells;
// тут можно еще записать всяко разное — цвета и т.п.
} FileHeader;

// Струтура описывает координаты закрашиваемой ячейки
Typedef struct
{
int x_koord;
int y_koord;
} CellCoord;

SaveFile()
{
 FileHeader HFile;
 CellCoord Cell;
 HFile.ColCells = // Количество записываемых ячеек

 // Записали заголовок
 FileWrite(Handle,&HFile,sizeof(HFile));

 // Дальше идем по массиву нужных ячеек (не знаю как он у вас представлен)
 for (i=0;i<размер массива;i++)
 {
   Cell.x_koord = // Столбец из массива
   Cell.y_koord = // Строка из массива

   // Записываем очередной элемент
   FileWrite(Handle,&Cell,sizeof(Cell));
 }
}



Чтение производим аналогично...
Если элементов много, то можно заменить int на word или short
Grigoriy
Отправлено: 25.11.2006, 21:01


Мастер участка

Группа: Участник
Сообщений: 381



Вот функция по формированию массива байтов из файла с именем f с однобайтовыми числами.
Имя файла в этой функции задается нуль-терминальной строкой.
Если исходная строка типа AnsiString, то она преобразуется с помощью свойства c_str()
CODE

int __stdcall ReadCharsNumbersFromFileToArray(char* f, void* m)
{
//f — имя файла с нуль-терминальной строкой
//m — указатель на массив байтов
//В случае неудачи функция возвращает -1
//В случае успеха функция возвращает 0
void* p;
void* r;
unsigned int k;
unsigned long k1;
if ((p=CreateFile(f,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0))==(void*)-1) return -1;
if (k=GetFileSize(p,0))
{
r=GlobalAlloc(0,k);
ReadFile(p,r,k,&k1,0);
asm{
pushad;
cld;
mov esi,r;
mov ecx,k;
mov edi,m;
@c1:
lodsb;
sub al,48;
jl @p1;
cmp al,9;
ja @p1;
stosb;
@p1:loop @c1;
popad;
};
GlobalFree(r);
};
CloseHandle(p);
return 0;
};


Отредактировано Grigoriy — 25.11.2006, 21:06
Shagg
Отправлено: 25.11.2006, 21:31


Дежурный стрелочник

Группа: Участник
Сообщений: 69



а если так?
CODE
struct TCellColor
{
 int x, y, color;
}
void load(char* file_name)
{
 ifstream inf(file_name);
 vector<TCellColor> vCells;
 TCellColor ccl;
 while (inf >> ccl.x >> ccl.y >> ccl.color) vCells.push_back(ccl);
 inf.close();
}


ЗЫ: вопрос Grigoriy'ю. Объясните пожалуйста, почему вы не используете потоки С++, а пользуетесь апишными функциями? Может я чего-то не знаю, просветите.
Serjoga
Отправлено: 25.11.2006, 22:04


Ученик-кочегар

Группа: Участник
Сообщений: 9



Я начал программировать недавно поэтому немного не понимаю smile.gif
У меня массив заполняется -1-цами(он типа integer). Потом эти значения переписываются, но чтобы не писать эту переписку прямо в коде хотел сделать чтение из файла...ну чтобы небыло чего-то подобного:
matrix2[0]=0;
matrix1[1]=2;
matrix2[1]=0;
matrix1[2]=3;
matrix2[2]=0;
matrix1[3]=4;
matrix2[3]=0;
Вот заполнение -1:
for (int i = 0; i < razmer; i++)
{
matrix1[i]=-1;
matrix2[i]=-1;
}
Потом заполняются ячейки:
for (int i=0; i < razmer; i++) {
if (matrix1[i]!=-1) {
tr=DrawGrid1->CellRect(matrix1[i],matrix2[i]);
DrawGrid1->Canvas->Brush->Color=clNavy;
DrawGrid1->Canvas->FillRect(tr);
}
}
Думую можно ограничится одним массивом, но это просто надо переделать код smile.gif

Можно это както полегче и попонятней осуществить? smile.gif
Grigoriy
Отправлено: 26.11.2006, 00:33


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE
ЗЫ: вопрос Grigoriy'ю. Объясните пожалуйста, почему вы не используете потоки С++, а пользуетесь апишными функциями? Может я чего-то не знаю, просветите

Решили "заесть" ? biggrin.gif biggrin.gif
Я использую АПИ потому, что так прикольнее и могу делать все что мне вздумается... в том числе и на асме.
Кроме того, я не пойму правильности кода и его работы пока не переведу его в уме на те же АПИ и работу компьютера.
То есть получается, для того, чтобы я смог написать всеми высшими средствами C++ Builder, мне сначала нужно представить
как программу должен выполнять компьютер, потом подобрать "рифмы" с возможностями высокоуровневых средств, чтобы обойтись без низкоуровневых. Так что так... Shagg.
Shagg
Отправлено: 26.11.2006, 01:04


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Grigoriy: не хотел я ни кого "заедать". Просто я далеко не профи в программировании и хотел узнать может действительно АПИ функции использовать предпочтительнее.
Serjoga:
изучайте STL. vector — это готовый класс массива. точнее шаблон класса
функция раскраски грида может выглядеть так:
CODE
void Paint(TDrawGrid *Grid, vector<TCellColor> vCells)
{
 TRect rect;
 for (vector<TCellColor>::iterator i=vCells.begin(); i != vCells.enf(); i++)
 {
   rect = Grid->CellRect(i->x, i->y);
   Grid->Canvas->Brush->Color = i->color;
   Grid->Canvas->FillRect(rect);
 }
}
Grigoriy
Отправлено: 26.11.2006, 01:49


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE
может действительно АПИ функции использовать предпочтительнее.

Так или иначе, компьютер все равно будет использовать АПИ.
А вот использовать ли АПИ в своем сознании — это решаете вы сами.
BadMan
Отправлено: 26.11.2006, 12:18


Дежурный стрелочник

Группа: Участник
Сообщений: 37



Лично я не вижу никакого смысла в реализации тривиальной задачи чтения из файла в массив через ассемблер или API.
Гораздо проще, читабельнее и быстрее прочитать обычными функциями типа FileRead
Serjoga
Отправлено: 26.11.2006, 12:34


Ученик-кочегар

Группа: Участник
Сообщений: 9



Всем спасибо буду разбирпться.

Вернуться в Вопросы программирования в C++Builder