DBGrid
мое первое сообщение не сохранилось на форуме - интересно почему? Или его кто-то удалил?
Посему, по второму разу.
1) надо подсчитать обычную сумму во всех полях DBGrida, однако этот вот код почему-то не работает
long int a;
[COLOR=blue]
Table2->First();
while(!Table2->Eof)
{
a = Table1->FieldByName("Paid")->AsInteger;
a = a + a;
Table2->Next();
}
Table2->First();
StaticTotal->Caption = IntToStr(a);
[/COLOR]
2) вопрос по вложению ф-ций - есть скажем набор операторов, которые должны выполняться довольно часто. Я их объединяю в одну ф-цию. Однако при клике на какой-то кнопке таких ф-ций довольно много, и часть из них повторяется, потому возникает идея их объединить в ф-цию тоже. Вопрос - насколько эффективно такое вложение функций? То есть, каков предел, и самое главное, будет ли от этого работать быстрее программа?
Так что при таком объединении ты ускоришь не время работы программы, а свое рабочее время..
Вопрос - насколько эффективно такое вложение функций?
Эффективность проявляется в следующем: если в одной из функций есть баг, достаточно его исправить в ней, и больше он повторяться не будет. Если же код растворен в теле программы, выловить все ошибки будет очень трудно.
Эффективность проявляется в следующем: если в одной из функций есть баг, достаточно его исправить в ней, и больше он повторяться не будет. Если же код растворен в теле программы, выловить все ошибки будет очень трудно.
Спасибо, а как несчет первого? :P
И кстати, по поводу второго - я имел в виду не операторы, из которых составляются функции, а функции, из которых составляются функции, причем в многоярусном варианте...
Hi there,
мое первое сообщение не сохранилось на форуме - интересно почему? Или его кто-то удалил?
Посему, по второму разу.
1) надо подсчитать обычную сумму во всех полях DBGrida, однако этот вот код почему-то не работает
long int a;
[COLOR=blue]
Table2->First();
while(!Table2->Eof)
{
a = Table1->FieldByName("Paid")->AsInteger;
a = a + a;
Table2->Next();
}
Table2->First();
StaticTotal->Caption = IntToStr(a);
[/COLOR]
Как я понимаю, код, вообще-то, должен быть примерно таким:
// long int имеет ту же размерность, что и int,
// а значит, может произойти переполнение.
// Следовательно, используем __int64
TIntegerField *Paid = dynamic_cast<TIntegerField *>(Table1->FieldByName("Paid"));
// Проверку на *Paid == NULL опускаем,
// будем считать, что "Paid" заведомо всегда целочисленное.
Table2->First();
while(!Table2->Eof)
{
a += Paid->AsInteger;
Table2->Next();
}
Table2->First();
StaticTotal->Caption = IntToStr(a);
Спасибо, а как несчет первого? :P
Или первая задача сформулирована некорректно, или одно из двух.
1) надо подсчитать обычную сумму во всех полях DBGrida, однако этот вот код почему-то не работает
Стоит задача суммирования по полям, а приведенный код выполняет суммирование по записям, да еще неправильно (строка "a = a + a" все портит).
Функции и есть разновидность операторов. Это операторы, описанные программистом, т. е. тобой. Структурная теорема верна и для них.
Грамотно написанная программа состоит из большого числа функций по десять-двадцать строк. Неспроста же объектно-ориентированное программирование появилось.
Или первая задача сформулирована некорректно, или одно из двух.
Стоит задача суммирования по полям, а приведенный код выполняет суммирование по записям, да еще неправильно (строка "a = a + a" все портит).
Функции и есть разновидность операторов. Это операторы, описанные программистом, т. е. тобой. Структурная теорема верна и для них.
Грамотно написанная программа состоит из большого числа функций по десять-двадцать строк. Неспроста же объектно-ориентированное программирование появилось.
Да-да, я не вполне точно выразился, имелось в виду сумма по записям - вертикально (сумму по полям можно сделать обычным CalcFields)
Как я понимаю, код, вообще-то, должен быть примерно таким:
// long int имеет ту же размерность, что и int,
// а значит, может произойти переполнение.
// Следовательно, используем __int64
TIntegerField *Paid = dynamic_cast<TIntegerField *>(Table1->FieldByName("Paid"));
// Проверку на *Paid == NULL опускаем,
// будем считать, что "Paid" заведомо всегда целочисленное.
Table2->First();
while(!Table2->Eof)
{
a += Paid->AsInteger;
Table2->Next();
}
Table2->First();
StaticTotal->Caption = IntToStr(a);
Спасибо, но честно говоря, этот код не работает. И потом. Можно объяснить причину динамического, если я правильно понял, создания поля Paid, которое уже есть?
То, что значение поля Paid всегда больше нуля, подразумевается.
Спасибо, но честно говоря, этот код не работает. И потом. Можно объяснить причину динамического, если я правильно понял, создания поля Paid, которое уже есть?
То, что значение поля Paid всегда больше нуля, подразумевается.
Честно говоря я давно на Билдере уже не писал ничего... Далее по существу...
Это не динамическое создание, а cast, т.е. динамическое приведение указателя одного типа к другому...
Далее, суммирование я бы точно бы так не делал, лучше всего использовать TQuery и что-то типа "SELECT SUM(Paid) FROM ...... "
Спасибо, но честно говоря, этот код не работает. И потом. Можно объяснить причину динамического, если я правильно понял, создания поля Paid, которое уже есть?
То, что значение поля Paid всегда больше нуля, подразумевается.
1. Код я, конечно, не тестировал. И всё-таки, что значит: "Не работает"? Есть сообщения об ошибках на этапе компиляции или линковании, вылетает по run-time exception или всё работает, но выводит неверный ответ?
2. Сейчас я не поленился и протестировал. Не считая опечатки Table1->FieldByName("Paid") ---> заменить на Table2->FieldByName("Paid") всё нормально, ответ даёт правильный.
3. Объясняю. В твоём случае в цикле происходит примерно следующее: у Table2 вызывается метод FieldByName, который ищет по списку полей нужное нам и приводит его к типу TFIeld* (а было TIntegerField*); FieldByName возврацает TField*, у которого вызывается метод AsInteger, который приводит TField* к TIntegerField и возвращает целое значение. И так каждую итерацию. Я один раз перед началом цикла формирую ссылочку на нужное мне поле с нужным мне типом и экономлю кучу тактов процессора, которые можно использовать в другом месте. :) Почему я акцетировал внимание на отсутствующей проверке указателя Paid на NULL. Если у нас неизвестная нам таблица (в которой всё-же есть поле Paid), и данное поле там имеет тип не Integer, а, скажем, String, то, понятно, к типу TIntegerField* оно не приведётся, и конструкция dynamic_cast<TIntegerField *>(Table2->FieldByName("Paid")) возвратит NULL. Соответственно, ничего работать не будет.
Кстати, поскольку у нас объект Paid уже TIntegerField*, можно использовать на Paid->AsInteger, а Paid->Value.
Честно говоря я давно на Билдере уже не писал ничего... Далее по существу...
Это не динамическое создание, а cast, т.е. динамическое приведение указателя одного типа к другому...
Далее, суммирование я бы точно бы так не делал, лучше всего использовать TQuery и что-то типа "SELECT SUM(Paid) FROM ...... "
Если мне надо просуммировать, я действительно выполняю запрос "SELECT SUM(Paid) FROM ...... ".
Но, во-первых, возможно, использовать человеку TQuery может не позволять религия ;); во-вторых, может быть, нужна более сложная обработка значений поля, которую не может предоставить BDE с его убогой версией SQL, автор немножко упростил задачу, приведя не этот сложный алгоритм обработки, а всего лишь суммирование.
Если мне надо просуммировать, я действительно выполняю запрос "SELECT SUM(Paid) FROM ...... ".
Но, во-первых, возможно, использовать человеку TQuery может не позволять религия ;); во-вторых, может быть, нужна более сложная обработка значений поля, которую не может предоставить BDE с его убогой версией SQL, автор немножко упростил задачу, приведя не этот сложный алгоритм обработки, а всего лишь суммирование.
И все-таки оно не работает. Может быть дело в том, что у меня обычная локальная БД? Не помню, говорил я это или нет.
А сообщение выдается такое - Project1 raised exception class EAccessViolation with message 'Access violation at address 00402177 in module Project1.exe' Read of address 00000000. Process stoped.
:{ :{
И все-таки оно не работает. Может быть дело в том, что у меня обычная локальная БД? Не помню, говорил я это или нет.
А сообщение выдается такое - Project1 raised exception class EAccessViolation with message 'Access violation at address 00402177 in module Project1.exe' Read of address 00000000. Process stoped.
:{ :{
Убедись, что поле Paid в табличке действительно целочисленое, скопируй код и нужные ресурсы в новый проект и убедись, что ошибка не в моём коде, а где-то в твоём. :D Или пройдись отладчиком, найди, где возникает ошибка.
Ошибка Access Voшation записи/чтения по адресу 0 означает, что ты пытаешься работать с указателем, который NULL.
Убедись, что поле Paid в табличке действительно целочисленое, скопируй код и нужные ресурсы в новый проект и убедись, что ошибка не в моём коде, а где-то в твоём. :D Или пройдись отладчиком, найди, где возникает ошибка.
Ошибка Access Voшation записи/чтения по адресу 0 означает, что ты пытаешься работать с указателем, который NULL.
Dear Plisteron, спасибо, наконец-то все заработало.
Однако, конечный код выглядит так
[COLOR=blue]
void __fastcall TForm1::CalcSum()
{
__int64 a;
a = 0;
Table2->First();
while(!Table2->Eof)
{
a += Table2->FieldByName("Paid")->AsInteger;
Table2->Next();
}
Table2->First();
StaticTotal->Caption = IntToStr(a);
}
//-----------------------------------------------
[/COLOR]
:D :D :D :D :D :D