Перейти к содержанию
СофтФорум - всё о компьютерах и не только

Заказы "Сделайте все за меня"


Рекомендуемые сообщения

Иазяв

"Пожалуйста, не ругайтесь. Хочу я так сделать. Мне хочется узнать, а можно ли так"

А что тут ругаться? Это же не черная магия. Это строительство из кубиков. Как в детском саду.

Правда, из кубиков и брусков можно такую головоломку соорудить... Поэтому в чужих программах куда труднее разбираться, чем в собственных.

"Пытаюсь понять стек. Хочу узнать, может ли один элемент стека содержат несколько различных данных. " А что его понимать? Опять ты ищешь там, где не спрятано, как было с указателями. Стек - это стопка подносов в столовой самообслуживания. Отсюда его название, отсюда и его работа. Можно поместить поднос наверх, можно посмотреть на верхний поднос, можно снять поднос. Это все.

В программе стек - это цепочка данных, в нее можно добавить элемент данных, можно посмотреть его содержимое, можно удалить. Суть в том, что у тебя предполагается наличие доступа только к верхнему элементу стека.

Элементом стека может быть что угодно - хоть число, хоть строка, хоть сложная структура данных, хоть другой стек.

Как соорудить стек? Можно на основе массива. Заполняешь потихоньку массив и каждый раз запоминаешь адрес последнего элемента. Доступ у тебя предполагается только к последнему элементу. Конечсно, раз ты знаешь, что это массив, ты можешь использовать индекс любого из его элементов, сортировать этот массив, переворачивать его вверх ногами и делать с ним что угодно, но это потому что ты знаешь внутреннюю структуру твоего стека - это на самом деле массив и с ним можно работать и как с массивом, а не как со стеком.

Если у тебя просто стек, о внутренней структуре которого ты ничего не знаешь, то это "вещь в себе", ты можешь с ним делать только то, что разрешено для стека - читай выше. Так что извлечь из середины стека что-то можно, только извлеча (или извлекя? хм, Чуду-юду я и так победю ;) ) сначала из него все элементы до нужного. Отсортировать в нем элементы тоже нельзя. Ну, теоретически можно гонять элементы между двумя стеками, смотря на пару верхних элементов стеков и при необходимости меняя их местами, но это больше походит на игру в "Ханойскую башню". Считается, что когда в Бенаресе жрецы закончат эту игру с 64 элементами, наступит конец света. Конечно, вооружив этих жрецов компьютерами, конец света можно ускорить ;). На похожую тему есть прелестный рассказ Артура Кларка "Девять миллиардов имен бога".

У тебя стек сделан на основе списка. Зная это, к элементу в его середине ты можешь добраться, работая с ним как со списком. Но это ты уже фактически работаешь не со стеком, а с выбранным тобой его внутренним представлением.

А в стандартной библиотеке STL есть стек, но ты ничего не знаешь о его внутренней структуре, и для него не предусмотрено функций ни для доступа к элементу в середине, ни для его сортировки. И если ты даже разберешься, как он устроен в этом варианте библиотеки STL и сможешь использовать его внутреннее устройство напрямую, то нет никакой гарантии, что с другим компилятором твоя программа будет работать. Стеку - только стеково ;)

Хотя, конечно, ты всегда можешь самостоятельно сделать свою структуру данных, которая будет работать как стек плюс какие-то еще функции - но это будет уже не стек, а "расширенный стек", нестандартная структура данных.

Так, вернемся к твоей реализации стека. Память для его элементов выделяется динамически, где они в памяти будут, никто не знает. Добраться до нужного элемента сразу невозможно, но поскольку на самом деле твой стек - список, можно добраться до нужного элемента, идя по списку.

Дополним твою программу этой возможностью (перепишу только конец программы, в начале ничего не меняется):

void Print ()	 {	   TNode *Current = First;	   while (Current)	   {			  Current->Print();			  Current = Current->Next;	   }	 }void PrintK (int k)	 {	   TNode *Cur=First;	   for(int i=0;i<k;i++)Cur=Cur->Next;	   Cur->Print();	 }};int main(){srand (time(0));const int s = 10;  TStack *Stack = new TStack();  for (int i = 0; i < s; i++)  {short name = i;char symbol = i + 48;Stack->Push (new TNode(i, name, symbol));    }    Stack->PrintK(2);  cout<<endl;  Stack->Print();  delete Stack;}

Тут я добавил функцию PrintK(int k), которая печатает элемент, отстоящий на k от вершины стека. Вызываем ее после заполнения стека, для примера с k, равным 2. Если делать не "для себя", то надо было бы дополнить эту функцию проверкой, не требуем ли мы элемент уже за пределами стека и выдачей в таком случае сообщения, но все это нам в примере не нужно.

Заодно я несколько упростил тестовую программу - зачем проверять работу на ста элементах, хватит и десяти, зато все на виду. Сначала выводим результат работы PrintK(2), потом весь стек целиком.

Только помни, что это мы работаем не со стеком - стек, по определению, операции чтения элемента в середине не допускает - а со списком, на основе которого реализован твой стек.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Тролль

Какой же Вы умный!

А что тут ругаться?

Код корявый. Стыдно. У Вас он всегда такой замечательный. А еще я прочитала в лукморье про быдлокодеров... Долго я после этого не хотела садиться за эксперименты программирование.

Как соорудить стек? Можно на основе массива. Заполняешь потихоньку массив и каждый раз запоминаешь адрес последнего элемента.

Примеры, которые видела я, основаны на списках. Я не знаю, как на основе массива создавать. И как в массиве можно запоминать адрес? Это в main-е будет создаваться массив? Массив указателей на элементы стека?

но поскольку на самом деле твой стек - список

Я правильно подумала, как добраться, но запуталась. Получается, надо было строчку tmp = First; вынести за пределы цикла. А почему? И если я хочу вернуть Cur со всеми потрохами, то это будет так?

TNode* GetValue (int pos) {  TNode *Cur = First;  for (int i = 0; i < pos; i++)   Cur=Cur->Next;  return Cur; }

Вы ни слова не сказали о моей работе с классами... :(Я надеялась на Вашу оценку. Не на что смотреть? Или - надо и можно лучше?

Ссылка на комментарий
Поделиться на другие сайты

Иазяв

Вы ни слова не сказали о моей работе с классами...
С классами у тебя очень здорово получается. Я, признаться, подумал, что ты взяла из какого-то учебника готовую программу и решила дополнить, поэтому не писал. И код хороший, не корявый... :)

А Cur - это указатель на выбранный нами элемент списка. Так что я бы функцию назвал не GetValue, а как-нибудь вроде PNode. Впрочем, как тебе больше нравится, так и называй... А по указателю, естественно, выпотрошить структуру, на которую он указывает, легко :)

И - ты сейчас меня убьешь - я у тебя функцию GetValue вообще как-то просмотрел, по названию решил, что что-то несущественное, и написал для выбора элемента PrintK. Оказалось, что она практически совпала с твоей GetValue.

Ну, а в

for (int i = 0; i< pos; i++)  {tmp = First;tmp = First->Next;  }

tmp топчется на месте, как бегун при фальстарте. При каждом выполнении цикла мы становимся на начальный адрес, делаем шаг, становимся снова на начальный адрес, делаем шаг, становимся снова на начальный адрес, ...

Начальный адрес при этом не меняется, так что дальше чем на шаг от вершины стека мы никогда не уйдем.

Примеры, которые видела я, основаны на списках. Я не знаю, как на основе массива создавать. И как в массиве можно запоминать адрес? Это в main-е будет создаваться массив? Массив указателей на элементы стека?

В массиве вместо адреса элемента можно помнить просто индекс элемента. В простой переменной, что для понимания даже проще.

В самом упрощенном виде, чтобы показать идею, программа со стеком на базе массива для, например, целых чисел будет выглядеть так:

#include<iostream>const int s=10; int st[s],t=0;void Push(int m){st[t++]=m;}int Pop(void){return st[--t];}int main(){for(int i=0;i<s;i++)Push(i);for(int i=0;i<s;i++)std::cout<<Pop()<<std::endl;}

Тут Push кладет очередное целое в свободную ячейку массива и увеличивает значение индекса первой свободной ячейки на единицу. Pop, наоборот, уменьшает значение индекса первой свободной ячейки на единицу, так что теперь он соответствует верхней занятой ячейке массива, и берет из этой ячейки значение элемента, после этого ячейка будет считаться свободной для новой записи в нее.

Можно было бы вместо функции Pop сделать две - одна только считывала бы значение элемента из вершины стека, а другая только удаляла бы из стека этот элемент.

Естественно, можно сделать массив динамическим, ввести проверки на пустоту и переполнение стека, элементами массива вместо целых определить какие-нибудь структуры, оформить все это в виде класса... Или использовать готовый стек из STL :)

Собственно, в STL стек является так называемым адаптером, то есть классом-оберткой - упрощенным обращением к более универсальному классу, там можно указать, будет ли стек реализован на основе списка или же динамического массива.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Тролль

ты сейчас меня убьешь

Никогда! У меня бы и мысли такой не возникло! Если не заметили, значит, устали, задергали на работе\дома\по дороге куда-то.

Хочу спросить по приоритетности и очередности выполнения операций. Как правильно писать, чтобы всегда корректно отрабатывался if?

if ( a == b && b == c && c == d )if ( a == b == c == d )if ( a == b && c && d )
Ссылка на комментарий
Поделиться на другие сайты

Иазяв

Вся логика в С и C++ основывается на том, что все ненулевое считается обозначением истины, а нулевое - лжи.

Соответственно этой логике if срабатывает на любое ненулевое число в качестве результата выражения в скобках.

Операции сравнения и логические операции как результат выдают 1 или 0.

== выдает 1, когда сравниваемые значения равны, иначе 0

&& выдает 1, когда слева И справа не нуль (и там, и там), иначе 0

|| выдает 1, когда слева ИЛИ справа не нуль (или там, или там, или и там и там), иначе 0

А очередность - в C есть 16 значений приоритета для разных операций. У == приоритет выше, сначала выполняются эти операции, затем &&. В ряду из операций одинакового приоритета они выполняются или слева направо (так для операции == и операции && тоже) или справа налево (для некоторых других операций, например, = ). Потому что определяли эти правила для себя профессионалы, как им удобнее. Приоритеты и порядок выполнения для разных операций должен быть в учебнике. В С все исходит из принципа "два пишем, три в уме".

В твоих примерах

if ( a == b && b == c && c == d ) - правильное сравнение на равенство всех четырех значений

if ( a == b == c == d ) - если a и b равны, получим 1 или 0. Дальше будем сравнивать 1 или 0 с с, а потом получившийся 1 или 0 с d. Навряд ли мы хотели именно этого ;)

if ( a == b && c && d ) - в переводе "если a равно b и при этом с не равно 0 и d не равно 0, то..."

Кстати, имей в виду, если используешь cout, то его операция << считается переопределенной операцией сдвига, а у нее приоритет даже выше сравнений, так что cout << 2 < 3; выдаст ошибку, правильно будет cout << (2 < 3); (выдаст 1)

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Иазяв

Вся логика в С и C++ основывается на том, что все ненулевое считается обозначением истины, а нулевое - лжи.

Соответственно этой логике if срабатывает на любое ненулевое число в качестве результата выражения в скобках.

Операции сравнения и логические операции как результат выдают 1 или 0.

== выдает 1, когда сравниваемые значения равны, иначе 0

&& выдает 1, когда слева И справа не нуль (и там, и там), иначе 0

|| выдает 1, когда слева ИЛИ справа не нуль (или там, или там, или и там и там), иначе 0

Таки не всё так гладко, сударь.

Эти измышления справедливы для C, но не для C++.

В С++ имеет место быть тип boolean. И все логические операции типизируются именно boolean типом. И RTTI это демонстрирует:

#include <iostream>#include <typeinfo>main() {   std::cout << "Type `0':      " << typeid(     0).name() << std::endl;   std::cout << "Type `42==42': " << typeid(42==42).name() << std::endl;   std::cout << "Type `0||1':   " << typeid(0 || 1).name() << std::endl;}/*output:Type `0':      iType `42==42': bType `0||1':   b*/

Все конструкции которым необходимо задавать условие (навроде, if или while) ожидают выржение boolean типа.

А причина по которой в С++ можно задавать int'ы в условные конструкции кроется в том, что Страус всегда очень хотел обеспечить совместимость с сишечкой (за это его и не любят девочки). И посему есть autocast'ы: int -> bool и bool -> int (без warning'ов!). И это плохо. Но ничего уж не поделать. Надо бы вынести C++ на помоечку.

Ссылка на комментарий
Поделиться на другие сайты

Ego Drama

Вообще-то да, это скрытый механизм приведений типов работает. Но благодаря ему "Вся логика в С и C++ основывается на том, что все ненулевое считается обозначением истины, а нулевое - лжи." остается верным. За счет приведений типов, конечно, но, в принципе, хоть за счет черта в ступе - КАКИМ ОБРАЗОМ это верно с точки зрения формального описания C++, я не разбирал.

Выкидывать C++ на свалку не стоит - это очень остроумный и изящный язык, но он предъявляет высокие требования к квалификации и безошибочности программиста. Поэтому изучение его в школах и вообще на непрограммистских специальностях, по-моему, глупость. Конструкции C++ не рассчитаны на облегчение жизни и работы программиста. Они рассчитаны только на эффективность - быстрое написание программ и эффективность получаемого кода - как раз за счет усложнения жизни и работы программиста. C++ относится к паскалеподобным языкам как стенография к обычному письму - быстрее, но отнюдь не проще и гораздо более чревато ошибками.

Ссылка на комментарий
Поделиться на другие сайты

Тролль

Нашла в инете задачки по ООП. Те, которые меня заинтересовали, хочу решить.

В данной задаче меня ничего не заинтересовало, кроме фразы "Составить из них иерархию или композицию". Посмотрите, пожалуйста, правильно ли я поняла, что иерархия - это наследование, а включение в класс объект другого класса - это композиция?

/* Создать классы : колесо, велосипед, автомобиль. Составить из них иерархию или композицию.*/#include <iostream>using namespace std;class Wheel{double Diameter;public:Wheel (){ Diameter = 0;}Wheel (double d){ Diameter = d;}void PrintDiameter (){ cout << "d = " << Diameter << endl;}};class Bike : public Wheel{double Price;char *Model;public:Bike (){ Price = 0; Model = new char[5]; strcpy(Model, "Empty");}Bike (double price, char *model){ Price = price; Model = new char[strlen(model) + 1]; strcpy(Model, model); }void PrintInfo (){ //printf ("%s%s%s%f", "Your choosing bike : ", Model, " cost ", Price); cout << "Your choosing bike : " << Model << " cost " << Price << endl;}};class Car{Wheel dmtr;double HorsePower;char *Model;public:Car (){ dmtr = HorsePower = 0; strcpy(Model, "Empty");}Car (double d, double HP, char *model){ dmtr = d; HorsePower = HP; Model = new char[strlen(model) + 1]; strcpy(Model, model);}void PrintInfo (){ printf ("Your choosing car : %s%s%f%s%f", Model, " has ", HorsePower, " horse power, diameter of wheel - ", dmtr);}};int main (){Wheel *wheel = new Wheel(9.9);wheel->PrintDiameter();cout << endl;Bike *bike = new Bike(12.23, "AZ");bike->PrintInfo();cout << "\nMethod from class Wheel" << endl;bike->PrintDiameter();cout << endl;Car *car = new Car(12.23, 34.45, "QW");car->PrintInfo();cout << endl << endl;delete wheel;delete bike;delete car;return 0;}

Спасибо за объяснение с if-ами.

Ссылка на комментарий
Поделиться на другие сайты

Иазяв

правильно ли я поняла, что иерархия - это наследование, а включение в класс объект другого класса - это композиция?
Да, правильно.

Все хорошо. По-моему, с классами ты уже управляешься легко :)

Ссылка на комментарий
Поделиться на другие сайты

По-моему, с классами ты уже управляешься легко

Спасибо за теплые слова (так хочется, чтоб они были правдивыми), но это ошибочное мнение. Я очень часто не могу заставить работать тот или иной класс. Часто компилятор отправляет в дебаггер, не указывая никакой ошибки. А я им так и не научилась работать. И приходится глазками скользить по программе, проверяя строчку за строчкой и выискивая ошибки. Чаще всего это ошибки связаны с динамической памятью, следовательно конструктор и деструктор неверны. Нас ориентировали на статическое создание объектов. А мне нравиться динамическое. Я очень хочу научиться управлять памятью в совершенстве.

Ссылка на комментарий
Поделиться на другие сайты

Тролль

так хочется, чтоб они были правдивыми

Извините, пожалуйста, это фраза может толковаться двояко. Хотела сказать, что хочется, чтобы так оно и было. Правда сурова и беспощадна. На днях рухнул мой "мощный" проект со множеством классов. А вчера допустила грубейшую ошибку в том примере, который выложила. Выделив память в конструкторе, не удалила ее в деструкторе... Меня что-то беспокоило в программе, но я не могла понять что. Сегодня утром открыла глаза и сразу перед глазами возникла строчка с new. Сразу вспомнила, что деструктор не писала.

Ссылка на комментарий
Поделиться на другие сайты

А вчера допустила грубейшую ошибку в том примере, который выложила. Выделив память в конструкторе, не удалила ее в деструкторе...

Вы уж меня извените, но помоему вы слишком критично к себе относитесь. Поверьте мне, даже супер гуру в программировании допускают ошибки, и довольно часто эти ошибки связаны именно с утечкой памяти. Благо их сложнее отловить, ведь всё работает, а то что через неделю работы программы у компа кончается оперативка, это надо ещё программу неделю где-то гонять.

Второй момент, не надо зацикливаться над проблемой, если с первого раза не идёт, лучше отложить задачу в сторону на некоторое время и заняться чем-нибудь другим. Мозг в фоне всё равно будет обдумывать эту проблему, пусть не так напряженно, но зато более продуктивно. Иногда полезно, что называется, с проблемой переспать, ведь не даром есть пословица: "Утро вечера мудреннее." С утра вы взглянете на проблему отдохнувшим мозгом и у вас получится типа

Сегодня утром открыла глаза и сразу перед глазами возникла строчка с new. Сразу вспомнила, что деструктор не писала.

@Иазяв, не забывайте что вы не компьютер, вы человек. И вы отличаетесь от компьютера именно тем, что вы можете ошибаться и можете уставать :)

Ссылка на комментарий
Поделиться на другие сайты

Человеку свойственно ошибаться - errare humanum est. Не стоит из этого делать открытие, это еще до нашей эры было замечено. А в программировании ошибки вообще норма. Поэтому Microsoft сначала отдает каждую Windows для бесплатного тестирования всем желающим, год выявляет и исправляет ошибки, и только затем начинает ее продавать, а исправления потом пишет еще десять лет ;) А в Microsoft не самые плохие программисты :)

Выделив память в конструкторе, не удалила ее в деструкторе.
И забыть освободить память - самый частый просмотр. Потому что при проверке работы программы он незаметен. Поэтому в C# ввели автоматическую сборку мусора - если ты забудешь освободить память, об этом позаботится компилятор :)

"Мало в какой области деятельности имеется столько возможностей для ошибок, как в программировании. Одним из критериев профессионального мастерства программистов является их способность обнаруживать и исправлять собственные ошибки: начинающие программисты не умеют этого делать, у опытных программистов это не вызывает затруднений. Тем не менее ошибки в программах делают все. В общем времени разработки программы отладка занимает, по оценкам специалистов, от 50 до 90%."

(Д. Ван Тассел. Стиль, разработка, эффективность, отладка и испытание программ.)

"Хорошие программисты знают, что они проведут столько же времени, отлаживая программу, сколько они ее и писали, и поэтому стараются учиться на своих ошибках. Каждая возможность в языке предотвращает одну проблему, но при этом имеет свою цену. Если в языке высокого уровня простые ошибки исчезают автоматически, то ценой этого станет большая вероятность совершать ошибки высокого уровня. Как бы нам ни хотелось обратного, но основное время при программировании тратится на тестирование и отладку."

("Практика программирования“, Б. Керниган, Р. Пайк)

Правда сурова и беспощадна. На днях рухнул мой "мощный" проект со множеством классов.
Это абсолютно нормально для "мощного проекта"...

"Эффект второй системы.

В своей первой работе архитектор обычно проявляет умеренность и аккуратность. Он знает, что он не знает того, что делает, а потому делает это тщательно и держит себя "в рамках". В процессе работы над своим первым проектом ему приходят на ум всякого рода находки и украшательства. Все они откладываются "до следующего раза". Рано или поздно работа над первой системой приходит к концу, и архитектор, преисполненный уверенности и продемонстрировавший свое мастерство на системах этого класса, готов заняться второй системой.

Эта вторая система - самая опасная из всех, которые когда-либо проектирует человек. Общая тенденция заключается в создании сверхпроекта второй системы, путем использования всех идей и находок, от которых предусмотрительно отказались в первой. В результате, как сказал Овидий, получается "большая куча"."

(Ф. Брукс. Мифический человеко-месяц или как создаются программные системы)

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Сегодня обнаружила, что пропустила большую часть информации о классах. Когда я познакомилась с классами, стала переделывать разные учебные программки в классы. И забыла, что есть мануал. Только какие-то определенные вопросы относительно работы или написания заставляли изучать матчасть. И вот сегодня я впервые узнала об абстрактных\виртуальных классах и виртуальных функциях... Как я пропустила все это? - сама очень сильно удивляюсь. Наверное, заигралась...

Конкретно меня интересует, почему в классе President закомментированная функция так и не вывела результат функции Earnings? Я добавила область видимости, как посоветовал компилятор, но результат не изменился. На экран выводится единица (тоже не могу понять почему).

#ifndef _EMPLOYEE_#define _EMPLOYEE_#include <iostream>#include <cstring>#include <assert.h>using namespace std;class Employee{char *FirstName;char *LastName;public:Employee (const char *first, const char *last){ FirstName = new char [strlen(first) + 1]; assert (FirstName != 0); strcpy(FirstName, first); LastName = new char [strlen(last) + 1]; assert (LastName != 0); strcpy(LastName, last);}~Employee (){ delete [] FirstName; delete [] LastName;}//-----------------------------------------------const char *GetFirstName () const{ return FirstName;}const char *GetLastName () const{ return LastName;}//-----------------------------------------------virtual float Earnings () const = 0;virtual void PrintInfo () const = 0;};//=================================================================================================class President : public Employee{float WeeklySalary;public:President (const char *first, const char *last, float s = 0.0) : Employee (first, last){  SetWeeklySalary (s);}//-----------------------------------------------void SetWeeklySalary (float s){ WeeklySalary = s > 0 ? s : 0;}//-----------------------------------------------virtual float Earnings () const{ return WeeklySalary;}/*virtual void PrintInfo () const{ cout << "President : " << GetFirstName () << " " << GetLastName ()  << ". Earnings = " << &President::Earnings << " in week." << endl;}*/virtual void PrintInfo () const{ cout << "President : " << GetFirstName () << " " << GetLastName () << endl;}};//=================================================================================================class Manager : public Employee{float Salary;float Commission;unsigned int Qty;public:Manager (const char *first, const char *last, float s = 0.0, float c = 0.0, unsigned int q = 0) : Employee (first, last){ Salary = s > 0 ? s : 0; Commission = c > 0 ? c : 0; Qty = q > 0 ? q : 0;}void SetSalary (float s){ Salary = s > 0 ? s : 0;}void SetCommission (float c){ Commission = c > 0 ? c : 0;}void SetQuantity (unsigned int q){ Qty = q > 0 ? q : 0;}virtual float Earnings () const{ return Salary + Commission * Qty;}virtual void PrintInfo () const{ cout << "Manager : " << GetFirstName () << " " << GetLastName ()  << ". Earnings = " << &Manager::Earnings << " in this week." << endl;}};//=================================================================================================class Worker : public Employee{float Wage;float Hours;public:Worker (const char *first, const char *last, float w = 0.0, float h = 0.0) : Employee (first, last){ Wage = w > 0 ? w : 0; Hours = (h >= 0 && h < 168) ? h : 0;}void SetWage (float w){ Wage = w > 0 ? w : 0;}void SetHour (float h){ Hours = (h >= 0 && h < 168) ? h : 0;}virtual float Earnings () const{ return Wage * Hours;}virtual void PrintInfo () const{ cout << "Worker : " << GetFirstName () << " " << GetLastName ()  << ". Earnings = " << &Worker::Earnings << " in this week." << endl;}};#endif

В main при написании ptr->Earnings() все вывелось правильно. В Manager уже просто проверяла и так и так. Результат такой же - 1 и правильно.

int main (){Employee *ptr;President P ("John", "Smith", 1000.00);ptr = &P;cout << "Dynamic : " << endl;ptr->PrintInfo();cout << "Static : " << endl;P.PrintInfo();cout << "Salary President = " << ptr->Earnings() << endl;Manager M ("Sue", "Jones", 400.00, 2.5, 130);ptr = &M;cout << "Dynamic : " << endl;ptr->PrintInfo();cout << "Static : " << endl;M.PrintInfo();cout << "Salary Manager = " << ptr->Earnings() << endl;Worker W ("Karen","Wolf", 13.75, 40);ptr = &W;cout << "Dynamic : " << endl;ptr->PrintInfo();cout << "Static : " << endl;W.PrintInfo();cout << endl;return 0;}
Ссылка на комментарий
Поделиться на другие сайты

kvazimoda

Я не слишком самокритична, просто держу себя в ежовых рукавицах. Хочется, чтобы другой программист, увидев мой код, сразу понял без каких-либо сопроводительных записок, что означают переменные, что выполняют функции, и чтоб, если он решит использовать мою программу, он не плевался, что компилятор выдал кучу ошибок или послал в дебаг из-за утечки памяти.

Над проблемами не зацикливаюсь, поэтому имела кучу хвостов и шанс не быть допущенной к экзамену. :) Обычно я сажусь за домашние задания и пишу код до момента, когда я не могу что-то придумать, сообразить, заставить программу правильно работать. Побившись, перехожу к следующей задаче и до такого же момента. Через некоторое время цикл повторяется. Если я сильно расстраиваюсь из-за незапустившейся программы, то могу удалить ее и написать заново. Есть программка, которую я переписывала 5 раз.

Иногда полезно, что называется, с проблемой переспать, ведь не даром есть пословица: "Утро вечера мудреннее."

Заметила, что лучше всего мне программируется утром. :rolleyes:

Ссылка на комментарий
Поделиться на другие сайты

Вообще-то да, это скрытый механизм приведений типов работает. Но благодаря ему "Вся логика в С и C++ основывается на том, что все ненулевое считается обозначением истины, а нулевое - лжи." остается верным. За счет приведений типов, конечно, но, в принципе, хоть за счет черта в ступе - КАКИМ ОБРАЗОМ это верно с точки зрения формального описания C++, я не разбирал.

Выкидывать C++ на свалку не стоит - это очень остроумный и изящный язык, но он предъявляет высокие требования к квалификации и безошибочности программиста. Поэтому изучение его в школах и вообще на непрограммистских специальностях, по-моему, глупость. Конструкции C++ не рассчитаны на облегчение жизни и работы программиста. Они рассчитаны только на эффективность - быстрое написание программ и эффективность получаемого кода - как раз за счет усложнения жизни и работы программиста. C++ относится к паскалеподобным языкам как стенография к обычному письму - быстрее, но отнюдь не проще и гораздо более чревато ошибками.

Эу. У меня есть подозрения, что вы немного запутались в своих утверждениях. Говорите, что "C++ не расчитан на облегчение жизни программиста" и кодирование на C++ "черевато ошибками". И в тоже время опровергаете это заключением о том, что C++ для эффективного и быстрого написания программ. Как же такое может быть? Объясните почтенной публике.

Выкидывать C++ на свалку не стоит - это очень остроумный и изящный язык, но он предъявляет высокие требования к квалификации и безошибочности программиста.

Именно по причине, что C++ "предъявляет высокие требования к квалификации и безошибочности программиста" его и стоит выбросить на свалку истории. Свалка светит именно потому, что C++, от природы, полагает, что программист это некий робот, который сможет управиться с, иcторически сложившейся, нелепой семантикой языка. И вместо того, что бы непосредственно решать прикладную задачу, подобрав подходящий инструмент, С++ кодер отчаянно и героически стражается с нелепостями своего инструмента.

Именно по этой причине, C++ кодеры всё менее и менее востребованы. C++ кодеры не рентабельны. Они, в большинстве случаев, крайне не эффективны. Тратят время и деньги работодателя.

Всё меньше и меньше доля рынка у C++. Сейчас уже почти никто не начинает новые проекты на нём. Вся работа это, в основном, legacy. Болото и забвение.

очень остроумный и изящный язык

Нет. Вас обманули. В C++ остроумия и изящности приблезительно столько же, сколько "в танцующем медведе". C++ кажется остраумным и изящным только тем господам, которые не видели ничего слаще этого и которые ещё не выписались из детского сада. "Остроумие и изящество" присуще, в основном, академическим технологиям. И тут следует смотреть в сторону, например, Haskell.

C++ относится к паскалеподобным языкам как стенография к обычному письму - быстрее, но отнюдь не проще и гораздо более чревато ошибками.

Синтаксис языка совершенно никак не коррелирует с быстрой разработкой программ. И для быстрого прототипирования C++ подходит крайне паршиво. На свете существует масса технологий для прототипирования, расчитаных на широкий круг задач, например:

  • Prolog, Lisp - области, где удобна логика предикатов (например, экспертные системы), трансляторы/компиляторы;

  • Tcl/Tk - GUI;

  • Ruby/Python/Perl/Tcl - автоматизация, интеграция, и пр.

и т.д.

Поэтому изучение его в школах и вообще на непрограммистских специальностях, по-моему, глупость.

Ещё большая глупость - изучение его на программстских специальностях. Программисты должны в первую очередь изучать математику, а далее прикладные области и методологии. Программист должен чётко разбираться в сематниках языков программирование. И обладая данным фундаментом, программист без труда в кратчайшие сроки изучит синтаксис любого языка, разберётся в сильных и слабых сторонах. И далее раздаст задачи обезьянкам-кодерам.

На фоне этого, изучение C++ глупая и бесполезная трата времени. Изучение C++ удел проф. училищ (причём, весьма посредственных).

Ссылка на комментарий
Поделиться на другие сайты

kvazimoda

Я не слишком самокритична, просто держу себя в ежовых рукавицах. Хочется, чтобы другой программист, увидев мой код, сразу понял без каких-либо сопроводительных записок, что означают переменные, что выполняют функции, и чтоб, если он решит использовать мою программу, он не плевался, что компилятор выдал кучу ошибок или послал в дебаг из-за утечки памяти.

Над проблемами не зацикливаюсь, поэтому имела кучу хвостов и шанс не быть допущенной к экзамену. :) Обычно я сажусь за домашние задания и пишу код до момента, когда я не могу что-то придумать, сообразить, заставить программу правильно работать. Побившись, перехожу к следующей задаче и до такого же момента. Через некоторое время цикл повторяется. Если я сильно расстраиваюсь из-за незапустившейся программы, то могу удалить ее и написать заново. Есть программка, которую я переписывала 5 раз.

Заметила, что лучше всего мне программируется утром. :rolleyes:

Если вы хотите достичь успехов в решении задач, а также получать удовольствие от конечной реализации, то с C++ вам не по пути. Вредно зацикливаться на одной спорной и невнятной технологии. Это путь в никуда.

Ссылка на комментарий
Поделиться на другие сайты

Иазяв

Заметила, что лучше всего мне программируется утром.
А я просыпаюсь обычно в 10 утра. То есть встать, одеться и начать работать я могу и в 6, но вот проснуться раньше 10 у меня обычно не получается, соответственно и толк от моей работы будет начиная с 10 часов, если она не совсем уж тупая, конечно ;)
Конкретно меня интересует, почему в классе President закомментированная функция так и не вывела результат функции Earnings? Я добавила область видимости, как посоветовал компилятор, но результат не изменился. На экран выводится единица (тоже не могу понять почему).
Так функцию-то никто не вызывает. Функцию надо вызывать не одним именем - это ее адрес (и что из него сделает cout, один cout и знает ;) ), а со скобками. И я не понял, зачем компилятору явно указывать, из какого класса брать функцию вычисления зарплаты. Пусть сам смотрит, кто ее вызвал, и разбирается, какую из виртуальных функций вызвать. То есть вместо вызовов типа &Worker::Earnings надо вызывать Earnings()

В общем, приложил немного переделанный вариант. Насколько я понял, там не все, чего ты хочешь, то есть нет демонстрации разницы между статическими функциями и виртуальными, которую ты вроде бы хотела (у тебя в main() просто двумя способами вызывается одна и та же виртуальная функция), однако я решил, что телегу достаточно только сдвинуть с места, а куда ее дальше везти и нужно ли это, ты решишь сама :)

Проклятье программирования на C++ в том, что он почти все ошибки как-нибудь да истолкует, причем обычно превратно.

President.zip

President.zip

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Ego Drama

У меня есть подозрения, что вы немного запутались в своих утверждениях. Говорите, что "C++ не расчитан на облегчение жизни программиста" и кодирование на C++ "черевато ошибками". И в тоже время опровергаете это заключением о том, что C++ для эффективного и быстрого написания программ. Как же такое может быть? Объясните почтенной публике.
Я вроде бы объяснил. Возможность писать программы кратко за счет высокой сложности языка вовсе не облегчает работу программиста, только ускоряет ее. Если мы решаем какую-то задачу, то чем выше сложность языка, на котором мы описываем решение, тем короче будет текст этого решения.

Например, системы уравнений при записи их в матричной форме выглядят куда компактнее - но при этом вам надо знать матричную алгебру, и о некоммутативности умножения матриц не забывать. Или, чрезвычайно мощный язык программирования APL для математических вычислений позволяет в одной строчке записать то, для чего на другом потребуется страница - но попробуйте составить или расшифровать такую запись.

Более простой пример, который я уже приводил - стенография. Знать надо больше, нагрузка на мозг выше, но пишется быстрее.

Даже на примитивном уровне С: выражение a[4*i+5]=a[4*i+5]+1 выглядит понятнее чем ++a[4*i+5]. Использование автоинкрементов позволяет писать программы короче и быстрее за счет того, что программисту надо помнить разные варианты увеличения значения на 1, выбирать из них самый короткий и учитывать возможные побочные эффекты.

Именно по причине, что C++ "предъявляет высокие требования к квалификации и безошибочности программиста" его и стоит выбросить на свалку истории.
Вы считаете, что Haskell не предъявляет высоких требований к квалификации программиста? Попробуйте преподавать его обычным людям, например, школьникам ;)
C++ кодеры всё менее и менее востребованы. C++ кодеры не рентабельны. Они, в большинстве случаев, крайне не эффективны. Тратят время и деньги работодателя.

Всё меньше и меньше доля рынка у C++. Сейчас уже почти никто не начинает новые проекты на нём.

Возьмем статистику ( http://www.tiobe.com...tpci/index.html ) - доля C++ за истекший год выросла. Хотя еще быстрее C++ растут другие варианты С. В общей сложности разные варианты С сейчас занимают 60% рынка и этот процент продолжает расти. Haskell применяется в 200 раз реже, занимая 0,3% рынка. При таком положении дел я бы лично не рискнул рекомендовать бросить C++ и начать изучать Haskell ;)

Вообще, как видно в табличке дальше на странице по ссылке, функциональные языки снижают свою популярность - в целом за год она снизилась на 1,3%, при росте популярности ООП языков на 1,5%.

Программист должен чётко разбираться в сематниках языков программирование. И обладая данным фундаментом, программист без труда в кратчайшие сроки изучит синтаксис любого языка, разберётся в сильных и слабых сторонах. И далее раздаст задачи обезьянкам-кодерам. На фоне этого, изучение C++ глупая и бесполезная трата времени. Изучение C++ удел проф. училищ (причём, весьма посредственных).

По-моему, у Вас завышенные представления об интеллекте типичных представителей рода человеческого. У работодателей нужда прежде всего в "обезьянках-кодерах", а не в неопытных руководителях проектов, теоретически изучивших синтаксис нескольких языков.

Вообще же такие языки, как Хаскелл, действительно очень интересны. Их минус - они требуют специфического, "нечеловеческого" мышления. Это общая беда всех функциональных языков, начиная с LISPa. Поэтому они так и не вышли на уровень распространенности процедурных и ООП языков.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Ego Drama

Возможно, Вам не понравиться, но я не согласна с тем, что Вы мне написали.

С++ - один из языков программирования, это инструмент, с помощью которого я учусь творить. Нельзя сказать, что он плохой. Любой язык имеет свои плюсы и минусы. Это все равно, как если бы я захотела взять сковороду или 3л кастрюлю или 5л кастрюлю или скороварку для приготовления борща, а Вы мне сказали, что они плохи для его приготовления. Но ведь я могу выбрать любой из них в зависимости от условий. 3л - если ко мне придут 5 человек в гости. 5л - если гости придут с друзьями. Скороварка - если я хочу приготовить борщ за короткий период времени. А в сковородке неудобно готовить, но 3л, 5л кастрюли и скороварка у меня заняты, а борщ готовить надо... Дурацкий пример, я знаю.)) Главное - суть.

Пример из жизни. Наш преподаватель по С++ очень резко отзывается о PHP (приблизительно как Вы о С++). А я видела человека, который творит чудеса на PHP. И сказать, что это ненужный, ограниченный, глупый язык, я не смогу, потому что я видела, что можно сделать с его помощью.

Мы проходим учебные программы. Мне не всегда нравятся задания - скучные, нелепые, списанные друг у друга - но их надо выполнить. Я их пишу, и когда они запускаются без ошибок, когда они красивы, оптимальны, я радуюсь. Мы проходим С++, но никто мне не мешает выучить любой другой язык. А еще я думаю, что если я после С++ выучу какой-нибудь другой язык программирования, то мне не составит труда перевести программы, написанные на С++, на этот язык или наоборот. Чем больше инструментов, тем интересней выбрать оптимальный и нужный в данный конкретный момент. Я могу морковку для борща нарезать ножом, натереть на терке или нашинковать в комбайне - это мой выбор для данной задачи в данный момент.

Ссылка на комментарий
Поделиться на другие сайты

Тролль

Даааа, уже стала не писать в функциях скобки... Что-то со мной в последнее время происходит... Ловлю себя на элементарных ошибках.

Спасибо большое!

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

Всем добрый день! Кому не сложно и интересно, помогите пожалуйста с задачками, буду очень благодарен:

Задачка на PascalABC:

Сведения о клиентах организованы в виде односвязного списка

Сведения включают:
Фамилия, имя;
Номер телефона;
Дата рождения (массив из трех чисел).
Написать программу, реализующую следующие действия:
Начальное формирование списка;
Добавление элементов в список;
Удаление элемента списка с заданным номером телефона;

Вывод информации о человеке, фамилия которого введена с клавиатуры.

Задачки на Делфи:

1я) Требование: исходные данные вводить с помощью компонента Еdit с соответствующим пояснением в виде компонента Label.

Для вывода результата использовать компонент Label или окно сообщения (для вывода сообщения в окне использовать процедуру ShowMessage)

Условие)Присвоить целой переменной k третью от конца цифру в записи положительного целого числа n

2я) Вычислить значения функции на заданном отрезке. Количество точек разбиения (n) отрезка вводить, используя компонент Edit. Значения аргумента (x) в каждой точке и значения функции поместить в таблицу (использовать компонент StringGrid). Построить график функции, используя компонент Chart. Использовать для построения графика полученные данные из таблицы.

f = sin(x) + sin(2x); 0<=x<=6π

3я) В текстовом файле записана по строкам действительная квадратная матрица a[1..m, 1..m], где m –заданное натуральное число. Найти минимальный элемент матрицы. Вывести его значение. Элементы строки, в которой находится минимальный элемент, поместить в компонент Memo.

Заранее спасибо!

Ссылка на комментарий
Поделиться на другие сайты

Добрый день!

Напишите пожалуйста программу на С++ :

Написать программу, использование которой позволяет пользователю ввести с клавиатуры четыре действительные числа и вывести на экран произведение этих чисел, а также их среднее арифметическое с двумя цифрами после запятой.

Ссылка на комментарий
Поделиться на другие сайты

  • 2 недели спустя...

Помогите, пожалуйста. Нужно написать программу на С++

Вычислить приближённое значение функции, используя представление ее в виде ряда Тейлора. Вычисления заканчивать, когда очередное слагаемое окажется по модулю меньше заданного числа e, где 0 < e < 10-k, k – натуральное число, k > 1. Сравнить полученный результат со значением, вычисленным, используя стандартные функции. Значение x и e ввести по запросу

arctan x= x - x
3
/3 + x
5
/5 - x
7
/7 +…; где x=(-1, +1)
Ссылка на комментарий
Поделиться на другие сайты

Rika23

#include<iostream>#include<iomanip>#include<cmath>using namespace std;int main(){double x,e,p,y; cout<<"x(-1<x<1) e(e<0.1) ? ";  cin>>x>>e; y=p=x; for(int i=3;abs(p)>=e;i+=2){p=-p*x*x; y+=p/i;}cout<<setprecision(14)<<"rough: "<<y<<"   exact: "<<atan(x)<<endl;}
Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу



×
×
  • Создать...