C ++ 'da bir dizeden boşluk kaldırmanın tercih edilen yolu nedir? Tüm karakterler arasında döngü ve yeni bir dize oluşturmak, ama daha iyi bir yolu var mı?
C ++ 'da bir dizeden boşluk kaldırmanın tercih edilen yolu nedir? Tüm karakterler arasında döngü ve yeni bir dize oluşturmak, ama daha iyi bir yolu var mı?
Yanıtlar:
Yapılacak en iyi şey algoritma remove_if
ve isspace kullanmaktır :
remove_if(str.begin(), str.end(), isspace);
Şimdi algoritmanın kendisi kabı değiştiremez (sadece değerleri değiştirir), bu yüzden aslında değerleri karıştırır ve sonun olması gereken yere bir işaretçi döndürür. Bu nedenle, kabın uzunluğunu gerçekten değiştirmek için string :: erase komutunu çağırmalıyız:
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
Ayrıca remove_if'in verilerin en fazla bir kopyasını oluşturacağını da not etmeliyiz. İşte örnek bir uygulama:
template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
T dest = beg;
for (T itr = beg;itr != end; ++itr)
if (!pred(*itr))
*(dest++) = *itr;
return dest;
}
erase
sonradan aramanız gerektiğini belirtmektedir . Bu doğru sonucu döndürür.
isspace
orijinal 7 bit ASCII hariç tüm karakter kümeleri için UB'dir. C99 §7.4 / 1. o sürpriz değil o Çok Kötü Önerileri olmanın rağmen artık 71 oy ayarlamak için upvoted oldu bana.
isspace
yanıttaki kod, ASCII olmayan tüm karakterler için uygulamada varsayılan imzalama seçeneğiyle negatif değerleri ( EOF'dan farklı) geçirir char
. Böylece tanımlanmamış bir davranışı vardır . Tekrarlıyorum çünkü bu gerçeği gürültüde boğmak için kasıtlı bir girişimden şüpheleniyorum.
std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());
<algorithm>
çalışması için dahil etmeniz gerekir .
Gönderen gamedev
string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());
::isspace
UB olduğunu unutmayın.
Boost String Algo kullanabilir misiniz? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573
erase_all(str, " ");
remove_if(str.begin(), str.end(), isspace);
Matt Price'ın bahsettiğinden daha yavaş . Nedenini bilmiyorum. Aslında, STL alternatifleri olan tüm takviye maddeleri, karşılık gelen gcc olanlardan daha yavaştır (Test ettiğim her şey). Bazıları son derece yavaş! (unordered_map eklerinde 5 kata kadar) Belki de paylaşılan ortamın CPU önbelleği veya bunun gibi bir şey olabilir.
Kırpmak için boost dize algoritmaları kullanın :
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
// ...
string str1(" hello world! ");
trim(str1); // str1 == "hello world!"
Bu çözümü bir karakteri kaldırmak için kullanabilirsiniz:
#include <algorithm>
#include <string>
using namespace std;
str.erase(remove(str.begin(), str.end(), char_to_remove), str.end());
Merhaba, böyle bir şey yapabilirsiniz. Bu işlev tüm boşlukları siler.
string delSpaces(string &str)
{
str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
return str;
}
Gereksiz tüm alanları silen başka bir işlev daha yaptım.
string delUnnecessary(string &str)
{
int size = str.length();
for(int j = 0; j<=size; j++)
{
for(int i = 0; i <=j; i++)
{
if(str[i] == ' ' && str[i+1] == ' ')
{
str.erase(str.begin() + i);
}
else if(str[0]== ' ')
{
str.erase(str.begin());
}
else if(str[i] == '\0' && str[i-1]== ' ')
{
str.erase(str.end() - 1);
}
}
}
return str;
}
string replaceinString(std::string str, std::string tofind, std::string toreplace)
{
size_t position = 0;
for ( position = str.find(tofind); position != std::string::npos; position = str.find(tofind,position) )
{
str.replace(position ,1, toreplace);
}
return(str);
}
kullanın:
string replace = replaceinString(thisstring, " ", "%20");
string replace2 = replaceinString(thisstring, " ", "-");
string replace3 = replaceinString(thisstring, " ", "+");
Bunu kolay bir makro ile yapmak istiyorsanız, işte bir tane:
#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end())
Bu #include <string>
tabii ki yaptığınızı varsayar .
Öyle söyle:
std::string sName = " Example Name ";
REMOVE_SPACES(sName);
printf("%s",sName.c_str()); // requires #include <stdio.h>
Aşağıdaki çalışmayı uzun süre kullandım - karmaşıklığından emin değilim.
s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return (f==' '||s==' ');}),s.end());
Eğer karakteri kaldırın istediğimde ' '
örnek için ve bazı -
kullanım
s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return ((f==' '||s==' ')||(f=='-'||s=='-'));}),s.end());
aynı şekilde sadece ||
kaldırmak istediğiniz karakter sayısı değilse artırmak 1
ancak diğerleri tarafından belirtildiği gibi, silme kaldırma deyimi de iyi görünüyor.
string removeSpaces(string word) {
string newWord;
for (int i = 0; i < word.length(); i++) {
if (word[i] != ' ') {
newWord += word[i];
}
}
return newWord;
}
Bu kod temelde bir dize alır ve içindeki her karakter boyunca yinelenir. Daha sonra, bu dizenin beyaz boşluk olup olmadığını kontrol eder, eğer değilse, karakter yeni bir dizeye eklenir.
#include <algorithm> using namespace std; int main() { . . s.erase( remove( s.begin(), s.end(), ' ' ), s.end() ); . . }
Referans bu forumdan alınmıştır .
C ++ 20'de ücretsiz işlev std :: erase kullanabilirsiniz
std::string str = " Hello World !";
std::erase(str, ' ');
Tam örnek:
#include<string>
#include<iostream>
int main() {
std::string str = " Hello World !";
std::erase(str, ' ');
std::cout << "|" << str <<"|";
}
Yazdırıyorum | böylece başlangıçtaki alanın da kaldırıldığı açıktır.
not: boşluk olarak kabul edilebilecek diğer tüm karakterleri değil, yalnızca alanı kaldırır, bkz. https://en.cppreference.com/w/cpp/string/byte/isspace
Sekmeler ve satır sonları (C ++ 11) gibi tüm boşluk karakterlerini kaldırır :
string str = " \n AB cd \t efg\v\n";
str = regex_replace(str,regex("\\s"),"");
string str = "2C F4 32 3C B9 DE";
str.erase(remove(str.begin(),str.end(),' '),str.end());
cout << str << endl;
çıktı: 2CF4323CB9DE
string removespace(string str)
{
int m = str.length();
int i=0;
while(i<m)
{
while(str[i] == 32)
str.erase(i,1);
i++;
}
}
length()
a değerini döndürür size_t
, değil int
. erase()
alır size_type
, değil int
. Dizin her zaman artırıldığından, art arda iki boşlukla karşılaşılırsa işlev büyük olasılıkla başarısız olur. Bir boşluk kaldırılırsa, döngü dizenin sınırlarının ötesinde okunur. Çok fazla yardıma ihtiyaç duyduğundan muhtemelen bu cevabı silmelisiniz.
Korkarım ki aklıma gelen en iyi çözüm. Ancak, işleri biraz hızlandırmak için gerekli olan minimum belleği önceden ayırmak için Reserve () kullanabilirsiniz. Muhtemelen daha kısa olacak ancak aynı miktarda bellek kaplayan yeni bir dize alacaksınız, ancak yeniden tahsislerden kaçınacaksınız.
DÜZENLEME: Durumunuza bağlı olarak, bu durum etrafta dolaşan karakterlerden daha az ek yüke neden olabilir.
Farklı yaklaşımlar denemeli ve sizin için en iyi olanı görmelisiniz: performans sorunlarınız olmayabilir.