Xóa ký tự cuối cùng khỏi chuỗi C ++


210

Làm cách nào để xóa ký tự cuối cùng khỏi chuỗi C ++?

Tôi đã thử st = substr(st.length()-1);Nhưng nó không hoạt động.


6
Bạn có muốn một chuỗi mới với ký tự cuối cùng bị xóa hoặc cùng một chuỗi mà không có ký tự cuối cùng không?
Matthieu M.

Đối với CString MFC Visual C ++: CString str=CString("Hello world"); str.Delete(str.GetLength()-1);
sergiol

Câu trả lời:


193

Đối với phiên bản không biến đổi:

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

20
@MatthieuM. Ví dụ của bạn khó hiểu, tôi nghĩ rằng bản chất của câu hỏi là sửa đổi chuỗi gốc, trong ví dụ của bạn, bạn không sửa đổi chuỗi gốc, bởi vì trong ví dụ của bạn, chuỗi ban đầu được gọi là "myString" gây nhầm lẫn, trong câu hỏi đó là "st". Mã của bạn phải là : st = st.substr(0, st.size()-1). Nhưng nó vẫn không nhìn đúng cách, tôi nghĩ rằng cách thích hợp là sử dụng hàm dành cho nhiệm vụ này, nó được gọi là erase () và mã là : st.erase(st.size()-1). Đây sẽ được gọi là "phiên bản đột biến".
Czarek Tomczak

1
@CzarekTomczak: Tôi hiểu đây không phải là chính xác những gì được yêu cầu, do đó từ chối trách nhiệm trước ý chính thực tế.
Matthieu M.

2
@MattPhillips: giải pháp của anh ấy là C ++ 11 cụ thể mặc dù ( pop_backkhông tồn tại trong C ++ 03) và đó cũng là một sửa đổi tại chỗ (và OP không bao giờ làm rõ liệu anh ấy có muốn tại chỗ hay không) ... như như vậy, anh ta có một câu trả lời đúng, nhưng không phải là câu trả lời duy nhất có thể.
Matthieu M.

404

Giải pháp đơn giản nếu bạn đang sử dụng C ++ 11. Có lẽ là thời gian O (1):

st.pop_back();

49
cái này dành cho c ++ 11!
Amir

1
Là một FYI - nó chỉ được hỗ trợ từ GCC 4.7 (tất nhiên cùng với công tắc biên dịch w / the -std = c ++ 11)
Shmil The Cat 7/214

20
Đừng quên kiểm tra length().

Phải, nó xuất hiện quá xa trang ..!
James Bedford

1
The behavior is undefined if the string is empty. từ đây
Raffi

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

Một thay thế std :: erase là tốt, nhưng tôi thích "- 1" (cho dù dựa trên kích thước hoặc bộ lặp cuối) - với tôi, nó giúp thể hiện ý định.

BTW - Có thực sự không có std :: string :: pop_back? - Có vẻ lạ.


11
Không có std::string::pop_backtrong C ++ 03; mặc dù nó đã được thêm vào C ++ 0x.
James McNellis

Được rồi cảm ơn. Nó gây ra một chút nhầm lẫn - tôi có thể thề rằng tôi đã sử dụng nó, nhưng nó không có ở đó. Có thể tôi có một thư viện không chuẩn trong một số trình biên dịch ở đâu đó (giữa VC ++ 2003, VC ++ 2008, MinGW GCC3 MinGW GCC 4 và Linux GCC 4, bạn có một vài khác biệt). Nhiều khả năng, tôi chỉ bị nhầm lẫn với các loại khác.
Steve314

resize () có lẽ không dành cho mục đích sử dụng đó, đó là một hàm liên quan đến bộ nhớ, erase () là để xóa các ký tự.
Czarek Tomczak

3
@Czarek Tomczak - xin lỗi vì trả lời trễ một cách vô lý, nhưng resizelà một chức năng thay đổi kích thước và không còn là chức năng bộ nhớ mà bất cứ điều gì khác có thể làm tăng bộ nhớ cần thiết. Ví dụ: nếu bạn resizeở kích thước nhỏ hơn, nó sẽ không làm giảm bộ nhớ dành riêng. Tôi nghĩ rằng bạn đang nghĩ đến reserve, điều này ít nhất có thể làm giảm bộ nhớ được phân bổ nếu được yêu cầu - xem thay đổi kích thước ở đâydự trữ ở đây .
Steve314

3
if (! str.empty ()) được ưu tiên hơn kích thước
ericcurtin

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

Điều này giả định rằng bạn biết rằng chuỗi không trống. Nếu vậy, bạn sẽ có một out_of_rangengoại lệ.


8
buf [buf.size () - 1] = '\ 0'; không xóa bất cứ thứ gì - nó chỉ thay đổi ký tự ở đó để có giá trị 0. std :; chuỗi có thể vui vẻ chứa các ký tự như vậy.

Neil là chính xác. Tôi có lẽ nên làm rõ điều này trong câu trả lời của tôi. Tùy chọn thứ hai sẽ thay đổi hiệu quả giá trị của ký tự cuối cùng để nó không in, nhưng độ dài chuỗi sẽ giữ nguyên. Sử dụng erase thực sự "loại bỏ" ký tự cuối cùng và sẽ thay đổi kích thước của chuỗi.
RC.

@RC Nó sẽ in, giả sử bạn sử dụng cái gì đó như cout << buf. Làm thế nào nó xuất hiện sẽ phụ thuộc vào nền tảng của bạn. Và bạn luôn có thể làm rõ bằng cách chỉnh sửa câu trả lời của bạn.

Điều gì tốt hơn nhiều về size() thay vì end()một câu trả lời khác?
ribamar

17

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

Tham khảo: std :: string :: erase () nguyên mẫu 2

không cần c ++ 11 hoặc c ++ 0x.


1
Điều này có thể dẫn đến tình huống kỳ lạ: kích thước của chuỗi đã bị giảm nhưng ký tự cuối cùng không được đặt thành '\ 0'.
Deqing

1
@De Khánh bạn có thể cho biết thêm chi tiết về những gì xảy ra trong trường hợp như vậy?
ribamar

Ví dụ: nếu bạn có string s("abc");, sau khi xóa, nó có vẻ hoạt động: cout<<s; // prints "ab"tuy nhiên, ký tự cuối cùng vẫn ở đó : cout<<s[2]; // still prints 'c'.
Deqing

1
dễ dàng sửa chữa: chỉstr[str.length()-1] = 0; str.erase(str.end()-1);
taxilian 19/03/2015

5
@Dequing: ví dụ của bạn không hợp lệ. Việc xóa làm giảm kích thước của chuỗi, vì vậy việc truy cập s[2]là bất hợp pháp.
EML

11

Đó là tất cả những gì bạn cần:

#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

Với C ++ 11, bạn thậm chí không cần chiều dài / kích thước. Miễn là chuỗi không trống, bạn có thể làm như sau:

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())không may biên dịch, vì reverse_iteratorkhông thể chuyển đổi thành normal_iterator.

C ++ 11 là bạn của bạn trong trường hợp này.


Phương pháp này cũng có vấn đề, ký tự cuối cùng không được đặt thành '\ 0'.
Đức Thanh

1
Bất kỳ lý do cụ thể cho việc không làm str.erase(str.end() - 1)?
vallentin

-4

Nếu độ dài khác không, bạn cũng có thể

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

4
Đặt ký tự cuối cùng thành \0không thay đổi độ dài của chuỗi. str.length()sẽ không chính xác.
jww

Vâng, tôi thấy nó bây giờ. Chúng tôi đang xem xét C ++. Bạn đã đúng, nó không thay đổi độ dài của chuỗi
Jan Glaser
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.