imho.ws |
![]() |
![]() |
![]() |
# 1 | ||
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Заполнение массива в С++ Builder из файла "txt"
Существует текстовый файл "file.txt" следующего вида:
Цитата:
Цитата:
![]() |
||
![]() |
![]() |
# 2 |
Member
Регистрация: 02.09.2003
Сообщения: 215
![]() ![]() ![]() |
![]()
не сильно заботясь об быстроте:
Код:
// создаем список TStringList *slFile; slFile = new TStringList; slFile->LoadFromFile(GetCurrentDir()+"\\file.txt"); // заполняем список из файла // обработка for(int iC = 0; iC < slFile->Count; iC++) { AnsiString strTMP = slFile->Strings[iC]; strTMP.Delete(1,strTMP.Pos(";")); // стирается 1ый столбец strTMP.Delete(1,strTMP.Pos(";")); // стирается 2ой столбец strTMP.SubString(1,strTMP.Pos(";") - 1); // значение 3го столбца strTMP.Delete(1,strTMP.Pos(";") + 1); // стирается 3й столбец /* остальные столбцы по аналогии */ strTMP; // последний столбец } delete slFile; // удаляем список
__________________
не могу просто так сидеть, когда другие работают. пойду полежу. Последний раз редактировалось spike; 21.04.2008 в 13:20. |
![]() |
![]() |
# 3 | |||
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
spike, прости меня дурака, но я не всё понял. Разъясни, пожалуйста...
Я понял, что при открытии файла мы заполняем список. Затем пробегаем по каждой строке списка и удаляем содержимое до знака ";". Тем самым удаляем содержимое первых 2 столбцов. А вот что значит строчка Цитата:
Потом мы зачем-то стираем и третий столбец. Цитата:
![]() Строка Цитата:
Когда-то я неплохо программил на Pascal'е и Borland C++, но с тех пор прошло ОЧЕНЬ много времени и я без практики всё позабыл. И сейчас глядя на этот код чувствую себя первокласником... ![]() ![]() |
|||
![]() |
![]() |
# 4 |
СуперМод
IMHO Консультант 2005-2009 Регистрация: 14.08.2002
Адрес: Московская ПЛ, ракетный отс
Пол: Male
Сообщения: 14 515
![]() |
Ну, если уж делать "как положено", то есть с привлечением средств ООП, то нужно создать класс, описывающий формат файла и умеющий считывать его в память (опционально - записывать содержимое памяти обратно в файл того же формата) с функцией-членом, обеспечивающей чтение произвольного элемента.
И при заполнении целевого массива использовать эту функцию со сдвигом на 2 столбца (т.е. 1-й элемент строки целевого массива считывается считывается из 3-го элемента соответствующей "строки" класса). А всю "прозу жизни" (разбор строк файла) упрятывать в этот класс. Если количество строк сильно переменное (скажем, от 10 до 10000) имеет смысл целевой двумерный массив заменить на связанный список указателей на элементы-"строки" (чтобы не выделять априорно лишнюю память и в то же время не оказаться в ситуации, когда выделенная память недостаточна для считывания файла). В общем, очень многое зависит от того, что в дальнейшем планируется делать с целевым массивом... Означает, что ";" в подстроку не попадает (крайним правым символом подстроки-результата этой команды становится символ слева от ";"). На самом деле, данная функция должна стоять в правой части оператора присваивания... ![]() Функция выделения подстроки, что вполне очевидно... Чтобы следующая strTMP.SubString(1,strTMP.Pos(";") - 1); вернула значение четвёртого столбца... Вот здесь мне тоже не совсем понятно, а лезть в мануал за описанием команды лень... Если данная команда - правильная, то почему "+1" нету в команде удаления первых двух столбцов?
__________________
Не засоряйте форум "спасибами"! Для выражения благодарности существуют ПС и репутация! Соблюдайте Правила! Распространенье наше по планете Особенно заметно вдалеке: В общественном парижском туалете Есть надписи на русском языке В. Высоцкий |
![]() |
![]() |
# 6 | |
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Borland, прошу прощения за свою назойливость, но не мог бы ты привести хотя бы примерный код? Я в классах вообще не разбираюсь. Только вчера удалось найти книгу, в которой рассказывается про классы и наследования.
Цитата:
С массивом ничего делаться не будет. В данном случае массив необходим исключительно как хранилище числовых данных, на основе которых потом будет строиться своеобразная диаграмма. |
|
![]() |
![]() |
# 7 | |
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
В конечном итоге с классами не разобрался. Массив заполнил использовав совет spike'а. Только немного изменил код, подогнав под свои нужды.
Сейчас возникла другая трудность. В программе участвуют 10 массивов одинакового размера, со всеми ними будут производиться одни и те же действия, поэтому пришёл к выводу, что нужно написать функцию, как в старом добром "Borland C++" (не Builder), и вызывать её для каждого массива. Для примера: Код:
void vvodmass (int mass[5][5]) //объявляем функцию {int i,j; for (i=0; i<5; i++) for (j-0; j<5; j++) cin>>mass[i][j];} void main() {int a[5][5], b[5][5]; vvodmass (a); //вызываем функцию для массива "a" vvodmass (b); //вызываем функцию для массива "b" } Код:
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void diagramma(int mass[37][5]) {int i,j,otstup; otstup=10; for (i=0; i<35; i++) { Image1->(!Здесь выскакивает ошибка!)Canvas->Brush->Color=(TColor)RGB(0,255,0); Image1->Canvas->Rectangle . . . //дальше идёт процесс рисования на элементе Image1 столбиков диаграммы. //Чтобы не грузить вас формулами, стёр всё ненужное. } } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) {int mass1[37][5],mass2[37][5],mass3[37][5],mass4[37][5],mass5[37][5]; int mass6[37][5],mass7[37][5],mass8[37][5],mass9[37][5],mass10[37][5]; diagramma (mass1); } Цитата:
![]() P.S. Если забыть про остальные массивы, и прописать процесс рисования не как функцию, то диаграмма рисуется просто замечательно. |
|
![]() |
![]() |
# 8 |
Advanced Member
Регистрация: 12.05.2004
Пол: Male
Сообщения: 482
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
у тебя функция diagramma не является методом класса TForm1 и соответственно не может юзать внутренние объекты , коим является Image1
нужно либо функцию определить методом класса: в Unit1.h там где "public: //User decloration" прописать прототип функции, а при описании функции указать void TForm1::diagramma(...), либо передавать в функцию указатель на объект на ряду с остальными параметрами
__________________
Этот мир для таких, как мы, Этот мир обречен на нас, Но реальность не изменить, И живем мы в ней здесь и сейчас. (C) С.Маврин Последний раз редактировалось PhoeniX; 04.06.2008 в 00:14. |
![]() |
![]() |
# 9 |
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
С классами я уже пробовал разбираться, поэтому отбрасываем этот вариант. А что значит передавать в функцию указатель на объект? Везде прописывать "Form1->Image1->..."? Можно хотябы маленький пример для наглядности?
|
![]() |
![]() |
# 10 |
Advanced Member
Регистрация: 12.05.2004
Пол: Male
Сообщения: 482
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
да, так как ты написал тоже сработает в данном конкретном примере, но это имхо не хорошо, делать свои функции зависимыми от глобальных переменных
я говорил о том, что в функцию передавать указательна объект, то есть прототип функции будет выглядеть так: void diagramma(int mass[37][5], TImage *Image1) а вызывать ее соответственно вот так: diagramma (mass1, Image1); опять же в твоем конкретном случае, потому что функция diagramma вызывается из метода класса TForm1, где Image1 определен да и с классом все просто: в нижней панели окна кода находим закладки, среди них unit1.h, переходим туда и в public, там где определяется пользователем пишем void diagramma(int mass[37][5]); а в основном коде (cpp - файл) определяем прототип как void TForm1::diagramma(int mass[37][5]) метод выбирай на свой вкус, судить о правильности и корректности я не буду (ну не считая первого случая, но там мое имхо)
__________________
Этот мир для таких, как мы, Этот мир обречен на нас, Но реальность не изменить, И живем мы в ней здесь и сейчас. (C) С.Маврин |
![]() |
![]() |
# 11 | |
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Очередная проблема: Создаю "Form2" и заполняю на ней два поля "Edit". После закрытия этой формы нужно вернуть значения этих полей. Но командра "return" не желает работать. Выдаётся ошибка:
Цитата:
Код:
void __fastcall TForm2::Button1Click(TObject *Sender) {AnsiString author, nazvanie; author=Edit1->Text; nazvanie=Edit2->Text; Form2->Close(); return author,nazvanie; } |
|
![]() |
![]() |
# 12 |
СуперМод
IMHO Консультант 2005-2009 Регистрация: 14.08.2002
Адрес: Московская ПЛ, ракетный отс
Пол: Male
Сообщения: 14 515
![]() |
Это ж самые основы программирования!!!
return ВСЕГДА возвращает ОДНО значение. К тому же, насколько я понимаю описание твоей функции, она вообще не может возвращать значений ибо void (что вполне логично для обработчика клика). Если нужно вернуть несколько значений - можно, например, изменять параметры, но для этого в Си необходимо передавать их в функцию по ссылке или указателю. Или возвращаемым значением функции делать экземпляр класса, содержащий необходимые значения внутри с соответствующей модификацией самой функции (хотя в качестве обработчика клика этот подход не годится).
__________________
Не засоряйте форум "спасибами"! Для выражения благодарности существуют ПС и репутация! Соблюдайте Правила! Распространенье наше по планете Особенно заметно вдалеке: В общественном парижском туалете Есть надписи на русском языке В. Высоцкий |
![]() |
![]() |
# 13 | ||
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Цитата:
К тому же, я прописал функцию рисования диаграммы, как сказал PhoeniX (мне нужна была функция, потому что придётся постоянно рисовать диаграмму, но с разным масштабом/с разных массивов), но вызвать её могу только при нажатии на "Button1", потому что я объявил массивы именно при нажании на эту кнопку. Код:
void __fastcall TForm1::Button1Click(TObject *Sender) {int mass1[37][5],mass2[37][5],mass3[37][5],mass4[37][5],mass5[37][5]; int mass6[37][5],mass7[37][5],mass8[37][5],mass9[37][5],mass10[37][5]; Цитата:
P.S. Извините, что задаю так много вопросов и часто - очень глупых, но мне очень нужна ваша помощь. ![]() ![]() |
||
![]() |
![]() |
# 15 |
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
В общем выяснил как объявлять переменные глобально и объявил соответствующим способом все 10 массивов и нужные для работы переменные. Программа отлично заработала. Теперь мне интересен другой вопрос: У меня в программе есть поток событий:
Код:
{import (mass1); Form2->Show(); ComboBox11->Items->Delete(0); ComboBox11->Items->Insert(0,"Имя диаграммы"); masshtab=(max*100/mass1[35][4]); diagramma (mass1, masshtab, Image1, 310, 300);} |
![]() |
![]() |
# 17 |
Full Member
Регистрация: 30.07.2004
Адрес: Санкт-Петербург
Пол: Male
Сообщения: 544
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
ЕЖ, то, что надо!
![]() Возникла очередная интересная проблемка: Существует каталог, где расположен exe'шник программы и внутри него папка Base, в которой хранятся текстовые файлы с вышеописанными данными. В программе присутствует 2 кнопки: одна - импорт файла папки "Base", а другая вызывает OpenDialog. Если сначала импортировать файлы из папки "Base" (путь прописан "Base/<имя текстового файла>"), то всё работает "на Ура". Но стоит нажать другую кнопку и указать текстовый файл из левого каталога, то видимо рабочий каталог меняется на последний используемый, и из базы данных уже ничего не получить (<левый каталог>/Base/<имя текстового файла> - не найдено). В идеале было бы не плохо сначала определить путь текущего каталога (где находится exe'шник) и запонимть его (пускай даже в переменной типа String). А перед нажатием на кнопку импортирования файла из папки "Base" изменить путь рабочего каталога на изначальный. Но я нигде не могу найти существуют-ли команды определения и смены рабочего каталога. Помогите, пожалуйста! |
![]() |
![]() |
# 19 |
Newbie
Регистрация: 11.06.2008
Сообщения: 25
![]() ![]() |
Path:=Application.ExeName; // полный путь и название запущенной программы
Path:=ExtractFileDir(Path); // отбрасываем название программы. Остается путь. if Path[Length(Path)]<>'\' then Path:=Path+'\'; // если последний символ не \ то добавить его {Последняя строка нужна для присвоения последнего символа '\', потому что при обрезке файла 'C:\PROG.EXE' получим 'C:\', а при обрезке 'C:\WINDOWS\PROG.EXE' получим 'C:\WINDOWS'} |
![]() |