C ++ dizesinden son karakteri kaldır


210

Bir C ++ dizesinden son karakteri nasıl kaldırabilirim?

Denedim st = substr(st.length()-1);ama işe yaramadı.


6
Son karakteri kaldırılmış yeni bir dize mi yoksa son karakteri olmayan aynı dize mi istiyorsunuz?
Matthieu M.

Bir MFC Visual C ++ CString için: CString str=CString("Hello world"); str.Delete(str.GetLength()-1);
sergiol

Yanıtlar:


193

Değişmeyen bir sürüm için:

st = myString.substr(0, myString.size()-1);

20
@MatthieuM. Örneğin kafa karıştırıcı, sorunun özünün orijinal dizeyi değiştirmek olduğunu düşünüyorum, örneğin orijinal dizeyi değiştirmiyorsunuz, çünkü örneğinizde orijinal dizeye karışıklığa neden olan "myString" soruda "st" dir. Sizin kodu olmalıdır: st = st.substr(0, st.size()-1). Ama yine de doğru şekilde görünmüyor, düzgün şekilde, 's denilen silme () bu görev için tasarlanmıştır işlevini kullanmaktır ve kod olduğunu düşünüyorum: st.erase(st.size()-1). Buna "mutasyona uğrayan versiyon" denir.
Czarek Tomczak

1
@CzarekTomczak: Bunun tam olarak istenen şey olmadığını anlıyorum, dolayısıyla asıl özden önceki feragatname.
Matthieu M.19

2
@MattPhillips: Çözümü C ++ 11'e özgüdür ( pop_backC ++ 03'te yoktu) ve aynı zamanda yerinde bir değişikliktir (ve OP, yerinde olmasını isteyip istemediğini asla açıklığa kavuşturmamıştır) ... böyle, elindeki bir değil, yalnızca olası bir doğru cevabı.
Matthieu M.21

404

C ++ 11 kullanıyorsanız basit çözüm. Muhtemelen O (1) zamanı da:

st.pop_back();

49
Bu c ++ 11 içindir!
Amir

1
FYI olarak - sadece GCC 4.7'den destekleniyor (wst the -std = c ++ 11 derleme anahtarıyla)
Shmil The Cat

20
Kontrol etmeyi unutma length().

Evet, sayfadan çok aşağıda görünüyor ..!
James Bedford

1
The behavior is undefined if the string is empty. dan burada
Raffi

24
if (str.size () > 0)  str.resize (str.size () - 1);

Bir std :: erase alternatifi iyidir, ancak "- 1" i (bir boyuta veya son yineleyiciye bağlı olarak) seviyorum - bana niyetini ifade etmeye yardımcı olur.

BTW - Gerçekten hiçbir std :: string :: pop_back var mı? - tuhaf görünüyor.


11
std::string::pop_backC ++ 03'te hiç yoktur ; Yine de C ++ 0x içinde eklendi.
James McNellis

Tamam teşekkürler. Biraz karışıklığa neden oldu - yemin edebilirim, ama orada değil. Belki bazı yerlerde derleyici olmayan standart bir kütüphane var (VC ++ 2003, VC ++ 2008, MinGW GCC3 MinGW GCC 4 ve Linux GCC 4 arasında, birkaç fark elde edersiniz). Büyük olasılıkla, diğer türlerle kafam karıştı.
Steve314

resize () muhtemelen böyle bir kullanım için tasarlanmamıştır, hafıza ile ilgili bir işlevdir, erase () karakterleri silmek içindir.
Czarek Tomczak

3
@Czarek Tomczak - saçma sapan geç cevap için özür dilerim, ancak resizeyeniden boyutlandırma fonksiyonu ve artık hafızayı arttırabilecek başka bir şey olmayan bir hafıza fonksiyonu yok. Eğer Örneğin, resizedaha küçük bir boyuta, bu olacak değil saklıdır hafızayı azaltır. Sana ait konum düşünme düşünmek reserveen azından belki istenirse ayrılan hafızayı azaltmak - bakınız burada yeniden boyutlandırmak ve burada rezerv .
Steve314

3
(! str.empty ()) boyutuna göre tercih
edildiyse

19
buf.erase(buf.size() - 1);

Bu, dizenin boş olmadığını bildiğinizi varsayar. Eğer öyleyse, bir out_of_rangeistisna alacaksınız .


8
buf [buf.size () - 1] = '\ 0'; hiçbir şeyi kaldırmaz - sadece orada bulunan karakteri sıfır değerine sahip olacak şekilde değiştirir. std:; dizeleri mutlu bir şekilde bu karakterleri içerebilir.

Neil doğrudur. Muhtemelen cevabımda bunu netleştirmeliydim. İkinci seçenek, son karakterin değerini etkili bir şekilde değiştirir, böylece yazdırılmaz, ancak dize uzunluğu aynı kalır. Erase komutunu kullanmak aslında son karakteri "kaldırır" ve dizenin boyutunu değiştirir.
RC.

@RC Baskı, cout << buf gibi bir şey kullandığınızı varsayar. Nasıl göründüğü platformunuza bağlı olacaktır. Ve her zaman cevabınızı düzenleyerek netleştirebilirsiniz.

Başka bir cevap size() yerine daha iyi ne olabilir end()?
ribamar

17

str.erase( str.end()-1 )

Referans: std :: string :: erase () prototip 2

c ++ 11 veya c ++ 0x gerekmez.


1
Bu garip bir duruma yol açabilir: dizenin boyutu küçülmüş ancak son karakter '\ 0' olarak ayarlanmamıştır.
Deqing

1
@Deqing böyle bir durumda neler olduğu hakkında daha fazla bilgi verebilir misiniz?
Mart'ta ribamar

Eğer varsa Örneğin string s("abc");, silme sonra çalışma görünüyor: cout<<s; // prints "ab"Ancak son karakteri hala orada: cout<<s[2]; // still prints 'c'.
Deqing

1
kolayca sabitlendi: sadecestr[str.length()-1] = 0; str.erase(str.end()-1);
taksiler

5
@Dequing: örneğiniz geçersiz. Silme dizenin boyutunu azaltır, bu nedenle erişim s[2]yasa dışıdır.
EML

11

Tek ihtiyacınız olan şey:

#include <string>  //string::pop_back & string::empty

if (!st.empty())
    st.pop_back();

9
int main () {

  string str1="123";
  string str2 = str1.substr (0,str1.length()-1);

  cout<<str2; // output: 12

  return 0;
}

2

C ++ 11 ile uzunluk / boyuta bile ihtiyacınız yoktur. Dize boş olmadığı sürece aşağıdakileri yapabilirsiniz:

if (!st.empty())
  st.erase(std::prev(st.end())); // Erase element referred to by iterator one
                                 // before the end

2

str.erase(str.begin() + str.size() - 1)

str.erase(str.rbegin())maalesef derlenmediğinden reverse_iteratornormal_iterator değerine dönüştürülemez.

C ++ 11 bu durumda arkadaşınızdır.


Bu yöntemin de sorunu var, son karakter '\ 0' olarak ayarlanmamış.
Deqing

1
Yapmamak için özel bir neden var str.erase(str.end() - 1)mı?
vallentin

-4

Uzunluk sıfır değilse, ayrıca

str[str.length() - 1] = '\0';

4
Son karakterin ayarlanması, \0dizenin uzunluğunu değiştirmez. str.length()yanlış olacaktır.
jww

Evet, şimdi görüyorum. C ++ 'ı düşünüyoruz. Haklısın, ipin uzunluğunu değiştirmiyor
Jan Glaser
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.