我刚刚和朋友讨论了检查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;
}
我正在寻找有关此代码的反馈,也欢迎更有效的方法来执行此任务。
答案 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
}
这样可以修剪所有换行符,空格和制表符。