检查std :: string是否只有空格的有效方法

时间:2011-06-22 18:39:04

标签: c++ string optimization whitespace

我刚刚和朋友讨论了检查std :: string是否只有空格的最有效方法。他需要在他正在进行的嵌入式项目中执行此操作,显然这种优化对他很重要。

我提出了以下代码,它使用了strtok()

bool has_only_spaces(std::string& str)
{
    char* token = strtok(const_cast<char*>(str.c_str()), " ");

    while (token != NULL)
    {   
        if (*token != ' ')
        {   
            return true;
        }   
    }   
    return false;
}

我正在寻找有关此代码的反馈,也欢迎更有效的方法来执行此任务。

13 个答案:

答案 0 :(得分:81)

if(str.find_first_not_of(' ') != std::string::npos)
{
    // There's a non-space.
}

答案 1 :(得分:41)

在C ++ 11中,可以使用all_of算法:

// Check if s consists only of whitespaces
bool whiteSpacesOnly = std::all_of(s.begin(),s.end(),isspace);

答案 2 :(得分:15)

为什么这么多工作,打字这么多?

bool has_only_spaces(const std::string& str) {
   return str.find_first_not_of (' ') == str.npos;
}

答案 3 :(得分:6)

不是更容易做到:

bool has_only_spaces(const std::string &str)
{
    for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
    {
        if (*it != ' ') return false;
    }
    return true;
}

这样做的好处就是一旦找到非空格字符就立即返回,因此它比检查整个字符串的解决方案更有效率。

答案 4 :(得分:3)

这里只使用STL(需要C ++ 11)

inline bool isBlank(const std::string& s)
{
    return std::all_of(s.cbegin(),s.cend(),[](char c) { return std::isspace(c); });
}

它依赖于以下事实:如果string为空(begin = end),std :: all_of也返回true

这是一个小型测试程序:http://cpp.sh/2tx6

答案 5 :(得分:3)

检查字符串在c ++ 11中是否只有空格:

bool is_whitespace(const std::string& s) {
  return std::all_of(s.begin(), s.end(), isspace);
}

在pre-c ++ 11中:

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

答案 6 :(得分:2)

使用strtok就是那种糟糕的风格! strtok 修改它标记的缓冲区(它用\ 0替换分隔符字符)。

这是一个非修改版本。

const char* p = str.c_str();
while(*p == ' ') ++p;
return *p != 0;

如果您在机器字块中迭代它,它可以进一步优化。为了便于携带,您还必须考虑对齐。

答案 7 :(得分:1)

你不太可能为此打败编译器优化的朴素算法,例如

string::iterator it(str.begin()), end(str.end())    
for(; it != end && *it == ' '; ++it);
return it == end;

编辑:实际上 - 有一种更快的方法(取决于字符串和可用内存的大小)..

std::string ns(str.size(), ' '); 
return ns == str;
编辑:实际上面并不快......它太愚蠢......坚持天真的实现,优化器将全部用完......

再次编辑:该死,我想最好看一下std::string中的函数

return str.find_first_not_of(' ') == string::npos;

答案 8 :(得分:1)

我不赞成你上面的const_casting并使用strtok。

std :: string可以包含嵌入的空值,但是在你点击NULL终结符之前我们假设它将是所有的ASCII 32字符。

你能解决这个问题的一种方法是使用一个简单的循环,我将假设为const char *。

bool all_spaces( const char * v )
{
   for ( ; *v; ++v )
   {
      if( *v != ' ' )
          return false;
   }
   return true;
}

对于较大的字符串,您可以一次检查字,直到到达最后一个字,然后假设32位字(例如)将为0x20202020,这可能更快。

答案 9 :(得分:1)

类似的东西:

return std::find_if(
            str.begin(), str.end(),
            std::bind2nd( std::not_equal_to<char>(), ' ' ) )
    == str.end();

如果你对白色空间感兴趣,而不仅仅是空间角色, 那么最好的办法是定义一个谓词,然后使用它:

struct IsNotSpace
{
    bool operator()( char ch ) const
    {
        return ! ::is_space( static_cast<unsigned char>( ch ) );
    }
};

如果您正在进行任何文本处理,那么这些简单的集合 谓词将是非常宝贵的(并且它们很容易生成 自动从<ctype.h>)中的函数列表。

答案 10 :(得分:1)

我在编程作业中遇到了类似的问题,这是我在查看其他解决方案后想出的另一个解决方案。在这里,我只是创建一个没有新空格的新句子。如果有双空格,我会直接忽略它们。

字符串语句; 字符串新闻; //重新构造新句子 字符串 dbl = " ";

getline(cin, sentence);

int len = sentence.length();

for(int i = 0; i < len; i++){

//if there are multiple whitespaces, this loop will iterate until there are none, then go back one.
    if (isspace(sentence[i]) && isspace(sentence[i+1])) {do{ 
        i++;
    }while (isspace(sentence[i])); i--;} //here, you have to dial back one to maintain at least one space.  
    
    
    newsent +=sentence[i];
}       

cout << newsent << "\n";

答案 11 :(得分:0)

嗯......我会这样做:

for (auto i = str.begin(); i != str.end() ++i)
    if (!isspace(i))
       return false;

伪代码,isspace位于C ++的cctype中。

编辑:感谢James指出isspace在签名字符上有未定义的行为。

答案 12 :(得分:0)

如果您使用的是CString,则可以执行

CString myString = "    "; // All whitespace
if(myString.Trim().IsEmpty())
{
    // string is all whitespace
}

这样可以修剪所有换行符,空格和制表符。