Hapus spasi dari std :: string di C ++

222

Apa cara yang disukai untuk menghapus spasi dari string di C ++? Saya bisa mengulang semua karakter dan membuat string baru, tetapi apakah ada cara yang lebih baik?

Steve Hanov
sumber

Jawaban:

257

Hal terbaik untuk dilakukan adalah menggunakan algoritme remove_ifdan ruang:

remove_if(str.begin(), str.end(), isspace);

Sekarang algoritma itu sendiri tidak dapat mengubah wadah (hanya memodifikasi nilai-nilai), jadi itu benar-benar mengocok nilai-nilai di sekitar dan mengembalikan pointer ke tempat akhir sekarang seharusnya. Jadi kita harus memanggil string :: erase untuk benar-benar memodifikasi panjang wadah:

str.erase(remove_if(str.begin(), str.end(), isspace), str.end());

Kami juga harus mencatat bahwa remove_if akan membuat paling banyak satu salinan data. Berikut ini contoh implementasi:

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;
}
Matt Price
sumber
54
Karena 'isspace' memiliki kelebihan, Anda mungkin perlu untuk memenuhi syarat kode generik untuk menggunakan :: isspace (implementasi C yang tidak mengambil lokal) atau disambut dengan kesalahan instantiasi template kriptik.
Bklyn
4
Semua waspada terhadap metode di atas (Dua baris tunggal, bukan versi templated, meskipun mungkin memiliki masalah yang sama). Saya menggunakannya dalam suatu proyek tanpa menyadari bahwa itu tidak selalu benar. Misalnya, jika Anda meneruskannya string "1 + 1" itu mengembalikan "1 + 11". Saya beralih ke metode @rupello di bawah dan ini berfungsi dengan baik untuk kasus ini. Selamat coding!
JoeB
6
@ Jo. Jawabannya secara eksplisit menyebutkan bahwa Anda perlu menelepon erasesesudahnya. Itu akan mengembalikan hasil yang benar.
Konrad Rudolph
31
-1 penggunaan ini isspaceadalah UB untuk semua set karakter kecuali ASCII 7-bit asli. C99 §7.4 / 1. itu tidak mengejutkan saya bahwa itu sudah upvoted untuk lagu 71 orang sekarang, meskipun menjadi sangat buruk Saran.
Ceria dan hth. - Alf
16
Sebagai pengulangan, kode dalam jawaban ini meneruskan nilai negatif (berbeda dari EOF) ke isspace, untuk semua karakter non-ASCII, dengan pilihan standar praktik dalam penandatanganan untuk char. Dengan demikian ia memiliki perilaku yang tidak jelas . Saya mengulanginya karena saya curiga ada upaya yang disengaja untuk menenggelamkan fakta itu dalam kebisingan.
Ceria dan hth. - Alf
100
std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());
Arno
sumber
31
Pemungutan suara saya untuk kanon menghapus / menghapus idiom. Dapat dibuat menjadi satu liner: str.erase (std :: remove (str.begin (), str.end (), ''), str.end ());
Bklyn
11
Catatan: Anda harus memasukkan <algorithm>ini agar berfungsi.
Tara
37

Dari gamedev

string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());
rupello
sumber
22
Ini tidak akan dikompilasi pada implementasi yang sesuai standar karena kelebihan pengambilan lokal std :: isspace. Anda harus menggunakan :: isspace atau melakukan beberapa intrik yang tidak dapat dibaca dengan std :: bind2nd. Bukankah kode generik cantik?
Bklyn
Juga perhatikan bahwa jika salah satu karakter negatif (misalnya char UTF8 ketika char ditandatangani), penggunaannya ::isspaceadalah UB.
Martin Bonner mendukung Monica
30

Bisakah Anda menggunakan Boost String Algo? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573

erase_all(str, " "); 
Nemanja Trifunovic
sumber
3
Lebih lambat dari remove_if(str.begin(), str.end(), isspace);yang disebutkan oleh Matt Price. Saya tidak tahu kenapa. Sebenarnya, semua hal yang meningkatkan, yang memiliki alternatif STL, lebih lambat daripada yang gcc yang sesuai (Semua yang saya diuji). Beberapa dari mereka jauh lebih lambat! (hingga 5 kali dalam sisipan unordered_map) Mungkin itu karena cache CPU dari lingkungan bersama atau sesuatu seperti itu.
Etherealone
16

Untuk pemangkasan, gunakan algoritma peningkatan string :

#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

// ...

string str1(" hello world! ");
trim(str1);      // str1 == "hello world!"
Roma
sumber
15

Anda dapat menggunakan solusi ini untuk menghapus char:

#include <algorithm>
#include <string>
using namespace std;

str.erase(remove(str.begin(), str.end(), char_to_remove), str.end());
pengguna2281802
sumber
1
#include <string.h> using namespace std;
slackmart
Solusi ini tepat untuk saya. Yang teratas bukan.
Jason Liu
1
menggunakan namespace std harus dihindari. stackoverflow.com/questions/1452721/…
infinitezero
12

Hai, Anda bisa melakukan hal seperti itu. Fungsi ini menghapus semua spasi.

string delSpaces(string &str) 
{
   str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
   return str;
}

Saya membuat fungsi lain, yang menghapus semua ruang yang tidak perlu.

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;
}
ddacot
sumber
8
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);
}

Gunakan:

string replace = replaceinString(thisstring, " ", "%20");
string replace2 = replaceinString(thisstring, " ", "-");
string replace3 = replaceinString(thisstring, " ", "+");
SudoBash
sumber
7

Jika Anda ingin melakukan ini dengan makro yang mudah, berikut ini:

#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end())

Ini mengasumsikan Anda sudah melakukan #include <string>tentu saja.

Sebut seperti ini:

std::string sName = " Example Name ";
REMOVE_SPACES(sName);
printf("%s",sName.c_str()); // requires #include <stdio.h>
Volomike
sumber
5
mengapa Anda menggunakan makro untuk ini?
dani
1
Kurang mengetik keyboard untuk tugas umum.
Volomike
3
Sama singkatnya dengan situs panggilan memanggil fungsi mengambil referensi-nilai lvalue ke string. Makro dapat memiliki perilaku mengejutkan yang berinteraksi dengan argumen mereka (terutama dengan efek samping), tetapi lebih buruk lagi, jika mereka terlibat dalam kesalahan, nama mereka tidak muncul dalam pesan kompiler, implementasinya tidak.
Chris Uzdavinis
2

Saya menggunakan pekerjaan di bawah ini untuk waktu yang lama - tidak yakin tentang kerumitannya.

s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return (f==' '||s==' ');}),s.end());

ketika Anda ingin menghapus karakter ' 'dan beberapa misalnya - digunakan

s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return ((f==' '||s==' ')||(f=='-'||s=='-'));}),s.end());

juga hanya menambah ||jika jumlah karakter yang ingin Anda hapus bukan 1

tetapi seperti yang disebutkan oleh orang lain menghapus idiom hapus juga tampak baik-baik saja.

RaGa__M
sumber
1
string removeSpaces(string word) {
    string newWord;
    for (int i = 0; i < word.length(); i++) {
        if (word[i] != ' ') {
            newWord += word[i];
        }
    }

    return newWord;
}

Kode ini pada dasarnya mengambil string dan beralih melalui setiap karakter di dalamnya. Itu kemudian memeriksa apakah string itu adalah spasi, jika tidak maka karakter ditambahkan ke string baru.

Apel Renyah
sumber
1
   #include <algorithm>
   using namespace std;

   int main() {
       .
       .
       s.erase( remove( s.begin(), s.end(), ' ' ), s.end() );
       .
       .
   }

Sumber:

Referensi diambil dari forum ini .

John
sumber
1
Ini tidak benar-benar menambahkan apa pun lebih dari jawaban ini sudah. Apakah ada lebih banyak penjelasan atau perincian yang dapat Anda tambahkan untuk membuat jawaban Anda lebih berkualitas dan layak untuk dipertahankan pada pertanyaan ini?
Das_Geek
Saya pikir ini lebih sederhana , karena melakukan hal yang sama dalam satu pernyataan.
John
2
Bagus! Kemudian berikan alasan itu sebagai penjelasan langsung dalam jawaban Anda . Pertanyaan aslinya berumur lebih dari sebelas tahun , dan tanpa pembenaran jawaban Anda dapat dianggap sebagai suara bising jika dibandingkan dengan jawaban lain yang diterima dengan baik. Memiliki penjelasan itu akan membantu menjaga jawaban Anda agar tidak dihapus.
Das_Geek
Itu akan baik tapi aku tidak bisa mendapatkan bahwa bagaimana saya harus menempatkan bahwa dalam jawaban saya ... bahwa jawaban saya lebih baik daripada jawaban ini . ? Akan sangat menyenangkan jika Anda dapat mengedit jawaban saya.
John
2
Sayangnya, mengedit jawaban Anda untuk menambahkan konten itu sendiri akan bertentangan dengan pedoman pengeditan , dan pengeditan saya kemungkinan akan ditolak atau diputar kembali nanti. Anda dapat menggunakan tautan pertama dalam komentar ini untuk mengedit sendiri jawabannya. Benar-benar dapat diterima untuk menyatakan bahwa Anda berpikir jawaban Anda lebih baik daripada yang lain, dan memberikan pembenaran untuk itu. Komunitas akan memutuskan apakah Anda benar dengan memilih atau tidak memilih.
Das_Geek
0

Di C ++ 20 Anda dapat menggunakan fungsi std :: erase gratis

std::string str = " Hello World  !";
std::erase(str, ' ');

Contoh lengkap:

#include<string>
#include<iostream>

int main() {
    std::string str = " Hello World  !";
    std::erase(str, ' ');
    std::cout << "|" << str <<"|";
}

Saya mencetak | sehingga jelas bahwa ruang di awal juga dihilangkan.

catatan: ini hanya menghapus ruang, tidak setiap karakter lain yang mungkin dianggap sebagai spasi putih, lihat https://en.cppreference.com/w/cpp/string/byte/isspace

NoSenseEtAl
sumber
0

Menghapus semua karakter spasi putih seperti tab dan jeda baris (C ++ 11):

string str = " \n AB cd \t efg\v\n";
str = regex_replace(str,regex("\\s"),"");
AnselmRu
sumber
Mengapa Anda merekomendasikan pendekatan ini atas jawaban yang diterima @ Matt-Price dari lebih dari satu dekade yang lalu?
Jeremy Caney
Biarkan semua solusi disajikan di sini. Mungkin seseorang akan membutuhkan solusi ini.
AnselmRu
Saya tidak membantah hal itu. Saya mengatakan untuk mempermudah orang menilai pendekatan yang berbeda dengan menjelaskan perbedaan dan skenario apa yang paling cocok untuk mereka.
Jeremy Caney
1
Mungkin solusi ini bukan yang paling ekonomis, tetapi memungkinkan Anda untuk menyingkirkan semua karakter spasi putih ', bukan hanya spasi' '.
AnselmRu
0
  string str = "2C F4 32 3C B9 DE";
  str.erase(remove(str.begin(),str.end(),' '),str.end());
  cout << str << endl;

output: 2CF4323CB9DE

Kerim FIRAT
sumber
-1
string removespace(string str)
{    
    int m = str.length();
    int i=0;
    while(i<m)
    {
        while(str[i] == 32)
        str.erase(i,1);
        i++;
    }    
}
tes c
sumber
3
Biasanya Anda lebih suka menambahkan penjelasan singkat ke kode jawaban.
arcyqwerty
1
@test - length()mengembalikan a size_t, bukan sebuah int. erase()mengambil size_type, bukan int. Fungsi ini mungkin akan gagal jika dua spasi berturut-turut ditemukan karena indeks selalu bertambah. Jika satu spasi dihilangkan, maka loop akan membaca di luar batas string. Anda mungkin harus menghapus jawaban ini karena butuh banyak bantuan.
jww
-3

Saya khawatir itu solusi terbaik yang bisa saya pikirkan. Tetapi Anda dapat menggunakan cadangan () untuk pra-alokasikan memori minimum yang diperlukan di muka untuk mempercepat segalanya. Anda akan berakhir dengan string baru yang mungkin akan lebih pendek tetapi membutuhkan jumlah memori yang sama, tetapi Anda akan menghindari realokasi.

EDIT: Tergantung pada situasi Anda, ini mungkin menimbulkan lebih sedikit overhead daripada karakter jumbling di sekitar.

Anda harus mencoba berbagai pendekatan dan melihat yang terbaik untuk Anda: Anda mungkin tidak memiliki masalah kinerja sama sekali.

Dave Van den Eynde
sumber
remove_if membuat paling banyak satu salinan dari setiap nilai. Jadi sebenarnya tidak ada banyak overhead dibandingkan dengan apa yang perlu dilakukan.
Harga Matt