9

我知道有一个“isspace”函数可以检查空格,但这需要我遍历字符串中的每个字符,这可能会影响性能,因为这会被调用很多次。有没有一种快速的方法来检查 std::string 是否只包含空格?

前任:

function("       ") // returns true
function("    4  ") // returns false

我想到的一种解决方案是使用正则表达式,然后我会知道它只包含空格,如果它是错误的......但我不确定这是否比 isspace 函数更有效。

regex: [\w\W] //checks for any word character(a,b,c..) and non-word character([,],..)

提前致谢!

4

5 回答 5

8

任何方法都必然需要查看字符串的每个字符。调用isspace()每个字符的循环非常有效。如果isspace()被编译器内联,那么这将是接近最优的。

当然,一旦看到非空格字符,循环就应该中止。

于 2012-07-11T02:05:46.943 回答
8

使用常规字符串,您能做的最好的将是以下形式:

return string::find_first_not_of("\t\n ") == string::npos;

在最坏的情况下,这将是 O(n),但在不了解字符串的情况下,这将是您能做的最好的事情。

于 2012-07-11T02:08:56.053 回答
2

您正在假设正则表达式不会遍历字符串。正则表达式可能比线性搜索重得多,因为它可能会构建一个 FSM 并基于它进行遍历。

The only way you could speed it up further and make it a near-constant time operation is to amortize the cost by iterating on every update to the string and caching a bool/bit that tracks if there is a space-like character, returning that value if no changes have been made since, and updating that bit whenever you do a write operation to that string. However, this sacrifices/slows that speed of modifying operations in order to increase the speed of your custom has_space().

于 2012-07-11T02:09:31.257 回答
1

For what it's worth, a locale has a function (scan_is) to do things like this:

#include <locale>
#include <iostream>
#include <iomanip>

int main() {

    std::string inputs[] = { 
        "all lower",
        "including a space"
    };

    std::locale loc(std::locale::classic());

    std::ctype_base::mask m = std::ctype_base::space;

    for (int i=0; i<2; i++) {
        char const *pos;
        char const *b = &*inputs[i].begin();
        char const *e = &*inputs[i].end();

        std::cout << "Input: " << std::setw(20) << inputs[i] << ":\t";
        if ((pos=std::use_facet<std::ctype<char> >(loc).scan_is(m, b, e)) == e)
            std::cout << "No space character\n";
        else
            std::cout << "First space character at position " << pos - b << "\n";
    }
    return 0;
}

It's probably open to (a lot of) question whether this gives much (if any) real advantage over using isspace in a loop (or using std::find_if).

于 2012-07-11T02:54:54.237 回答
0

You can also use find_first_not_of if you all the characters to be in a given list. Then you can avoid loops.

Here is an example

#include <string>
#include <algorithm>
using namespace std;
int main()
{
    string str1="      ";
    string str2="      u    ";
    bool ContainsNotBlank1=(str1.find_first_not_of("\t\n ")==string::npos);
    bool ContainsNotBlank2=(str2.find_first_not_of("\t\n ")==string::npos);
    bool ContainsNotBlank3=(str2.find_first_not_of("\t\n u")==string::npos);
    cout << ContainsNotBlank1 <<endl;
    cout << ContainsNotBlank2 <<endl;
    cout << ContainsNotBlank3 <<endl;
    return 0;
}

Output: 1: because only blanks and a tab 0: because u is not into the list "\t\n " 1: because str2 contains blanks, tabs and a u.

Hope it helps Tell me if you have any questions

于 2013-06-19T19:17:19.890 回答