Get last word of the string
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
8
down vote
favorite
We have to print the last word of the given string. How to improve and optimise this code?
#include <iostream>
std::string get_last_word(const std::string& str)
if (str.length() == 0)
std::cerr << "No stringn";
return 0;
int len = str.length();
int i = len - 1;
while (i >= 0 && str[i] != ' ')
i--;
std::string last_word;
for (int j = i + 1; j < len; j++)
last_word += str[j];
return last_word;
int main()
std::string str;
std::cout << "Enter string :n";
std::getline(std::cin, str);
std::cout << "Last word :n";
std::cout << get_last_word(str);
std::cout << std::endl;
c++
add a comment |Â
up vote
8
down vote
favorite
We have to print the last word of the given string. How to improve and optimise this code?
#include <iostream>
std::string get_last_word(const std::string& str)
if (str.length() == 0)
std::cerr << "No stringn";
return 0;
int len = str.length();
int i = len - 1;
while (i >= 0 && str[i] != ' ')
i--;
std::string last_word;
for (int j = i + 1; j < len; j++)
last_word += str[j];
return last_word;
int main()
std::string str;
std::cout << "Enter string :n";
std::getline(std::cin, str);
std::cout << "Last word :n";
std::cout << get_last_word(str);
std::cout << std::endl;
c++
add a comment |Â
up vote
8
down vote
favorite
up vote
8
down vote
favorite
We have to print the last word of the given string. How to improve and optimise this code?
#include <iostream>
std::string get_last_word(const std::string& str)
if (str.length() == 0)
std::cerr << "No stringn";
return 0;
int len = str.length();
int i = len - 1;
while (i >= 0 && str[i] != ' ')
i--;
std::string last_word;
for (int j = i + 1; j < len; j++)
last_word += str[j];
return last_word;
int main()
std::string str;
std::cout << "Enter string :n";
std::getline(std::cin, str);
std::cout << "Last word :n";
std::cout << get_last_word(str);
std::cout << std::endl;
c++
We have to print the last word of the given string. How to improve and optimise this code?
#include <iostream>
std::string get_last_word(const std::string& str)
if (str.length() == 0)
std::cerr << "No stringn";
return 0;
int len = str.length();
int i = len - 1;
while (i >= 0 && str[i] != ' ')
i--;
std::string last_word;
for (int j = i + 1; j < len; j++)
last_word += str[j];
return last_word;
int main()
std::string str;
std::cout << "Enter string :n";
std::getline(std::cin, str);
std::cout << "Last word :n";
std::cout << get_last_word(str);
std::cout << std::endl;
c++
asked Apr 15 at 7:04
coder
911425
911425
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
13
down vote
accepted
Be careful with types. For example, your get_last_word function is meant to return a string but in your error case you return 0. If you want to return an empty string, use return "";
I'm guessing that you might be working under restrictions about what library functions you're allowed to use here, but you don't say so.
If you're allowed to use anything in the standard library, have a look at std::string::find_last_of
as a replacement for your first loop.
Similarly, look at std::string::substr
as a replacement for your second loop. Building a string one character at a time is generally discouraged because it's quite inefficient. Something like substr
will be more efficient because it can, for example, allocate all the memory needed by your string in one go.
Is there a notable difference betweenfind_last_of
andrfind
? I'm fairly certain the entire task can be done with something likeline.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
rfind
searches for a character sequence (which can be of length one if you just want one character)find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you wantrfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you wantfind_last_of
. Either should work if you want a single option for a single character.
â Josiah
Apr 15 at 20:38
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
It looks to me that at least in libcxx, callingfind_last_of
with a single char falls back torfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.
â Josiah
Apr 15 at 22:17
add a comment |Â
up vote
9
down vote
Looking at the code, it seems like you are reinventing the wheel.
See the answer of @Josiah for some alternatives to use the standard library.
Assuming this ain't possible for some reason, lets say its implemented badly, I would improve some smaller things.
Before giving some improvements, make sure to measure!
Is this code only used once? Does it only take 1% of the time? Is the example code the only use? Than don't spend time on this!
Add preconditions
Currently your function accepts an empty string.
When this is encountered, you always get an error message.
If you somewhere want to handle this differently, it should be checked twice.
Or in case you know it can't be empty, it still is checked when not needed.
Instead, you could write:
assert(!str.empty() && "An empty string should not be passed");
If your specific example, you'll have to write the check in the main function. However, in that case, you could use an alternative way of handling it. For example:
std::string str;
do
std::cout << "Enter string :n";
std::getline(std::cin, str);
while (str.empty());
Memory allocations
std::string
can have short string optimization. Although, for large strings, this might allocate memory. If you append character by character, this might reallocate.
To prevent this reallocation, you can reserve the string:
last_word.reserve(str.size() + 1 /*Null terminator*/);
The code above would be wonderful for a vector, when you have at least 1 element. However, as we have short string optimization, this might allocate, while the result won't require it.
last_word.reserve(len - j); // To be verified with null terminator.
If really performance critical, you might want to check the implementation of the standard library as they are allowed to reserve more characters than you pass. So, they can add 1 for the null terminator. (libstdc++ and MSVC do so, I read)
Output argument
In order to not recreate a string, you can manipulate the original string.
With the erase
method, you can (in bulk) remove all previous characters at once.
This will work when you don't need that argument any more, however, this might add unwanted overhead if you do or don't have a std::string instance.
string_view
std::string_view
was added in a recent c++ version, this will behave as a string, although, doesn't store the content in it.
Returning a string_view might prevent copying over the characters into the std::string
. Same can be said for the input argument.
Warning: This is error prone in case you work with temporaries.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
13
down vote
accepted
Be careful with types. For example, your get_last_word function is meant to return a string but in your error case you return 0. If you want to return an empty string, use return "";
I'm guessing that you might be working under restrictions about what library functions you're allowed to use here, but you don't say so.
If you're allowed to use anything in the standard library, have a look at std::string::find_last_of
as a replacement for your first loop.
Similarly, look at std::string::substr
as a replacement for your second loop. Building a string one character at a time is generally discouraged because it's quite inefficient. Something like substr
will be more efficient because it can, for example, allocate all the memory needed by your string in one go.
Is there a notable difference betweenfind_last_of
andrfind
? I'm fairly certain the entire task can be done with something likeline.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
rfind
searches for a character sequence (which can be of length one if you just want one character)find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you wantrfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you wantfind_last_of
. Either should work if you want a single option for a single character.
â Josiah
Apr 15 at 20:38
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
It looks to me that at least in libcxx, callingfind_last_of
with a single char falls back torfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.
â Josiah
Apr 15 at 22:17
add a comment |Â
up vote
13
down vote
accepted
Be careful with types. For example, your get_last_word function is meant to return a string but in your error case you return 0. If you want to return an empty string, use return "";
I'm guessing that you might be working under restrictions about what library functions you're allowed to use here, but you don't say so.
If you're allowed to use anything in the standard library, have a look at std::string::find_last_of
as a replacement for your first loop.
Similarly, look at std::string::substr
as a replacement for your second loop. Building a string one character at a time is generally discouraged because it's quite inefficient. Something like substr
will be more efficient because it can, for example, allocate all the memory needed by your string in one go.
Is there a notable difference betweenfind_last_of
andrfind
? I'm fairly certain the entire task can be done with something likeline.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
rfind
searches for a character sequence (which can be of length one if you just want one character)find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you wantrfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you wantfind_last_of
. Either should work if you want a single option for a single character.
â Josiah
Apr 15 at 20:38
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
It looks to me that at least in libcxx, callingfind_last_of
with a single char falls back torfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.
â Josiah
Apr 15 at 22:17
add a comment |Â
up vote
13
down vote
accepted
up vote
13
down vote
accepted
Be careful with types. For example, your get_last_word function is meant to return a string but in your error case you return 0. If you want to return an empty string, use return "";
I'm guessing that you might be working under restrictions about what library functions you're allowed to use here, but you don't say so.
If you're allowed to use anything in the standard library, have a look at std::string::find_last_of
as a replacement for your first loop.
Similarly, look at std::string::substr
as a replacement for your second loop. Building a string one character at a time is generally discouraged because it's quite inefficient. Something like substr
will be more efficient because it can, for example, allocate all the memory needed by your string in one go.
Be careful with types. For example, your get_last_word function is meant to return a string but in your error case you return 0. If you want to return an empty string, use return "";
I'm guessing that you might be working under restrictions about what library functions you're allowed to use here, but you don't say so.
If you're allowed to use anything in the standard library, have a look at std::string::find_last_of
as a replacement for your first loop.
Similarly, look at std::string::substr
as a replacement for your second loop. Building a string one character at a time is generally discouraged because it's quite inefficient. Something like substr
will be more efficient because it can, for example, allocate all the memory needed by your string in one go.
edited Apr 15 at 7:31
ÃÂìýÃÂñ á¿¥Ã栨Â
3,82431126
3,82431126
answered Apr 15 at 7:25
Josiah
3,182326
3,182326
Is there a notable difference betweenfind_last_of
andrfind
? I'm fairly certain the entire task can be done with something likeline.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
rfind
searches for a character sequence (which can be of length one if you just want one character)find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you wantrfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you wantfind_last_of
. Either should work if you want a single option for a single character.
â Josiah
Apr 15 at 20:38
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
It looks to me that at least in libcxx, callingfind_last_of
with a single char falls back torfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.
â Josiah
Apr 15 at 22:17
add a comment |Â
Is there a notable difference betweenfind_last_of
andrfind
? I'm fairly certain the entire task can be done with something likeline.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
rfind
searches for a character sequence (which can be of length one if you just want one character)find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you wantrfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you wantfind_last_of
. Either should work if you want a single option for a single character.
â Josiah
Apr 15 at 20:38
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
It looks to me that at least in libcxx, callingfind_last_of
with a single char falls back torfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.
â Josiah
Apr 15 at 22:17
Is there a notable difference between
find_last_of
and rfind
? I'm fairly certain the entire task can be done with something like line.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
Is there a notable difference between
find_last_of
and rfind
? I'm fairly certain the entire task can be done with something like line.substr(line.rfind(" ") + 1)
â yuri
Apr 15 at 12:14
rfind
searches for a character sequence (which can be of length one if you just want one character) find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you want rfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you want find_last_of
. Either should work if you want a single option for a single character.â Josiah
Apr 15 at 20:38
rfind
searches for a character sequence (which can be of length one if you just want one character) find_last_of
does not do sequences, it searches for a character matching a pattern. If you want to find the last time the word 'apple' appears in a text, you want rfind
. If you want the last time a full stop, exclamation mark, or question mark appears in a text, you want find_last_of
. Either should work if you want a single option for a single character.â Josiah
Apr 15 at 20:38
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
As to the single line solution, that might suffice for many cases but I suspect needs special handling for the case where there are no spaces in the string.
â Josiah
Apr 15 at 20:41
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
I was more interested in performance differences; The code in the OP uses space as delimiter so for that case it'd be fine.
â yuri
Apr 15 at 21:05
It looks to me that at least in libcxx, calling
find_last_of
with a single char falls back to rfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.â Josiah
Apr 15 at 22:17
It looks to me that at least in libcxx, calling
find_last_of
with a single char falls back to rfind
. On that basis, I feel comfortable saying the performance should be identical. Obviously different libraries could differ.â Josiah
Apr 15 at 22:17
add a comment |Â
up vote
9
down vote
Looking at the code, it seems like you are reinventing the wheel.
See the answer of @Josiah for some alternatives to use the standard library.
Assuming this ain't possible for some reason, lets say its implemented badly, I would improve some smaller things.
Before giving some improvements, make sure to measure!
Is this code only used once? Does it only take 1% of the time? Is the example code the only use? Than don't spend time on this!
Add preconditions
Currently your function accepts an empty string.
When this is encountered, you always get an error message.
If you somewhere want to handle this differently, it should be checked twice.
Or in case you know it can't be empty, it still is checked when not needed.
Instead, you could write:
assert(!str.empty() && "An empty string should not be passed");
If your specific example, you'll have to write the check in the main function. However, in that case, you could use an alternative way of handling it. For example:
std::string str;
do
std::cout << "Enter string :n";
std::getline(std::cin, str);
while (str.empty());
Memory allocations
std::string
can have short string optimization. Although, for large strings, this might allocate memory. If you append character by character, this might reallocate.
To prevent this reallocation, you can reserve the string:
last_word.reserve(str.size() + 1 /*Null terminator*/);
The code above would be wonderful for a vector, when you have at least 1 element. However, as we have short string optimization, this might allocate, while the result won't require it.
last_word.reserve(len - j); // To be verified with null terminator.
If really performance critical, you might want to check the implementation of the standard library as they are allowed to reserve more characters than you pass. So, they can add 1 for the null terminator. (libstdc++ and MSVC do so, I read)
Output argument
In order to not recreate a string, you can manipulate the original string.
With the erase
method, you can (in bulk) remove all previous characters at once.
This will work when you don't need that argument any more, however, this might add unwanted overhead if you do or don't have a std::string instance.
string_view
std::string_view
was added in a recent c++ version, this will behave as a string, although, doesn't store the content in it.
Returning a string_view might prevent copying over the characters into the std::string
. Same can be said for the input argument.
Warning: This is error prone in case you work with temporaries.
add a comment |Â
up vote
9
down vote
Looking at the code, it seems like you are reinventing the wheel.
See the answer of @Josiah for some alternatives to use the standard library.
Assuming this ain't possible for some reason, lets say its implemented badly, I would improve some smaller things.
Before giving some improvements, make sure to measure!
Is this code only used once? Does it only take 1% of the time? Is the example code the only use? Than don't spend time on this!
Add preconditions
Currently your function accepts an empty string.
When this is encountered, you always get an error message.
If you somewhere want to handle this differently, it should be checked twice.
Or in case you know it can't be empty, it still is checked when not needed.
Instead, you could write:
assert(!str.empty() && "An empty string should not be passed");
If your specific example, you'll have to write the check in the main function. However, in that case, you could use an alternative way of handling it. For example:
std::string str;
do
std::cout << "Enter string :n";
std::getline(std::cin, str);
while (str.empty());
Memory allocations
std::string
can have short string optimization. Although, for large strings, this might allocate memory. If you append character by character, this might reallocate.
To prevent this reallocation, you can reserve the string:
last_word.reserve(str.size() + 1 /*Null terminator*/);
The code above would be wonderful for a vector, when you have at least 1 element. However, as we have short string optimization, this might allocate, while the result won't require it.
last_word.reserve(len - j); // To be verified with null terminator.
If really performance critical, you might want to check the implementation of the standard library as they are allowed to reserve more characters than you pass. So, they can add 1 for the null terminator. (libstdc++ and MSVC do so, I read)
Output argument
In order to not recreate a string, you can manipulate the original string.
With the erase
method, you can (in bulk) remove all previous characters at once.
This will work when you don't need that argument any more, however, this might add unwanted overhead if you do or don't have a std::string instance.
string_view
std::string_view
was added in a recent c++ version, this will behave as a string, although, doesn't store the content in it.
Returning a string_view might prevent copying over the characters into the std::string
. Same can be said for the input argument.
Warning: This is error prone in case you work with temporaries.
add a comment |Â
up vote
9
down vote
up vote
9
down vote
Looking at the code, it seems like you are reinventing the wheel.
See the answer of @Josiah for some alternatives to use the standard library.
Assuming this ain't possible for some reason, lets say its implemented badly, I would improve some smaller things.
Before giving some improvements, make sure to measure!
Is this code only used once? Does it only take 1% of the time? Is the example code the only use? Than don't spend time on this!
Add preconditions
Currently your function accepts an empty string.
When this is encountered, you always get an error message.
If you somewhere want to handle this differently, it should be checked twice.
Or in case you know it can't be empty, it still is checked when not needed.
Instead, you could write:
assert(!str.empty() && "An empty string should not be passed");
If your specific example, you'll have to write the check in the main function. However, in that case, you could use an alternative way of handling it. For example:
std::string str;
do
std::cout << "Enter string :n";
std::getline(std::cin, str);
while (str.empty());
Memory allocations
std::string
can have short string optimization. Although, for large strings, this might allocate memory. If you append character by character, this might reallocate.
To prevent this reallocation, you can reserve the string:
last_word.reserve(str.size() + 1 /*Null terminator*/);
The code above would be wonderful for a vector, when you have at least 1 element. However, as we have short string optimization, this might allocate, while the result won't require it.
last_word.reserve(len - j); // To be verified with null terminator.
If really performance critical, you might want to check the implementation of the standard library as they are allowed to reserve more characters than you pass. So, they can add 1 for the null terminator. (libstdc++ and MSVC do so, I read)
Output argument
In order to not recreate a string, you can manipulate the original string.
With the erase
method, you can (in bulk) remove all previous characters at once.
This will work when you don't need that argument any more, however, this might add unwanted overhead if you do or don't have a std::string instance.
string_view
std::string_view
was added in a recent c++ version, this will behave as a string, although, doesn't store the content in it.
Returning a string_view might prevent copying over the characters into the std::string
. Same can be said for the input argument.
Warning: This is error prone in case you work with temporaries.
Looking at the code, it seems like you are reinventing the wheel.
See the answer of @Josiah for some alternatives to use the standard library.
Assuming this ain't possible for some reason, lets say its implemented badly, I would improve some smaller things.
Before giving some improvements, make sure to measure!
Is this code only used once? Does it only take 1% of the time? Is the example code the only use? Than don't spend time on this!
Add preconditions
Currently your function accepts an empty string.
When this is encountered, you always get an error message.
If you somewhere want to handle this differently, it should be checked twice.
Or in case you know it can't be empty, it still is checked when not needed.
Instead, you could write:
assert(!str.empty() && "An empty string should not be passed");
If your specific example, you'll have to write the check in the main function. However, in that case, you could use an alternative way of handling it. For example:
std::string str;
do
std::cout << "Enter string :n";
std::getline(std::cin, str);
while (str.empty());
Memory allocations
std::string
can have short string optimization. Although, for large strings, this might allocate memory. If you append character by character, this might reallocate.
To prevent this reallocation, you can reserve the string:
last_word.reserve(str.size() + 1 /*Null terminator*/);
The code above would be wonderful for a vector, when you have at least 1 element. However, as we have short string optimization, this might allocate, while the result won't require it.
last_word.reserve(len - j); // To be verified with null terminator.
If really performance critical, you might want to check the implementation of the standard library as they are allowed to reserve more characters than you pass. So, they can add 1 for the null terminator. (libstdc++ and MSVC do so, I read)
Output argument
In order to not recreate a string, you can manipulate the original string.
With the erase
method, you can (in bulk) remove all previous characters at once.
This will work when you don't need that argument any more, however, this might add unwanted overhead if you do or don't have a std::string instance.
string_view
std::string_view
was added in a recent c++ version, this will behave as a string, although, doesn't store the content in it.
Returning a string_view might prevent copying over the characters into the std::string
. Same can be said for the input argument.
Warning: This is error prone in case you work with temporaries.
answered Apr 15 at 8:17
JVApen
516212
516212
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192097%2fget-last-word-of-the-string%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password