วิธีการผนวกถ่านกับ std :: string?


175

ข้อผิดพลาดต่อไปนี้ล้มเหลว prog.cpp:5:13: error: invalid conversion from ‘char’ to ‘const char*’

int main()
{
  char d = 'd';
  std::string y("Hello worl");
  y.append(d); // Line 5 - this fails
  std::cout << y;
  return 0;
}

ฉันยังลองต่อไปนี้ซึ่งรวบรวม แต่ทำงานแบบสุ่มที่รันไทม์:

int main()
{
  char d[1] = { 'd' };
  std::string y("Hello worl");
  y.append(d);
  std::cout << y;
  return 0;
}

ขออภัยสำหรับคำถามโง่ ๆ นี้ แต่ฉันค้นหารอบ ๆ google สิ่งที่ฉันเห็นคือ "char array to char ptr", "char ptr to char array" ฯลฯ


ข้อผิดพลาดของคอมไพเลอร์ใช่ .. ฉันลืมว่าข้อผิดพลาดคืออะไร แต่ก็สมเหตุสมผล
จมน้ำตาย

3
คุณมีคำตอบที่ดีกว่าด้านล่าง แต่คุณสามารถทำให้ตัวอย่างที่สองทำงานเช่น char d [2] = {'d', 0}; หรือเพียงแค่ถ่าน d [2] = "d"; โดยทั่วไปคุณจะต้องมี 0 เพื่อยกเลิกสตริง c-style ของคุณที่คุณส่งไปยังผนวก
sbk

เอกสารที่ดีที่นี่: sgi.com/tech/stl/basic_string.html
มาร์ตินนิวยอร์ก

คำตอบ:


225
y += d;

ฉันจะใช้+=โอเปอเรเตอร์แทนฟังก์ชั่นที่ตั้งชื่อ


2
ทำไมคุณถึงคิดว่า + = ดีกว่า push_back มันพิมพ์น้อยลงหรือคุณมีเหตุผลอื่นหรือไม่
เกลน

4
มันพิมพ์น้อย ในgcc, เป็นเพียงการโทรในbasic_string::operator+= push_back
eduffy

2
มันเป็นธรรมชาติ IMO สำหรับสตริง push_back เป็นฟังก์ชั่นภาชนะและสตริงเป็นหนึ่งที่เชี่ยวชาญในการ STL :)
อารักษ์

6
ลองหันคำถามนั้นไปดู: ทำไมคุณถึงเห็นว่า push_back ดีกว่า + = ในความคิดของฉัน + = ชัดเจนและรัดกุม
Jesper

34
คุณต้องการที่จะระมัดระวังกับเรื่องนี้เพราะถ้าคุณได้รับเป็นนิสัยนี้จะรวบรวมได้ดีถ้าyเป็นแทนchar* std::stringมันจะเพิ่มdตัวละครไปยังตัวชี้ y
Zan Lynx


19

ในการเพิ่มถ่านให้กับ std :: string var โดยใช้วิธีการต่อท้ายคุณจะต้องใช้งานเกินพิกัดนี้:

std::string::append(size_type _Count, char _Ch)

แก้ไข: คุณถูกต้องฉันเข้าใจผิดพารามิเตอร์ size_type ซึ่งแสดงในวิธีใช้บริบท นี่คือจำนวนตัวอักษรที่จะเพิ่ม ดังนั้นการโทรที่ถูกต้องคือ

s.append(1, d);

ไม่

s.append(sizeof(char), d);

หรือวิธีที่ง่ายที่สุด:

s += d;

ฉันคิดว่าการใช้ sizeof นั้นไม่ถูกต้องทางความหมายที่นี่ วิธีการผนวกมีประโยชน์มากขึ้นโดยธรรมชาติถ้าคุณต้องการที่จะผนวกสำเนาของอักขระเดียวกัน !!!!!!!!!!
UncleBens

1
ทำไมคุณกำลังใช้sizeof(char)แทน1? คุณต้องการผนวกการซ้ำหนึ่งครั้งอย่างแน่นอนdดังนั้นเพียงแค่บอกว่า การใช้sizeofที่นี่ทำให้เข้าใจผิดเพราะมันแสดงให้เห็นว่ามีใครบอกappendขนาดไบต์ของชนิดข้อมูลที่ใช้ (ซึ่งไม่ใช่กรณี)
Ferdinand Beyer

ดังที่ Unclebens กล่าววิธีการผนวกมีประโยชน์มากขึ้นเมื่อเพิ่มอักขระเดียวกันหลายครั้ง
Patrice Bernassola

10

นอกเหนือจากที่กล่าวมาแล้วหนึ่งในตัวสร้างสตริงใช้ถ่านและจำนวนซ้ำสำหรับถ่านนั้น ดังนั้นคุณสามารถใช้มันเพื่อผนวกอักขระตัวเดียว

std::string s = "hell";
s += std::string(1, 'o');

7

ฉันทดสอบข้อเสนอหลาย ๆ ข้อด้วยการทำให้เป็นวงขนาดใหญ่ ฉันใช้ microsoft visual studio 2015 เป็นคอมไพเลอร์และโปรเซสเซอร์ของฉันคือ i7, 8Hz, 2GHz

    long start = clock();
    int a = 0;
    //100000000
    std::string ret;
    for (int i = 0; i < 60000000; i++)
    {
        ret.append(1, ' ');
        //ret += ' ';
        //ret.push_back(' ');
        //ret.insert(ret.end(), 1, ' ');
        //ret.resize(ret.size() + 1, ' ');
    }
    long stop = clock();
    long test = stop - start;
    return 0;

จากการทดสอบนี้ผลลัพธ์คือ:

     operation             time(ms)            note
------------------------------------------------------------------------
append                     66015
+=                         67328      1.02 time slower than 'append'
resize                     83867      1.27 time slower than 'append'
push_back & insert         90000      more than 1.36 time slower than 'append'

ข้อสรุป

+= ดูเหมือนจะเข้าใจได้มากกว่า แต่ถ้าคุณคำนึงถึงความเร็วให้ใช้ผนวก


เพื่อให้คำตอบมีความหมายคุณควรอย่างน้อยควรบอกว่าคุณใช้คอมไพเลอร์เพราะสิ่งต่าง ๆ อาจแตกต่างกันมาก การพูดคุยเกี่ยวกับโปรเซสเซอร์ของคุณนั้นยอดเยี่ยมเช่นกันเพื่อให้ได้การประเมินคร่าวๆเกี่ยวกับผลกระทบจริงที่อาจเกิดขึ้น
akaltar

ฉันใช้ visual studio 2015 ฉันจะมองหา gcc เพื่อทำการทดสอบอื่น ๆ ตัวประมวลผลของฉันคือ i7, 8 hearts, 2.20 Ghz .... แต่สิ่งที่เป็นตัวประมวลผลของฉันมันจะไม่มีผลกระทบต่อ std :: การใช้งานสตริง ... ยกเว้นถ้าวิธีการเหล่านี้บางอย่างมีหลายเธรด
Hugo Zevetel

บางครั้งอาจมีผลกระทบโดยเฉพาะถ้าคุณแสดงการกำหนดเวลาเป็นมิลลิวินาที แต่คุณสามารถแสดงเป็นเปอร์เซ็นต์เทียบกับวิธีที่เร็วที่สุด (ดังนั้นความเร็วของโปรเซสเซอร์ที่แท้จริงไม่เกี่ยวข้อง) นอกจากนี้ย้ายข้อมูลจากความคิดเห็นไปยังคำตอบของคุณนี่เป็นเพียงมารยาท StackExchange ทั่วไป คำตอบที่ดีเป็นอย่างอื่น
akaltar


2

ปัญหากับ:

std::string y("Hello worl");
y.push_back('d')
std::cout << y;

คือคุณต้องมี 'd' ซึ่งตรงข้ามกับการใช้ชื่อของถ่านเช่น char d = 'd'; หรือฉันผิด


ฉันแค่ลองมันแล้วก็ใช้งานได้ดี ฉันมีchar c = 'd'และฉันสามารถทำได้y.push_back(c)โดยไม่มีปัญหา ดังนั้นจึงไม่มีปัญหาstd::string::push_back()(ยกเว้นว่ายาวกว่า+=)
แฟรงคลินหยู

1
int main()
{
  char d = 'd';
  std::string y("Hello worl");

  y += d;
  y.push_back(d);
  y.append(1, d); //appending the character 1 time
  y.insert(y.end(), 1, d); //appending the character 1 time
  y.resize(y.size()+1, d); //appending the character 1 time
  y += std::string(1, d); //appending the character 1 time
}

y += 'd';โปรดทราบว่าในทุกตัวอย่างเหล่านี้คุณจะได้ใช้ตัวอักษรตัวอักษรโดยตรง:

ตัวอย่างที่สองของคุณเกือบจะใช้ได้เพราะเหตุผลที่ไม่เกี่ยวข้อง char d[1] = { 'd'};ไม่ได้ทำงาน แต่char d[2] = { 'd'};(หมายเหตุอาร์เรย์คือขนาดสอง) จะได้รับการทำงานประมาณเช่นเดียวกับconst char* d = "d";และตัวอักษรสตริงสามารถy.append(d);ถูกผนวก:


1

ลองใช้ d เป็นตัวชี้ y.append (* d)


นั่นเป็นอันตรายเนื่องจากซิงเกิ้ลcharนั้นไม่มีสตริงและไม่มี null-terminator การทำเช่นนี้ทำให้เกิดพฤติกรรมที่ไม่ได้กำหนด
Simon Kraemer

นี่เป็นเพียงความผิด *dหมายถึงตัวยกเลิกการอ้างอิงdซึ่งเป็นข้อผิดพลาดทางไวยากรณ์เนื่องจากdไม่ใช่ตัวชี้
แฟรงคลินหยู

0
str.append(10u,'d'); //appends character d 10 times

แจ้งให้ทราบล่วงหน้าฉันได้เขียน10uและไม่ 10 ตามจำนวนครั้งที่ฉันต้องการที่จะผนวกตัวละคร; แทนที่ 10 ด้วยจำนวนเท่าใดก็ได้


0

ฉันพบวิธีที่ง่าย ... ฉันต้องตะปูหัวcharต่อไปยังสายที่ถูกสร้างขึ้นทันที ฉันต้องการ a char list;เนื่องจากฉันให้ทางเลือกแก่ผู้ใช้และใช้ตัวเลือกนั้นในswitch()คำสั่ง

ฉันเพิ่งเพิ่มอีก std::string Slist;และตั้งค่าสตริงใหม่เท่ากับตัวอักษร "รายการ" - a, b, c หรือสิ่งที่ผู้ใช้เลือกเช่นนี้:

char list;
std::string cmd, state[], Slist;
Slist = list; //set this string to the chosen char;
cmd = Slist + state[x] + "whatever";
system(cmd.c_str());

ความซับซ้อนอาจจะเย็น แต่ความเรียบง่ายก็เย็นกว่า IMHO


0

ยังเพิ่มตัวเลือกแทรกตามที่ยังไม่ได้กล่าวถึง

std::string str("Hello World");
char ch;

str.push_back(ch);  //ch is the character to be added
OR
str.append(sizeof(ch),ch);
OR
str.insert(str.length(),sizeof(ch),ch) //not mentioned above

-1

หากคุณใช้ push_back จะไม่มีการเรียกตัวสร้างสตริง มิฉะนั้นมันจะสร้างวัตถุสตริงผ่านการคัดเลือกแล้วมันจะเพิ่มตัวละครในสายนี้ไปยังสายอื่น ปัญหามากเกินไปสำหรับตัวละครตัวเล็ก;)


1
ผู้ประกอบการ + = (ถ่าน c); ถูกโหลดมากเกินไปสำหรับสตริง ในความเป็นจริงตัวสร้างสตริงไม่ยอมรับตัวละครตัวหนึ่งดูคำตอบของไบรอัน;)
อารักษ์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.