11

文字列に特殊文字が含まれているかどうかを確認するより良い方法があるかどうかを調べています。私の場合、英数字と「_」以外はすべて特殊文字と見なされます。現在、std::string = "!@#$%^&" などの特殊文字を含む文字列があります。次に、std::find_first_of () アルゴリズムを使用して、文字列に特殊文字が存在するかどうかを確認します。

ホワイトリストに基づいてそれを行う方法を考えていました。小文字/大文字、数字、およびアンダースコアを文字列で指定したい (それらをリストしたくない。 [a-zA-Z0-9_] のような種類の ASCII 範囲を指定する方法はありますか? )。どうすればこれを達成できますか?次に、std::find_first_not_of() を使用する予定です。このようにして、私が実際に欲しいものに言及し、反対をチェックすることができます.

4

9 に答える 9

17

試す:

std::string  x(/*Load*/);
if (x.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_") != std::string::npos)
{
    std::cerr << "Error\n";
}

または正規表現をブーストしてみてください:

// Note: \w matches any word character `alphanumeric plus "_"`
boost::regex test("\w+", re,boost::regex::perl);
if (!boost::regex_match(x.begin(), x.end(), test)
{
    std::cerr << "Error\n";
}

// The equivalent to \w should be:
boost::regex test("[A-Za-z0-9_]+", re,boost::regex::perl);   
于 2011-07-07T02:50:33.087 に答える
4

std::stringをコレクションとして扱い、アルゴリズムを使用して、少し違った方法で仕事をすると思います。C++0x ラムダを使用すると、次のようになります。

bool has_special_char(std::string const &str) {
    return std::find_if(str.begin(), str.end(),
        [](unsigned char ch) { return !(isalnum(ch) || ch == '_'); }) != str.end();
}

char少なくとも(not wchar_t)を扱っているときは、通常はテーブル ルックアップを使用するため、(通常は代わりに線形検索を使用する) にisalnum基づくものよりも (かなり) 高速になります。find_first_ofIOW、これは O(N) (N=str.size()) であり、これに基づくものfind_first_ofは O(N*M)、(N=str.size()、M=pattern.size()) になります。

純粋な C でジョブを実行する場合は、scanf理論的には移植性がありませんが、基本的にすべての最近の/人気のあるコンパイラでサポートされている scanset 変換を使用できます。

char junk;
if (sscanf(str, "%*[A-Za-z0-9_]%c", &junk))
    /* it has at least one "special" character
else
    /* no special characters */

ここでの基本的な考え方は非常に単純です: scanset は連続するすべての非特殊文字をスキップし (ただし、*. それが成功した場合、スキップされなかった文字が少なくとも 1 つあったことを意味するため、少なくとも 1 つの特殊文字が必要です。失敗した場合は、scanset 変換が文字列全体に一致したため、すべての文字が「非特殊」だったことを意味します。

公式には、C 標準では、このようにスキャンセット変換に範囲を入れようとすると移植性がないとされています (スキャンセットの先頭または末尾以外の場所に '-' を付けると、実装で定義された動作が得られます)。これに失敗する (Borland の) コンパイラもいくつかありました。これらのコンパイラはA-Z、'A'、'-'、'Z' の 3 つの文字に正確に一致するものとして扱います。現在のほとんどのコンパイラ (または、より正確には、標準ライブラリの実装) は、これが想定するアプローチを採用しています。「AZ」は、任意の大文字に一致します。

于 2011-07-07T05:57:23.583 に答える
3

最初に考慮する必要があるのは、「これはASCIIのみですか」ということです。「はい」と答えた場合は、ASCIIのみを許可するかどうかを実際に検討することをお勧めします。私は現在、最初からユニコードをサポートすることを考えていなかったため、海外市場に参入するのに本当に頭痛の種を抱えている会社で働いています。

そうは言っても、ASCIIを使用すると、アルファ以外の数値を簡単にチェックできます。アスキーチャートを見てください。

http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters

  • 各文字を繰り返します
  • 文字が10進値であるかどうかを確認します48-57、65-90、97-122、または95(アンダースコア)
于 2011-07-07T02:59:33.900 に答える
3

標準の C または C++ を使用して文字範囲を使用してそれを行う方法はありません。すべての文字をリストする必要があります。C 文字列の場合、 と を使用strspn(3)strcspn(3)て、特定の文字セットのメンバーである、またはメンバーではない文字列内の最初の文字を見つけることができます。例えば:

// Test if the given string has anything not in A-Za-z0-9_
bool HasSpecialCharacters(const char *str)
{
    return str[strspn(str, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")] != 0;
}

C++ 文字列の場合、メンバー関数find_first_offind_first_not_ofメンバー関数を同等に使用できます。

もう 1 つのオプションは、isalnum(3)および関連する の関数を使用して<ctype.h>、特定の文字が英数字かどうかをテストすることです。これらの関数はロケールに依存するため、他のロケールでは動作が変わる可能性があることに注意してください。その動作が望ましくない場合は、使用しないでください。それらを使用することを選択した場合は、「アルファベット、数字、またはアンダースコア」をテストする関数がないため、アンダースコアも個別にテストする必要があり、文字列を検索する独自のループもコーディングする必要があります (またはstd::find適切な関数オブジェクトで使用します)。

于 2011-07-07T02:58:45.863 に答える
1

関数 (マクロ) はロケール設定の影響を受けますが、またはisalnum()から関連するものを調査する必要があります。<ctype.h><cctype>

于 2011-07-07T02:51:15.897 に答える
0

これが必要であるが、完全に行き過ぎて正規表現を使用したくない場合、およびテストがASCII文字用であるとすると、find_first_not_of...の文字列を生成する関数を作成するだけです。

#include <iostream>
#include <string>

std::string expand(const char* p)
{
    std::string result;
    while (*p)
        if (p[1] == '-' && p[2])
        {
            for (int c = p[0]; c <= p[2]; ++c)
                result += (char)c;
            p += 3;
        }
        else
            result += *p++;
    return result;
}

int main()
{
    std::cout << expand("A-Za-z0-9_") << '\n';
}
于 2011-07-07T03:10:40.060 に答える
0

使用する

    s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());

    bool my_predicate(char c)
    {
     return !(isalpha(c) || c=='_');
    }

きれいな文字列が得られますs

消去はすべての特殊文字を削除し、my_predicate関数で高度にカスタマイズ可能です。

于 2012-09-23T07:59:28.800 に答える
0

ここでは組み込みの C 機能を使用します。文字列内の各文字を繰り返し処理し、それが true_かどうかを確認します。isalpha(ch)そうである場合は有効であり、そうでない場合は特殊文字です。

于 2011-07-07T02:56:52.790 に答える