Разграничаване на string-ове от getline. Memory Management Homework
Здравейте,
Извинявам се предварително ако въпроса ми е прекалено елементарен, но наистина не мога да го направя това. А именно да отделя различните string-ове веднъж след като съм прочела някакъв текст от конзолата. Трябва да мина през всяка дума, за да променя или проверя нещо в упражнения 5,6 и 7.
Знам че за getline може да се зададе опция да взема до определен символ. Но в случая това което ме обърква е, че не е един символа, който разделя думите. Може да е празно място, може да е тире, може да е запетя, може да е скоба и тн.
Как се прави така че всички тези символи да бъдат отчетени като разграничения между думите?
Камелия
Благодаря ти за отговора!
Имам още един въпрос за задача 5. Защо toupper не се задейства като е в функцията? Нещо не правя както трябва сигурно. Пробвах го в main и си работи, но в makeTitleCases не ми се получава:
#include<iostream>
#include <string>
using namespace std;
void makeTitleCase(string& text);
int main()
{
cout << "Please enter a line of text:" << endl;
string inputLine;
getline(cin, inputLine);
makeTitleCase(inputLine);
cout << inputLine << endl;
return 0;
}
void makeTitleCase(string& text)
{
for(int i=0; i<text.length(); i++){
if(text[i] == ' ' || text[i]== ','){
toupper(text[i+1]);
}
}
return;
}
Провери го как е дефиниран и описан тук: http://www.cplusplus.com/reference/cctype/toupper/
Забележи, че не приема референция към променлива, а взема стойност и връща стойност :)
Това означава, че ако имаш char letter = 'a'; toupper(letter) няма да направи нищо директно. Но ако имаш char letter = 'a'; char uppercaseLetter = toupper(a) вече е друго нещо. Също както abs(-5) няма да промени -5 на 5, а ще ти върне ново число, което е абсолютната стойност, така и toupper връща стойност вместо да променя това, което си му подала. http://www.cplusplus.com/ is your friend за всякакви такива неща
text[i+1]=toupper(text[i+1]);
Така ще работи обаче не работи за първата буква.
Освен интервал и "," има още доста неща " ' ? ....12345 и т.н.
Може да използваш isalpha().
Освен съвета на колегата - помисли за последния символ - какво ще стане като направиш i+1 там? В конкретния случай, понеже работиш със string, а той има null-terminator накрая, ще си ок, но ако кодът ти правеше нещо различно от toupper може да бъде опасно :)
Аз го направих по този начин. Просто ползвам !isalpha(), т.е. всичко, което не е буква пред намерената буква. Сложил съм и проверка за интервал и нов ред.. За първия символ съвсем отделна проверка правя.
void makeTitleCase(string& text)
{
int i = 0;
if (isalpha(text[i])) toupper(text[i]); // Make upper if is a letter at index 0.
for (i; i < text.length(); i++)
{
if (isalpha (text[i]) // Check for letter
&& (!isalpha (text[i-1]) // and any not-letter character
|| isspace(text[i-1]))) // or space/tab... etc. before before letter
text[i] = toupper(text[i]);
}
}
Нали функцията ти е void, защо има return? Работи ли ти с returna?
Можеш да имаш return; във void функция, стига да е "празен", тоест да няма нещо което return-ваш. Принципно идеята е да можеш да прекратиш изпълнението на функцията, преди тя да е стигнала до края си (примерно в някой if), доста често се ползва (в другите езици е същото). Не е задължително да го има и общо взето в нейния пример няма нужда от него, защото така или иначе е накрая, но не е грешно и не пречи :)
аха! Нещо като break за фунцкия. Не знаех, че може да е празен... (аз го пробвах с нула, ама не ставаше...)
Хубаво е, че си така отзивчив и всеки път човек научава нещо!
Да, точно като break за функция. И е по-"силно" от break-а, тоест ако си в цикъл във функция, ако кажеш break ще излезе от цикъла, ако кажеш return направо ще излезе от функцията.
Радвам се, че съм от полза :)
Според мен ти трябва едно i++ преди цикъла или в самия цикъл for (++i;..... .
Какво ще ти даде && (!isalpha (text[i-1]) от i=0 ? Божа работа...
Гледам, че от C++ 11 вече има std::regex_match. Не съм го пробвал но като знам как работят регексите не би трябвало да е проблем разделянето на думи.
Просто може цикълът да започва от 1. Нулата така или иначе е вече проверена. Не ме притеснява какво ще намери на -1. Каквото и да намери, първият символ ще си остане главна буква. Условието не е да сваляме съществуващите в текста главни букви...
Хубаво е с хора
Притеснява, не притеснява...Това е математика. 2 пъти проверяваш 1вата буква, един път извън цикъла и втори път в цикъла. Така ли е? Какъв е смисъла да я проверяваш 2 пъти?
И 2рата проверка е научно казано ундефинед. Да кажат знаещите.
И не си мисли че се заяждам с тебе. Аз също се уча.
georgi.stef.georgiev Още веднъж мерси. Много е приятно като има кой да помогне и да обясни :)
Здравей @ Bobosam !
Опитвах да използвам regex_replace, ама срещнах 2 проблема:
Много е бавно. Нямам изпълнение под 3 сек., а условието е до 0,1 сек.
Другият проблем е, че ме праща в някакви хедъри. Дали е от настройките на компилатора ми или грешно го използвам:
...
string text = "kid+ding kitt!ens W123456";
ostringstream separatedWords;
regex toReplace(".|,|;|!|?");
regex_replace(separatedWords, text.begin(), text.end(), toReplace, " ");