Софтуерно Инженерство
Loading...
Jordan_Dobrev12 avatar Jordan_Dobrev12 256 Точки

Съвети за първа задача от ООП - C++

Здравейте колеги , от липса на време още се мъча как да реша първа задача от ООП

Правя няколко неща накуп и ме затрудняват задачите , ако може малко помощ?

Как да отделя един масив ?

Примерно имам един стринг масив:

 

string text []  = {" SoftUni 3.0! Write C++ through 2017 year."};

 

Как да разделя текста от числата и char-овете ?

Искам да изкарам :

" SoftUni Write C++ through year "  - в стринг масив
" 3 0  2017 "като масив от числа
" !  .  "   като char масив

 

 

 

 

0
C++ Programming
Vladimir_Asenov_Vasilev avatar Vladimir_Asenov_Vasilev 13 Точки
Best Answer

Това не ти е условието на задачата. 
Ако имаш 1 9 34 56 73 12 -> да го изкараш като масив от числа.
Ако имаш "String1 String2 String3" -> да го изкарваш като масив от стрингове или масив от чарове.
Ако искаш да си го правиш сложно просто вземи един цикъл и обикаляй през входния стринг.
Когато срешнеш цифра с isdigit(char) влизаш в друг цикъл който следи колко последователни цифри имаш и ги правиш на число:
Да кажем: if( isdigit(input[index]) { int num = 0; while(isdigit(input[index]) { num *= 10; num += input[index] - '0'; input[index++] = ' ';} }.
Забележи, че замества цифрите със space. След това излизаш от този цикъл и правиш останалия input стринг на stringstream и просто чрез оператора >> вадиш следващия стринг. Ако стринга е с size() == 1 това е char и го слагаш в масив от чарове ако ли не в масив от стрингове.
Общо взето такива ми ти глупости.
Ако искаш може даже да си направиш стринг с дължина колкото входния. Да обикаляш с цикъл и да копираш числата и след това да ги извадиш със string stream.
Общо взето разбивай си задачата на под задачи.
1.Как да извядя само числата.
2.Как да извадя самотните букви.
3.Как да извася последователните букви

 

1
30/03/2017 22:02:01
v.krastev avatar v.krastev 54 Точки

здравейте!

отворена тема, с подходящо за въпроса ми заглавие, затова ще питам тук. за въпросната първа задача - какво се предполага, че трябва да прави метода "void changeLine(const string& line);". препрочитам условието пак и пак и не схващам какво се продполага че трябва да напиша, отговарящо на това име? вторият въпрос - някакви ограничения относно const и по-специално референциите с които очевидно може да декларираме конструктори (пак както е показано в условието)? да разбирам че все едно си е нормална функция и да си използвам референции, навсякъде където мога, с цел забързване на програмата?

Благодаря предварително!

1
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки

Здравей,

На първия ти въпрос - changeLine просто сменя нещото, което LineParser-а parse-ва. Примерно ако имаш няколко реда числа, вместо да създаваш нов LineParser за всеки от тях, можеш да създадеш само един и да му казваш .changeLine() за всеки нов ред.

LineParser parser("1 2 3");
parser.getNumbers(); // ще даде int масив с елементи {1, 2, 3}
parser.changeLine("4 5 6");
parser.getNumbers(); // ще даде int масив с елементи {4, 5, 6}

На втория въпрос - методите трябва да са точно такива, каквито са в условието. Ако параметърът е const &, значи и при теб трябва да е така - какво ще правиш с така получения параметър в тялото на методите е твое решение. Идеята тук е както да упражните различните начини за работа с конструктори, референции и т.н., така и да сте подготвени ако ви се наложи да ползвате библиотеки, които имат такива изисквания (примерно в STL има изисквания за някои от параметрите на определени методи, когато искаш да ползваш твой клас с някой контейнер, например priority_queue).

Поздрави,

Жоро

1
v.krastev avatar v.krastev 54 Точки

дааа, има логика :D:D толкова време го мислех, а то е напълно логично, благодаря!

да, нов въпрос. още по време на лекцията, колега попита дали при обявяването на x(x) с двете точки преди бодито на конструктора може да използваме this->. жоро пробва и видяхме че даде някаква грешка и уточнихме че този this-> трябва да го използваме вътре във методите и конструкторите. НО, следната грешка: в самия клас, името на стринга който използвам (подавам към стринг стрийма) ми е "line". метода "void changeLine(const string& line);" има параметър "line", следователно ще е добра идея да използвам this->. НО, вътре в метода this->line = line; работи, докато line(line) и this->line(line) дава грешка. в демото предоставено от лектора примера си е с this->line=line (е, не е line, ами number, age и тн). въпроса ми е - когато използваме this->,      x(x) е невалиден синтаксис винаги или? и защо line(line) не работи вътре в тялото на този метод, но подобни присвоявания си работят при конструкторите, когато ги правим там с двете точки преди бодито?

ако не се разбира въпроса ми, кажете, не знам колко добре се изразих.

0
31/03/2017 20:54:12
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки

Не съм напълно сигурен, че те разбрах, но все пак ще се опитам да ти отговоря :D

Синтаксиса на initializer list - в твоя случай line(line) - може да се ползва само при ... drumroll ... инициализация :D! Инициализацията на членовете на един клас се случва в конструктора. Затова ако се опитваш да го ползваш в някой метод (който може да бъде викнат когато и да е по време на живота на обекта), C++ ти мрънка, че се опитваш да инициализираш нещо, което вече е инициализирано (или нещо подобно ще ти казва грешката).

Това важи и за "нормален" C++ код, например в main функцията:

int number(5);
cout << number;
number(6); //компилационна грешка - number вече е инициализиран, ако искаме да му сменим стойността трябва да ползваме assignment, тоест = оператора

int otherNumber;
otherNumber(69); //пак грешка - otherNumber е инициализиран "по подразбиране" на горния ред (в случая за int това ще е произволна стойност)

Тези неща нямат нищо общо с this, не се бъркай, че едното пречи на другото.

А причината да не можем да ползваме this-> в initializer list-а, когато пробвахме по време на лекцията, както си спомняш, е че просто не можем да пишем this извън тялото на метод. Тоест, синтаксиса на езика е просто такъв.

Обобщено:

- initializer list е специален синтаксис, който може да ползваш само с двуеточие след конструктор (преди тялото му)

- this-> можеш да ползваш само в тялото на (non-static) методи

- инициализация (int x(3);) и присвояване (x = 3;) са две различни неща, като инициализацията може да се случи само веднъж, а присвояването може да стане колкото си искаш пъти (стига да x да не е const)

- не можеш да инициализираш членове на класове в тяло на метод (в тяло на конструктор също), защото тяхната инициализация се случва в initializer list-а на конструктора (не в тялото на конструктора), дори и да нямаш написан някой член в initializer list, той се инициализира по подразбиране.

- Но в тяло на метод (или конструктор) можеш да им правиш assignment, тоест да им казваш "= something" на което и да е поле или променлива

- Нищо не ти пречи в тяло на метод да си направиш локална променлива, която инициализираш чрез скобите, но не можеш да го правиш за поле, защото - отново - то вече е инициализирано

1
v.krastev avatar v.krastev 54 Точки

да, разбрал си ме и отговора ти ми обясни много неща, благодаря много!!!!

0
zzerro avatar zzerro 11 Точки

Не мога да се ориентирам в условието. Първо се казва, че "класът приема стринг...", но доколкото разбирам идеята за класове, те приемат обекти; а после са дадени такива редове в тялото на класа: 

    IntSmartArray getNumbers() const;

    StringSmartArray getStrings() const;

...

Какъв е този синтаксис? Какво е отношението на масивите (!?) към функциите/методите? Защо са на един ред без никакви знаци помежду си?

0
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки

Под "класът приема стринг" се има предвид, че когато създаваш обект от този клас, на конструктора му подаваш обект от тип string. Затова е даден и примерен код с точно такъв конструктор. Един вид от твоя клас се очаква да работи с някакъв конкретен обект от тип string, това се има предвид в условието.

После като викаш съответните методи на класа, те трябва да обработят този string и да го преобразуват съответно в масив от int-ове или масив от string-ове.

Няма нищо обобено в този синтаксис, IntSmartArray и StringSmartArray са просто някакви измислени класове, които представляват масив от int-ове и масив от string-ове. По време на лекциите написахме един SmartArray клас, който работеше с int-ове - затова и текста преди примерния код казва "ако решите да ползвате SmartArray...". Ако искаш може методите ти да връщат и vector<int> и vector<string> съответно, или по някакъв начин да връщат масив - но при всички положения трябва някак да върнат елементите, които са били обработени (parse-нати) от string обекта, който е бил подаден на конструктора.

Виж примерите, които съм дал по-нагоре в коментарите.

Поздрави,

Жоро

 

0
zzerro avatar zzerro 11 Точки

После като викаш съответните методи на класа, те трябва да обработят този string и да го преобразуват съответно в масив от int-ове или масив от string-ове.

T.e. методите се отнасят за всеки обект поотделно? И не е нужно да пълнят масивите с инт-овете на всички въведени обекти? Така всеки обект ще има своя отделен инт-масив?

Няма нищо обобено в този синтаксис, IntSmartArray и StringSmartArray са просто някакви измислени класове, които представляват масив от int-ове и масив от string-ове.

Ако са класове, то валидно ли е да създаваме техни обекти в синтаксис за функция?

0
14/04/2017 16:51:10
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки

Класът си има методи. Тези методи се викат върху обекти от класа. Това е цялата идея на не-static методите, като викнеш един такъв метод на един обект, този метод да се изпълни само за този обект. Като имаш един string s; и на него му кажеш s.find("...") или s.size(), това не работи върху всички string обекти създавани някога, а върху конкретния string s;.

Иначе, разбира се че можеш да създаваш обекти от един клас във функция (метод) на друг клас. string също е клас, можеш да си създаваш обекти от него в main(), можеш да го връщаш и т.н.

Мисля че трябва да прегледаш наново лекцията за ООП, там сме ги говорили тези неща.

0
zzerro avatar zzerro 11 Точки

олелеее... наистина така задачата е лесна... а аз се чудех как да обединя всички инт-масиви в един резултантен...

...

Иначе, разбира се че можеш да създаваш обекти от един клас във функция (метод) на друг клас. 

Да, но за обект задаваме само име. Можеш ли да ми обясниш какво създаваме така (кое е името на обекта?):

IntSmartArray getNumbers() const;

0
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки

Не създаваме обекти с тази декларация. С това само казваме, че има метод getNumbers в този клас, който връща обект от тип IntSmartArray (и освен това този getNumbers не променя текущия обект, заради const думата). Това не е цялата функция, това е само декларация на функция, спомни си в първата лекция как можехме да декларираме функция на едно място, а на друго да я дефинираме (да ѝ напишем тялото). В тялото на тази функция, което ти трябва да напишеш, ще създадеш обект, на който можеш да му дадеш име, и ще го return-неш. Дадена ти е само декларацията, а от теб се иска спрямо тази декларация да напишеш имплементация, това е част от задачата.

В 5-та лекция (тази за Code Organization) можеш да видиш подробно обяснение на това разделение на декларация и дефиниция, когато става дума за класове.

 

0
zzerro avatar zzerro 11 Точки

Благодаря за отговорите! smiley

Не исках да занимавам форума с минали неща, но не ми беше ясно. Навсякъде за тази задача пишат, че това са масиви, а не декларация на функция/метод, която връща обекти на класовете IntSmartArray и StringSmartArray (създадени като варианти на smart-array класа). Май и на други не им е съвсем ясно... дано е от полза и за други и съжалявам, че ти губя времето за минали неща.

0
14/04/2017 18:02:07