Bagaimana menghapus semua kemunculan karakter dalam string c ++


101

Saya menggunakan berikut ini:

replace (str1.begin(), str1.end(), 'a' , '')

Tapi ini memberikan kesalahan kompilasi.


8
''memang bukan karakter.
n. 'kata ganti' m.

4
Yah, tentu akan membantu mengetahui kesalahan yang Anda dapatkan.
SBI

3
baiklah, ada banyak konteks di mana mengganti adalah pemikiran yang tepat, hanya saja bukan yang ini.
RichardPlunkett

Jawaban:


171

Pada dasarnya, replacemengganti karakter dengan karakter lain dan ''bukan karakter. Apa yang Anda cari adalah erase.

Lihat pertanyaan ini yang menjawab masalah yang sama. Dalam kasus Anda:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

Atau gunakan boostjika itu pilihan untuk Anda, seperti:

#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");

Semua ini didokumentasikan dengan baik di situs web referensi . Tetapi jika Anda tidak mengetahui fungsi-fungsi ini, Anda dapat dengan mudah melakukan hal-hal semacam ini dengan tangan:

std::string output;
output.reserve(str.size()); // optional, avoids buffer reallocations in the loop
for(size_t i = 0; i < str.size(); ++i)
  if(str[i] != 'a') output += str[i];

2
Bukankah algoritme yang Anda berikan O(n^2)?
jww

@ Jww: Saya menganggap Anda sedang berbicara tentang contoh kode terakhir dan nmerupakan panjang string asli. Untuk setiap karakter input, saya melakukan tes 1 karakter O(1), dan 0 atau 1 karakter menambahkan. Penambahan karakter O(1)adalah mencadangkan cukup memori, atau O(current_length)jika buffer baru dialokasikan. Jika Anda melakukannya output.reserve(str.size())sebelum pengulangan, ini tidak pernah terjadi dan Anda memiliki O(n)biaya global . Jika tidak, secara asimtotik, saya kira biayanya O(n . log(n) )karena strategi realokasi kontainer STL.
Antoine

5
Saya perlu #include <algorithm>
S Meaden

Jawaban bagus. Selalu bagus jika jawabannya mengandung banyak solusi. Bagi saya, solusi dengan the foradalah yang paling cocok.
Dmitry Nichiporenko

@DmitryNichiporenko, jawaban untuk tidak mungkin yang paling cocok. Jika Anda memiliki predikat atau keluaran yang tidak kosong, saya lebih suka mempertimbangkan: output.reserve (str.size () + output.size ()); std :: copy_if (str.begin (), str.end (), std :: back_inserter (keluaran), [] (char c) {return predicate (c);});
jimifiki

11

Algoritme std::replacebekerja per elemen pada urutan tertentu (sehingga menggantikan elemen dengan elemen yang berbeda, dan tidak dapat menggantikannya dengan tidak ada ). Tetapi tidak ada karakter kosong . Jika Anda ingin menghapus elemen dari urutan, elemen berikut harus dipindahkan , dan std::replacetidak berfungsi seperti ini.

Anda dapat mencoba menggunakan std::remove( bersama denganstd::erase ) untuk mencapai ini.

str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

9

Menggunakan copy_if:

#include <string>
#include <iostream>
#include <algorithm>
int main() {
    std::string s1 = "a1a2b3c4a5";
    char s2[256];
    std::copy_if(s1.begin(), s1.end(), s2, [](char c){return c!='a';});
    std::cout << s2 << std::endl;
    return 0;
}

3
string RemoveChar(string str, char c) 
{
   string result;
   for (size_t i = 0; i < str.size(); i++) 
   {
          char currentChar = str[i];
          if (currentChar != c)
              result += currentChar;
   }
       return result;
}

Beginilah cara saya melakukannya.

Atau Anda bisa melakukan seperti yang Antoine sebutkan:

Lihat pertanyaan ini yang menjawab masalah yang sama. Dalam kasus Anda:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

1

Jika Anda memiliki predicatedan / atau yang tidak kosong outputuntuk diisi dengan string yang difilter, saya akan mempertimbangkan:

output.reserve(str.size() + output.size());  
std::copy_if(str.cbegin(), 
             str.cend(), 
             std::back_inserter(output), 
             predicate});

Dalam pertanyaan awal, predikatnya adalah [](char c){return c != 'a';}


1

Kode ini menghilangkan pengulangan karakter yaitu, jika input adalah aaabbcc maka output akan menjadi abc. (array harus diurutkan agar kode ini berfungsi)

cin >> s;
ans = "";
ans += s[0];
for(int i = 1;i < s.length();++i)
if(s[i] != s[i-1])
    ans += s[i];
cout << ans << endl;

0

Berdasarkan jawaban lain, inilah satu contoh lagi di mana saya menghapus semua karakter khusus dalam string tertentu:

#include <iostream>
#include <string>
#include <algorithm>

std::string chars(".,?!.:;_,!'\"-");

int main(int argc, char const *argv){

  std::string input("oi?");
  std::string output = eraseSpecialChars(input);   

 return 0;
}




std::string eraseSpecialChars(std::string str){

std::string newStr;
    newStr.assign(str);  

    for(int i = 0; i < str.length(); i++){
        for(int  j = 0; j < chars.length(); j++ ){
            if(str.at(i) == chars.at(j)){
                char c = str.at(i);
                newStr.erase(std::remove(newStr.begin(), newStr.end(), c), newStr.end());
            }
        }

    }      

return newStr; 
}

Input vs Output:

Input:ra,..pha
Output:rapha

Input:ovo,
Output:ovo

Input:a.vo
Output:avo

Input:oi?
Output:oi

-1

Saya kira metode std: hapus berfungsi tetapi memberikan beberapa masalah kompatibilitas dengan penyertaan jadi saya akhirnya menulis fungsi kecil ini:

string removeCharsFromString(const string str, char* charsToRemove )
{
    char c[str.length()+1]; // + terminating char
    const char *p = str.c_str();
    unsigned int z=0, size = str.length();
    unsigned int x;
    bool rem=false;

    for(x=0; x<size; x++)
    {
        rem = false;
        for (unsigned int i = 0; charsToRemove[i] != 0; i++)
        {
            if (charsToRemove[i] == p[x])
            {
                rem = true;
                break;
            }
        }
        if (rem == false) c[z++] = p[x];
    }

    c[z] = '\0';
    return string(c);
}

Gunakan saja sebagai

myString = removeCharsFromString (myString, "abc \ r");

dan itu akan menghapus semua kemunculan daftar karakter yang diberikan.

Ini juga mungkin sedikit lebih efisien karena loop kembali setelah pertandingan pertama, jadi kami sebenarnya melakukan lebih sedikit perbandingan.


1
Anda menebak dengan benar. Daripada menulis sendiri, lebih baik cari tahu mengapa Anda tidak dapat menggunakan header C ++ standar.
xtofl

Nah itu pendapat pribadi xtofl, Tidak selalu baik untuk menggunakan kode 3 Anda sebenarnya tidak tahu apa yang dilakukannya atau kinerja daripada menulis apa yang Anda butuhkan secara khusus.
Damien

1
Aku mengerti apa yang kamu maksud. Kerendahan hati itulah yang membuat saya memilih versi yang telah ditinjau, diuji, dioptimalkan oleh penulis perpustakaan profesional penuh waktu, daripada versi saya sendiri. The standar perpustakaan dapat dianggap sebagai pengetahuan yang diperlukan: fungsinya serta kompleksitas runtime nya.
xtofl

Selain string, Ini adalah solusi C untuk masalah C ++. Saya tidak berpikir ini seharusnya ditolak.
Burung Hantu

-1

Inilah cara saya melakukannya:

std::string removeAll(std::string str, char c) {
    size_t offset = 0;
    size_t size = str.size();

    size_t i = 0;
    while (i < size - offset) {
        if (str[i + offset] == c) {
            offset++;
        }

        if (offset != 0) {
            str[i] = str[i + offset];
        }

        i++;
    }

    str.resize(size - offset);
    return str;
}

Pada dasarnya setiap kali saya menemukan char tertentu, saya memajukan offset dan memindahkan char ke indeks yang benar. Saya tidak tahu apakah ini benar atau efisien, saya mulai (lagi) di C ++ dan saya akan menghargai masukan apa pun tentang itu.


4
Melihat kembali pertanyaan ini 4 bulan setelahnya, saya benar-benar tidak tahu mengapa saya tidak menggunakan std :: erase atau std :: replace.
Ricardo Pieper

-3
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());

Akan menghapus kapital Y dan S dari str, meninggalkan "ourtring".

Perhatikan bahwa itu removeadalah algoritme dan memerlukan header yang <algorithm>disertakan.


ya, saya pikir ada loop tersirat atas karakter array hte yang dia tinggalkan
RichardPlunkett
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.