ลบอักขระตัวสุดท้ายออกจากสตริง C ++


210

ฉันจะลบอักขระตัวสุดท้ายออกจากสตริง C ++ ได้อย่างไร

ฉันลองแล้วst = substr(st.length()-1);แต่มันไม่ทำงาน


6
คุณต้องการสตริงใหม่ที่ลบอักขระตัวสุดท้ายหรือสตริงเดียวกันโดยไม่มีอักขระตัวสุดท้ายหรือไม่?
Matthieu M.

สำหรับ MFC Visual c ++ CString: CString str=CString("Hello world"); str.Delete(str.GetLength()-1);
sergiol

คำตอบ:


193

สำหรับเวอร์ชันที่ไม่ได้กลายพันธุ์:

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

20
@MatthieuM ตัวอย่างของคุณสับสนฉันคิดว่าสาระสำคัญของคำถามคือการแก้ไขสตริงเดิมในตัวอย่างของคุณคุณไม่ได้แก้ไขสตริงเดิมเพราะในตัวอย่างของคุณสตริงเดิมเรียกว่า "myString" ซึ่งทำให้เกิดความสับสน ในคำถามมันคือ "เซนต์" รหัสของคุณควรเป็น: st = st.substr(0, st.size()-1). แต่ก็ยังไม่ได้ดูวิธีการที่เหมาะสมผมคิดว่าวิธีการที่เหมาะสมคือการใช้ฟังก์ชั่นที่มีไว้สำหรับงานนี้ก็เรียกว่าลบ () st.erase(st.size()-1)และรหัสคือ: สิ่งนี้จะเรียกว่า "รุ่นกลายพันธุ์"
Czarek Tomczak

1
@CzarekTomczak: ฉันเข้าใจว่านี่ไม่ใช่สิ่งที่ถูกขอดังนั้นข้อจำกัดความรับผิดชอบก่อนส่วนสำคัญที่แท้จริง
Matthieu M.

2
@MattPhillips: วิธีการแก้ปัญหาของเขาคือ C ++ 11 โดยเฉพาะ ( pop_backไม่มีอยู่ใน C ++ 03) และยังเป็นการดัดแปลงแบบแทนที่ (และ OP ไม่เคยชี้แจงว่าเขาต้องการแบบนั้นหรือไม่) ... เป็น เช่นเขามีคำตอบที่ถูกต้อง แต่ไม่ได้เป็นคนไปได้เท่านั้น
Matthieu M.

404

วิธีแก้ปัญหาง่ายๆถ้าคุณใช้ C ++ 11 อาจเป็นเวลา O (1) เช่นกัน:

st.pop_back();

49
นี่สำหรับ c ++ 11!
อาเมียร์

1
ในฐานะที่เป็น FYI - ได้รับการสนับสนุนจาก GCC 4.7 (นอกหลักสูตรพร้อมสวิตช์สลับการรวบรวม -std = c ++ 11)
Shmil The Cat

20
length()อย่าลืมที่จะตรวจสอบ

ใช่มันดูเหมือนจะไกลเกินไปหน้า .. !
James Bedford

1
The behavior is undefined if the string is empty. จากที่นี่
Raffi

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

std :: ลบทางเลือกเป็นสิ่งที่ดี แต่ฉันชอบ "- 1" (ไม่ว่าจะขึ้นอยู่กับขนาดหรือตัวทำซ้ำสุดท้าย) - สำหรับฉันมันช่วยแสดงเจตนา

BTW - ไม่มี std :: string :: pop_back จริง ๆ หรือไม่ - ดูเหมือนแปลก


11
ไม่มีstd::string::pop_backใน C ++ 03; มันถูกเพิ่มเข้าไปใน C ++ 0x
James McNellis

โอเคขอบคุณ. มันทำให้เกิดความสับสนเล็กน้อย - ฉันสามารถสาบานได้ว่าฉันเคยใช้ แต่ก็ไม่ได้มี บางทีฉันอาจมีไลบรารีที่ไม่ได้มาตรฐานในคอมไพเลอร์บางแห่ง (ระหว่าง VC ++ 2003, VC ++ 2008, MinGW GCC3 MinGW GCC 4 และ Linux GCC 4 คุณมีความแตกต่างเล็กน้อย) มีแนวโน้มมากขึ้นฉันเพิ่งสับสนกับประเภทอื่น
Steve314

ปรับขนาด () อาจไม่ได้มีไว้สำหรับการใช้งานเช่นนี้เป็นฟังก์ชั่นที่เกี่ยวข้องกับหน่วยความจำลบ () สำหรับการลบอักขระ
Czarek Tomczak

3
@Careare Tomczak - ขอโทษสำหรับการตอบกลับอย่างไร้เหตุผล แต่resizeเป็นฟังก์ชั่นปรับขนาดและไม่มีฟังก์ชั่นหน่วยความจำอะไรอีกที่อาจเพิ่มหน่วยความจำที่จำเป็น ตัวอย่างเช่นถ้าคุณresizeมีขนาดเล็กลงมันจะไม่ลดหน่วยความจำที่สงวนไว้ ฉันคิดว่าคุณกำลังความคิดของreserveซึ่งอย่างน้อยอาจลดการจัดสรรหน่วยความจำถ้าถามไป - ดูปรับขนาดที่นี่และสำรองที่นี่
Steve314

3
ถ้า (! str.empty ()) เป็นที่ต้องการมากกว่าขนาด
ericcurtin

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

สิ่งนี้จะถือว่าคุณรู้ว่าสตริงนั้นไม่ว่างเปล่า ถ้าเป็นเช่นนั้นคุณจะได้รับout_of_rangeข้อยกเว้น


8
buf [buf.size () - 1] = '\ 0'; ไม่ได้ลบอะไรเลย - เพียงแค่เปลี่ยนตัวละครที่อยู่ที่นั่นเพื่อให้มีค่าเป็นศูนย์ std:; สตริงสามารถมีอักขระดังกล่าวได้อย่างมีความสุข

นีลนั้นถูกต้อง ฉันควรจะชี้แจงเรื่องนี้ในคำตอบของฉัน ตัวเลือกที่สองจะเปลี่ยนค่าของอักขระตัวสุดท้ายอย่างมีประสิทธิภาพดังนั้นมันจะไม่พิมพ์ แต่ความยาวสตริงจะยังคงเหมือนเดิม การใช้การลบจริง ๆ แล้ว "ลบ" อักขระสุดท้ายและจะเปลี่ยนขนาดของสตริง
RC

@RC มันจะพิมพ์สมมติว่าคุณใช้บางอย่างเช่นศาล << buf ลักษณะที่ปรากฏจะขึ้นอยู่กับแพลตฟอร์มของคุณ และคุณสามารถชี้แจงได้โดยแก้ไขคำตอบของคุณ

มีอะไรที่ดีมากเกี่ยวกับsize() แทนend()ของคำตอบอื่นได้หรือไม่
ribamar

17

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

การอ้างอิง: std :: string :: erase () prototype 2

ไม่จำเป็นต้องใช้ c ++ 11 หรือ c ++ 0x


1
สิ่งนี้สามารถนำไปสู่สถานการณ์แปลก ๆ : ขนาดของสตริงลดลง แต่ตัวละครสุดท้ายไม่ได้ถูกตั้งค่าเป็น '\ 0'
Deqing

1
@Deqing คุณสามารถให้รายละเอียดเพิ่มเติมว่าเกิดอะไรขึ้นในกรณีเช่นนี้?
ribamar

ตัวอย่างเช่นถ้าคุณมีstring s("abc");หลังจากลบมันดูเหมือนว่าทำงาน: cout<<s; // prints "ab"อย่างไรก็ตามตัวละครสุดท้ายยังคงอยู่ที่นั่น: cout<<s[2]; // still prints 'c'.
Deqing

1
แก้ไขได้อย่างง่ายดาย: เพียงstr[str.length()-1] = 0; str.erase(str.end()-1);
taxilian

5
@Dequing: ตัวอย่างของคุณไม่ถูกต้อง การลบจะลดขนาดของสตริงดังนั้นการเข้าถึงs[2]จึงผิดกฎหมาย
EML

11

นั่นคือทั้งหมดที่คุณต้องการ:

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

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


2

ด้วย C ++ 11 คุณไม่จำเป็นต้องมีความยาว / ขนาด ตราบใดที่สตริงไม่ว่างคุณสามารถทำสิ่งต่อไปนี้:

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()) ไม่ได้รวบรวมน่าเสียดายตั้งแต่ reverse_iteratorไม่สามารถแปลงเป็น Normal_iterator

C ++ 11 คือเพื่อนของคุณในกรณีนี้


วิธีนี้มีปัญหาเช่นกันอักขระตัวสุดท้ายไม่ได้ถูกตั้งค่าเป็น '\ 0'
Deqing

1
มีเหตุผลใดที่ทำให้ไม่ทำstr.erase(str.end() - 1)?
vallentin

-4

หากความยาวไม่ใช่ศูนย์คุณสามารถทำได้เช่นกัน

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

4
การตั้งค่าอักขระสุดท้ายเป็น\0ไม่เปลี่ยนความยาวของสตริง str.length()จะไม่ถูกต้อง
jww

ใช่ฉันเห็นแล้ว เรากำลังพิจารณา C ++ คุณถูกต้องมันไม่เปลี่ยนความยาวของสตริง
Jan Glaser
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.