私はソフトウェアを書いており、libcurlを使用してWebページから取得したデータを処理する必要があります。データを取得すると、何らかの理由で余分な改行が含まれています。文字、数字、スペースのみを許可する方法を理解する必要があります。そして、改行を含むその他すべてを削除します。これを行う簡単な方法はありますか?ありがとう。
char
を取り、その文字を削除する場合はtrue
を返し、保持する場合はfalse
を返す関数を記述します。
bool my_predicate(char c);
次に、std::remove_if
アルゴリズムを使用して、不要な文字を文字列から削除します。
std::string s = "my data";
s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());
要件によっては、独自の述語を作成する代わりに、std::isalnum
などの標準ライブラリの述語のいずれかを使用できる場合があります(英数字とスペースを一致させる必要があると述べたため、これは正確にできない場合があります)必要なものに合わせてください)。
標準ライブラリstd::isalnum
関数を使用する場合は、C標準ライブラリヘッダーstd::isalnum
(使用する関数)の<cctype>
関数を明確にするキャストが必要です。 )およびC++標準ライブラリヘッダーのstd::isalnum
<locale>
(ロケール固有の文字列処理を実行する場合を除いて、これは使用するものではありません):
s.erase(std::remove_if(s.begin(), s.end(), (int(*)(int))std::isalnum), s.end());
これは、任意のシーケンスコンテナ(std::string
、std::vector
、std::deque
を含む)でも同様に機能します。このイディオムは一般に「消去/削除」イディオムと呼ばれます。 std::remove_if
アルゴリズムは、通常の配列でも機能します。 std::remove_if
は、シーケンスを1回だけ通過するため、時間の複雑さが線形になります。
以前のstd::isalnum
の使用は、_nary引数を渡さないとstd::ptr_fun
でコンパイルできません。したがって、ラムダ関数を使用したこのソリューションは正しい答えをカプセル化する必要があります。
s.erase(std::remove_if(s.begin(), s.end(),
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
erase
を使用している場合は、常にループして、string
の英数字以外のすべての文字だけをループできます。
#include <cctype>
size_t i = 0;
size_t len = str.length();
while(i < len){
if (!isalnum(str[i]) || str[i] == ' '){
str.erase(i,1);
len--;
}else
i++;
}
標準Libの優れた人なら、ループなしでこれを実行できるでしょう。
char
バッファのみを使用している場合はループすることができ、文字が英数字ではない場合は、後ろにあるすべての文字を1つ後ろにシフトします(問題の文字を上書きします)。
#include <cctype>
size_t buflen = something;
for (size_t i = 0; i < buflen; ++i)
if (!isalnum(buf[i]) || buf[i] != ' ')
memcpy(buf[i], buf[i + 1], --buflen - i);
remove_copy_if 標準アルゴリズムは、ケースに非常に適しています。
#include <cctype>
#include <string>
#include <functional>
std::string s = "Hello World!";
s.erase(std::remove_if(s.begin(), s.end(),
std::not1(std::ptr_fun(std::isalnum)), s.end()), s.end());
std::cout << s << std::endl;
結果:
"HelloWorld"
isalnum
を使用して各文字が英数字であるかどうかを判別し、次にptr_fun
を使用して関数をnot1
に渡します。これにより、戻り値ではなく、英数字のみが残ります。欲しいです。
この方法で削除消去アルゴリズムを使用できます-
// Removes all punctuation
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());
James McNellisのコードをもう少し拡張するだけです。彼の機能は、非文字ではなく文字を削除することです。
文字列からnon-alnum文字を削除します。 (alnum =アルファベット順または数値)
関数を宣言します(渡されたcharがalnumでない場合、isalnumは0を返します)
bool isNotAlnum(char c) {
return isalnum(c) == 0;
}
そしてこれを書いてください
s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end());
次に、あなたの文字列はalnum文字のみです。
上記の解決策
s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());
は非常にいいですが、残念ながらVisual Studio(デバッグモード)で 'Ñ'のような文字を処理することはできません。次の行が原因です。
_ASSERTE((unsigned)(c + 1) <= 256)
isctype.c内
だから、私はこのようなものをお勧めします:
inline int my_ispunct( int ch )
{
return std::ispunct(unsigned char(ch));
}
...
s.erase( std::remove_if(s.begin(), s.end(), &my_ispunct), s.end());
以下のコードは、与えられた文字列s
に対してうまく機能するはずです。 <algorithm>
および<locale>
ライブラリを利用しています。
std::string s("He!!llo Wo,@rld! 12 453");
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalnum(c); }), s.end());
次は私のために働きます。
str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end());
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end());
void remove_spaces(string data)
{ int i=0,j=0;
while(i<data.length())
{
if (isalpha(data[i]))
{
data[i]=data[i];
i++;
}
else
{
data.erase(i,1);}
}
cout<<data;
}