Jump to content
  • Advertisement
Sign in to follow this  
monchito

how do I know if std::string really empty?

This topic is 3093 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I want to know how can i get an empty srting when there are no digits or alpha characters. Can't use str.empty() if spaces or tabs are part of the string?

Share this post


Link to post
Share on other sites
Advertisement
You can do something like:

bool isEmpty(const std::string &str)
{
for (int i = 0; i < str.size(); ++i)
// check if the character is inside the a-z or A-Z or 0-9
if ((str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z') || (str >= '0' && str <= '9'))
return false; // we found an alphanumeric character

return true;
}


Edit: Made several edits to fix the logic a bit.

Share this post


Link to post
Share on other sites
Quote:
Original post by nullsquared
You can do something like:

bool isEmpty(const std::string &str)
{
for (int i = 0; i < str.size(); ++i)
// check if the character is inside the a-z or A-Z or 0-9
if ((str >= 'a' && str <= 'z') || (str >= 'A' && str <= 'Z') || (str >= '0' && str <= '9'))
return false; // we found an alphanumeric character

return true;
}


Edit: Made several edits to fix the logic a bit.


Your code is buggy, at least you should have used the functions from cctype.

Further, I guess monchito is looking for a function that checks whether a string is made of zero or more whitespace, and not for a string that does not include any of [a-zA-Z0-9], so your code is wrong by principle. E.g. it fails for "!", for which you return true, but where the OP wants false.


#include <string>
bool is_whitespace_or_empty (std::string const &str) {
if (str.empty()) return true;
for (std::string::iterator it=str.begin();
it != str.end();
++it
) {
switch (*it) {
case ' ':
case '\n':
case '\t': break;
default: return false;
};
}
return true;
}


Let only pass what you want, and don't even try to block what is not wanted (think of unicode!). See also "Pretty Basic Validation", which is similar to your post.

Fix in spirit of my above statement:

#include <cctype>
#include <string>
bool is_whitespace_or_empty (std::string const &str) {
if (str.empty()) return true;
for (std::string::iterator it=str.begin();
it != str.end();
++it
) {
if (!std::isspace (*it)) return false;
}
return true;
}



(disclaimer: functions not tested)

Share this post


Link to post
Share on other sites

bool is_empty(const std::string &value)
{
return value.find_first_not_of(" \t\n\r") == std::string::npos;
}




Does this work? I can't test it at the moment...

Share this post


Link to post
Share on other sites
Should work.

I was going to suggest something that takes advantage of isspace, but it didn't turn out particularly elegant.


bool is_empty_or_ws(const std::string& s)
{
int (*spaces)(int) = &std::isspace; //this sucker is overloaded
return s.empty() || std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(spaces))) == s.end();
}

Share this post


Link to post
Share on other sites
Quote:
Original post by visitor
Should work.

I was going to suggest something that takes advantage of isspace, but it didn't turn out particularly elegant.


bool is_empty_or_ws(const std::string& s)
{
int (*spaces)(int) = &std::isspace; //this sucker is overloaded
return s.empty() || std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(spaces))) == s.end();
}


IMHO, using trivial algorithms like std::find_if often makes things more obscure than the loops they replace:

bool is_empty_or_ws(const std::string &s) {
for (std::string::const_iterator it=s.begin(), end=s.end(); it!=end; ++it) {
if (!std::isspace(*it))
return false;
}
return true;
}



Share this post


Link to post
Share on other sites
IMO you should write the following functions, as they are extremely useful:


template<class InIter, class Pred>
bool exists(InIter first, InIter second, Pred p)
{
while (first != second)
{
if (p(*first)) return true;
++first;
}
return false;
}

template<class InIter, class Pred>
bool every(InIter first, InIter second, Pred p)
{
while (first != second)
{
if (!p(*first)) return false;
++first;
}
return true;
}




Then you can write your function like this:


if (!every(str.begin(), str.end(), std::isspace))
{
//There's a non whitespace character
}





Plus, you can use these two generic template functions for just about anything.

Share this post


Link to post
Share on other sites
Quote:
Original post by monchito
Hi
I want to know how can i get an empty srting when there are no
digits or alpha characters. Can't use str.empty() if spaces or tabs
are part of the string?


0) which language? The rest assumes C++.

1) Are you checking for string having length of 0, or whether string contains only alphanumeric symbols
2) Do you use US ASCII set, specific codepage, or unicode?
3) Which characters do you wish to ignore? Aside from space and tab, there are other invisible characters which may appear, including \n and \0
4) How is string represented? Using std::basic_string variants? C-style string?

Share this post


Link to post
Share on other sites
Quote:
Original post by cache_hit
IMO you should write the following functions, as they are extremely useful:

*** Source Snippet Removed ***

Then you can write your function like this:

*** Source Snippet Removed ***


Plus, you can use these two generic template functions for just about anything.


Oh, that is pretty neat. However, it's still a lot less flexible than writing a loop.

For instance (real-world example), I may want to consider a line to be blank if the first non-space character is a '#', because we'll accept Perl-style comments.

bool is_blank_or_comment(const std::string &s) {
for (std::string::const_iterator it=s.begin(), end=s.end(); it!=end; ++it) {
if (*it=='#')
return true;
if (!std::isspace(*it))
return false;
}
return true;
}




Do you have a good way to write something like that?

Share this post


Link to post
Share on other sites
Quote:
Original post by alvaro
Oh, that is pretty neat. However, it's still a lot less flexible than writing a loop.

For instance (real-world example), I may want to consider a line to be blank if the first non-space character is a '#', because we'll accept Perl-style comments.

*** Source Snippet Removed ***

Do you have a good way to write something like that?


Loops are definitely more flexible. For the concrete example you mention I'd just use std::string::find_first_not_of and check whether it's equal to '#'.

But yea, in general those types of problems require that the loop maintain state, which is why they're more flexible. Sometimes you can encapsulate this state in an accumulator that is threaded through the operation (usually called a 'fold' in the context of functional programming), or a more simple accumulation like what you can get with std::accumulate.

But sometimes you need a hand-rolled loop, as you mention.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!