ฉันจะต่อหลาย C ++ สตริงในหนึ่งบรรทัดได้อย่างไร


150

C # มีคุณสมบัติซินแท็กซ์ซึ่งคุณสามารถต่อข้อมูลหลายชนิดเข้าด้วยกันใน 1 บรรทัด

string s = new String();
s += "Hello world, " + myInt + niceToSeeYouString;
s += someChar1 + interestingDecimal + someChar2;

อะไรจะเทียบเท่าใน C ++ เท่าที่ฉันเห็นคุณจะต้องทำทุกอย่างแยกกันเพราะมันไม่รองรับสตริง / ตัวแปรหลายตัวด้วยเครื่องหมาย + ไม่เป็นไร แต่ดูไม่เรียบร้อย

string s;
s += "Hello world, " + "nice to see you, " + "or not.";

รหัสข้างต้นก่อให้เกิดข้อผิดพลาด


4
ตามที่อธิบายไว้ที่อื่นนี่ไม่ใช่เพราะ "มันไม่สนับสนุนสตริง / ตัวแปรหลายตัวพร้อมกับเครื่องหมาย +" แต่เพราะคุณพยายามเพิ่มพchar *อยน์เตอร์เข้าด้วยกัน นั่นคือสิ่งที่ทำให้เกิดข้อผิดพลาด - เนื่องจากการรวมพอยน์เตอร์นั้นไร้สาระ ตามที่ระบุไว้ด้านล่างให้ทำอย่างน้อย 1 ตัวถูกดำเนินการเป็นstd::stringและไม่มีข้อผิดพลาดเลย
underscore_d

ข้อผิดพลาดใดที่ถูกสร้างขึ้น?
Wolf

ซ้ำกันเป็นไปได้ของวิธีการเชื่อม std :: string และ int?
vitaut

คำตอบ:


240
#include <sstream>
#include <string>

std::stringstream ss;
ss << "Hello, world, " << myInt << niceToSeeYouString;
std::string s = ss.str();

ลองดูที่บทความ Guru Of The Week จาก Herb Sutter: The Format Formatters ของ Manor Farm


6
ลองนี้:std::string s = static_cast<std::ostringstream&>(std::ostringstream().seekp(0) << "HelloWorld" << myInt << niceToSeeYouString).str();
Byzantian

42
ss << "ว้าวการต่อสตริงใน C ++ นั้นน่าประทับใจ" << "หรือไม่"
joaerl

4
เพียงตั้งชื่ออีกวิธี: ใช้หลายผนวก: string s = string ("abc"). ผนวก ("def"). ผนวก (otherStrVar). ผนวก (to_string (123));
Patricio Rossi

1
std::stringstream ss; ss << "Hello, world, " << myInt << niceToSeeYouString; std::string s = ss.str();เป็นหนึ่งบรรทัดสวยมาก
Kotauskas

74

ใน 5 ปีที่ไม่มีใครพูดถึง.append?

#include <string>

std::string s;
s.append("Hello world, ");
s.append("nice to see you, ");
s.append("or not.");

เพราะมันยุ่งยากกับการเปรียบเทียบเพียงแค่เพิ่มข้อความในหนึ่งบรรทัด
Hi-Angel

11
s.append("One"); s.append(" line");
จอนนี่

16
@ จอนนี่s.append("One").append(" expression");บางทีฉันควรแก้ไขต้นฉบับเพื่อใช้ค่าส่งคืนด้วยวิธีนี้หรือไม่?
Eponymous

5
@ SilverMöls OP ประกาศsในบรรทัดที่แตกต่างกันในรหัส C # ที่เทียบเท่าและในรหัส C ++ ที่ไม่คอมไพล์ของเขา C ++ ที่เขาต้องการs += "Hello world, " + "nice to see you, " + "or not.";สามารถเขียนได้s.append("Hello world, ").append("nice to see you, ").append("or not.");
Eponymous

4
ข้อได้เปรียบที่สำคัญappendคือมันยังทำงานได้เมื่อสตริงมีอักขระ NUL
John S.

62
s += "Hello world, " + "nice to see you, " + "or not.";

ตัวอักษรของอาร์เรย์ตัวอักษรเหล่านั้นไม่ใช่ C ++ std :: strings - คุณต้องแปลงมัน:

s += string("Hello world, ") + string("nice to see you, ") + string("or not.");

ในการแปลง ints (หรือประเภท streamable อื่น ๆ ) คุณสามารถใช้ boost lexical_cast หรือสร้างฟังก์ชั่นของคุณเอง:

template <typename T>
string Str( const T & t ) {
   ostringstream os;
   os << t;
   return os.str();
}

ตอนนี้คุณสามารถพูดสิ่งที่ชอบ:

string s = string("The meaning is ") + Str( 42 );

16
คุณจะต้องแปลงอย่างแรก: s + = string ("Hello world,") + "ยินดีที่ได้พบคุณ" + "หรือไม่";
Ferruccio

8
ใช่ แต่ฉันไม่สามารถอธิบายได้ว่าทำไม!

1
เพิ่ม :: lexical_cast - ดีและฟังก์ชั่นที่คล้ายกันใน Str ของคุณ :)
Bayda

2
concatenations ทำที่ด้านขวาของตัวสร้างที่string("Hello world")จะดำเนินการผ่านทางที่กำหนดไว้ในชั้นเรียนoperator+() stringถ้าไม่มีวัตถุที่อยู่ในการแสดงออกเรียงต่อกันจะกลายเป็นผลรวมของตัวชี้เพียงถ่านstring char*
davide

41

รหัสของคุณสามารถเขียนเป็น1 ,

s = "Hello world," "nice to see you," "or not."

... แต่ฉันสงสัยว่านั่นคือสิ่งที่คุณกำลังมองหา ในกรณีของคุณคุณอาจกำลังมองหาสตรีม:

std::stringstream ss;
ss << "Hello world, " << 42 << "nice to see you.";
std::string s = ss.str();

1 " สามารถเขียนเป็น ": ใช้ได้กับตัวอักษรสตริงเท่านั้น การต่อข้อมูลจะกระทำโดยคอมไพเลอร์


11
ตัวอย่างที่ 1 ของคุณมีค่าควรพูดถึง แต่โปรดระบุด้วยว่ามันจะใช้งานได้กับสตริงตัวอักษร "concatenating" เท่านั้น (คอมไพเลอร์ทำการเรียงต่อกันเอง)
j_random_hacker

ตัวอย่างแรกทำให้เกิดข้อผิดพลาดสำหรับฉันถ้ามีการประกาศสตริงก่อนหน้านี้ว่าเป็นเช่นconst char smthg[] = "smthg": / มันเป็นข้อผิดพลาดหรือไม่?
Hi-Angel

@ Hi-Angel โชคไม่ดีที่คุณสามารถใช้#defineสายของคุณเพื่อแก้ไขปัญหานี้ได้
cz

27

การใช้ตัวอักษรที่กำหนดโดยผู้ใช้ C ++ 14 และstd::to_stringรหัสจะง่ายขึ้น

using namespace std::literals::string_literals;
std::string str;
str += "Hello World, "s + "nice to see you, "s + "or not"s;
str += "Hello World, "s + std::to_string(my_int) + other_string;

โปรดทราบว่าการรวมสตริงสตริงสามารถทำได้ในเวลาคอมไพล์ +เพียงแค่ลบ

str += "Hello World, " "nice to see you, " "or not";

2
ตั้งแต่ C ++ 11 คุณสามารถใช้ std :: to_string
Patricio Rossi

ที่ผู้ใช้กำหนดตัวอักษรยังตั้งแต่ C ++ 11 <> ฉันแก้ไข
Danny Danny

@StackDanny การเปลี่ยนแปลงไม่ถูกต้อง เมื่อฉันพูดว่า "C ++ 14" ฉันอ้างถึงstd::literals::string_literalsไม่ใช่แนวคิดของ UDL
Rapptz

16

ที่จะนำเสนอวิธีการแก้ปัญหาที่มีมากขึ้นหนึ่งบรรทัด-ish: ฟังก์ชั่นconcatสามารถดำเนินการเพื่อลด "คลาสสิก" วิธีการแก้ปัญหาตาม stringstream ไปคำเดียว มันขึ้นอยู่กับเทมเพลตหลากหลายและการส่งต่อที่สมบูรณ์แบบ


การใช้งาน:

std::string s = concat(someObject, " Hello, ", 42, " I concatenate", anyStreamableType);

การดำเนินงาน:

void addToStream(std::ostringstream&)
{
}

template<typename T, typename... Args>
void addToStream(std::ostringstream& a_stream, T&& a_value, Args&&... a_args)
{
    a_stream << std::forward<T>(a_value);
    addToStream(a_stream, std::forward<Args>(a_args)...);
}

template<typename... Args>
std::string concat(Args&&... a_args)
{
    std::ostringstream s;
    addToStream(s, std::forward<Args>(a_args)...);
    return s.str();
}

สิ่งนี้จะไม่กลายเป็นช่วงเวลารวบรวมหรือไม่ถ้ามีชุดค่าผสมหลายชุดในฐานรหัสขนาดใหญ่
Shital Shah

1
@ ShitalShah ไม่ได้เป็นอะไรมากไปกว่าการเขียนเนื้อหาแบบอินไลน์ด้วยตนเองเนื่องจากฟังก์ชั่นผู้ช่วยเหล่านี้จะได้รับการแทรกไว้
underscore_d

13

ใน C ++ 20 คุณจะสามารถทำสิ่งต่อไปนี้

auto s = std::format("{}{}{}", "Hello world, ", myInt, niceToSeeYouString);

คุณสามารถทำเช่นเดียวกันกับห้องสมุด {fmt} :

auto s = fmt::format("{}{}{}", "Hello world, ", myInt, niceToSeeYouString);

ข้อจำกัดความรับผิดชอบ : ฉันเป็นผู้เขียน {fmt}


7

เพิ่มรูปแบบ ::

หรือ std :: stringstream

std::stringstream msg;
msg << "Hello world, " << myInt  << niceToSeeYouString;
msg.str(); // returns std::string object

6

ปัญหาที่เกิดขึ้นจริงคือการที่เชื่อมโยงกับตัวอักษรของสตริง+ล้มเหลวใน C ++:

string s;
s += "Hello world, " + "nice to see you, " + "or not.";
รหัสข้างต้นก่อให้เกิดข้อผิดพลาด

ใน C ++ (ใน C) คุณเชื่อมตัวอักษรของสตริงเข้าด้วยกันโดยเพียงแค่วางมันไว้ข้างๆกัน:

string s0 = "Hello world, " "nice to see you, " "or not.";
string s1 = "Hello world, " /*same*/ "nice to see you, " /*result*/ "or not.";
string s2 = 
    "Hello world, " /*line breaks in source code as well as*/ 
    "nice to see you, " /*comments don't matter*/ 
    "or not.";

สิ่งนี้สมเหตุสมผลถ้าคุณสร้างโค้ดในมาโคร:

#define TRACE(arg) cout << #arg ":" << (arg) << endl;

... แมโครอย่างง่ายที่สามารถใช้เช่นนี้

int a = 5;
TRACE(a)
a += 7;
TRACE(a)
TRACE(a+7)
TRACE(17*11)

( การสาธิตสด ... )

หรือถ้าคุณยืนยันในการใช้+สำหรับตัวอักษรสตริง (ตามที่แนะนำโดยunderscore_d ):

string s = string("Hello world, ")+"nice to see you, "+"or not.";

โซลูชันอื่นรวมสตริงและ a const char*สำหรับแต่ละขั้นตอนการต่อข้อมูล

string s;
s += "Hello world, "
s += "nice to see you, "
s += "or not.";

ฉันยังใช้เทคนิคนี้เป็นจำนวนมาก แต่ถ้าตัวแปรอย่างน้อยหนึ่งตัวเป็น int / string .eg สตริง s = "abc" "def" (int) y "ghi" (std :: string) z "1234"; จากนั้น sprintf ก็ยังเป็นทางออกที่ดีที่สุด
Bart Mensfort

@BartMensfort แน่นอนว่าsprintfเป็นตัวเลือก แต่ก็ยังมีstd :: stringstreamซึ่งป้องกันปัญหาเกี่ยวกับบัฟเฟอร์ที่มีขนาดเล็ก
Wolf


3

คุณจะต้องกำหนดโอเปอเรเตอร์ + () สำหรับข้อมูลทุกประเภทที่คุณต้องการเชื่อมโยงกับสตริง แต่เนื่องจากโอเปอเรเตอร์ << ถูกกำหนดสำหรับประเภทส่วนใหญ่คุณควรใช้ std :: stringstream

ประณามเอาชนะ 50 วินาที ...


1
คุณไม่สามารถกำหนดโอเปอเรเตอร์ใหม่ในประเภทบิวด์อินเช่น char และ int
Tyler McHenry

1
@TylerMcHenry ไม่ว่าฉันจะแนะนำในกรณีนี้ แต่คุณสามารถ:std::string operator+(std::string s, int i){ return s+std::to_string(i); }
Eponymous

3

ถ้าคุณเขียน+=มันมันก็เกือบจะเหมือนกับ C #

string s("Some initial data. "); int i = 5;
s = s + "Hello world, " + "nice to see you, " + to_string(i) + "\n";

3

เป็นคนอื่น ๆ กล่าวว่าปัญหาหลักที่มีรหัส OP คือการที่ผู้ประกอบการ+ไม่ได้ concatenate const char *; มันทำงานร่วมกับstd::stringแม้ว่า

ต่อไปนี้เป็นโซลูชันอื่นที่ใช้ lambdas C ++ 11 for_eachและอนุญาตให้มีseparatorการแยกสตริง:

#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>

string join(const string& separator,
            const vector<string>& strings)
{
    if (strings.empty())
        return "";

    if (strings.size() == 1)
        return strings[0];

    stringstream ss;
    ss << strings[0];

    auto aggregate = [&ss, &separator](const string& s) { ss << separator << s; };
    for_each(begin(strings) + 1, end(strings), aggregate);

    return ss.str();
}

การใช้งาน:

std::vector<std::string> strings { "a", "b", "c" };
std::string joinedStrings = join(", ", strings);

ดูเหมือนว่าจะขยายได้ดี (เป็นเส้นตรง) อย่างน้อยหลังจากการทดสอบอย่างรวดเร็วบนคอมพิวเตอร์ของฉัน นี่คือการทดสอบอย่างรวดเร็วที่ฉันเขียน:

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <chrono>

using namespace std;

string join(const string& separator,
            const vector<string>& strings)
{
    if (strings.empty())
        return "";

    if (strings.size() == 1)
        return strings[0];

    stringstream ss;
    ss << strings[0];

    auto aggregate = [&ss, &separator](const string& s) { ss << separator << s; };
    for_each(begin(strings) + 1, end(strings), aggregate);

    return ss.str();
}

int main()
{
    const int reps = 1000;
    const string sep = ", ";
    auto generator = [](){return "abcde";};

    vector<string> strings10(10);
    generate(begin(strings10), end(strings10), generator);

    vector<string> strings100(100);
    generate(begin(strings100), end(strings100), generator);

    vector<string> strings1000(1000);
    generate(begin(strings1000), end(strings1000), generator);

    vector<string> strings10000(10000);
    generate(begin(strings10000), end(strings10000), generator);

    auto t1 = chrono::system_clock::now();
    for(int i = 0; i<reps; ++i)
    {
        join(sep, strings10);
    }

    auto t2 = chrono::system_clock::now();
    for(int i = 0; i<reps; ++i)
    {
        join(sep, strings100);
    }

    auto t3 = chrono::system_clock::now();
    for(int i = 0; i<reps; ++i)
    {
        join(sep, strings1000);
    }

    auto t4 = chrono::system_clock::now();
    for(int i = 0; i<reps; ++i)
    {
        join(sep, strings10000);
    }

    auto t5 = chrono::system_clock::now();

    auto d1 = chrono::duration_cast<chrono::milliseconds>(t2 - t1);
    auto d2 = chrono::duration_cast<chrono::milliseconds>(t3 - t2);
    auto d3 = chrono::duration_cast<chrono::milliseconds>(t4 - t3);
    auto d4 = chrono::duration_cast<chrono::milliseconds>(t5 - t4);

    cout << "join(10)   : " << d1.count() << endl;
    cout << "join(100)  : " << d2.count() << endl;
    cout << "join(1000) : " << d3.count() << endl;
    cout << "join(10000): " << d4.count() << endl;
}

ผลลัพธ์ (มิลลิวินาที):

join(10)   : 2
join(100)  : 10
join(1000) : 91
join(10000): 898

3

บางทีคุณอาจชอบโซลูชัน "Streamer" ของฉันที่จะทำในบรรทัดเดียว:

#include <iostream>
#include <sstream>
using namespace std;

class Streamer // class for one line string generation
{
public:

    Streamer& clear() // clear content
    {
        ss.str(""); // set to empty string
        ss.clear(); // clear error flags
        return *this;
    }

    template <typename T>
    friend Streamer& operator<<(Streamer& streamer,T str); // add to streamer

    string str() // get current string
    { return ss.str();}

private:
    stringstream ss;
};

template <typename T>
Streamer& operator<<(Streamer& streamer,T str)
{ streamer.ss<<str;return streamer;}

Streamer streamer; // make this a global variable


class MyTestClass // just a test class
{
public:
    MyTestClass() : data(0.12345){}
    friend ostream& operator<<(ostream& os,const MyTestClass& myClass);
private:
    double data;
};

ostream& operator<<(ostream& os,const MyTestClass& myClass) // print test class
{ return os<<myClass.data;}


int main()
{
    int i=0;
    string s1=(streamer.clear()<<"foo"<<"bar"<<"test").str();                      // test strings
    string s2=(streamer.clear()<<"i:"<<i++<<" "<<i++<<" "<<i++<<" "<<0.666).str(); // test numbers
    string s3=(streamer.clear()<<"test class:"<<MyTestClass()).str();              // test with test class
    cout<<"s1: '"<<s1<<"'"<<endl;
    cout<<"s2: '"<<s2<<"'"<<endl;
    cout<<"s3: '"<<s3<<"'"<<endl;
}

2

นี่คือวิธีแก้ปัญหาแบบหนึ่งซับ:

#include <iostream>
#include <string>

int main() {
  std::string s = std::string("Hi") + " there" + " friends";
  std::cout << s << std::endl;

  std::string r = std::string("Magic number: ") + std::to_string(13) + "!";
  std::cout << r << std::endl;

  return 0;
}

แม้ว่ามันจะดูค่อนข้างน่าเกลียด แต่ฉันคิดว่ามันสะอาดพอ ๆ กับที่คุณแมวได้รับใน C ++

เราจะหล่ออาร์กิวเมนต์แรกไปstd::stringแล้วโดยใช้ (จากซ้ายไปขวา) เพื่อประเมินผลoperator+เพื่อให้มั่นใจว่ามันซ้ายstd::stringถูกดำเนินการอยู่เสมอ ในลักษณะนี้เราเชื่อมstd::stringต่อด้านซ้ายกับconst char *ตัวถูกดำเนินการทางด้านขวาและส่งคืนอีกแบบstd::stringโดยเรียงลำดับเอฟเฟกต์

หมายเหตุ: มีกี่ตัวเลือกสำหรับตัวถูกดำเนินการที่เหมาะสมรวมทั้งconst char *, และstd::stringchar

มันขึ้นอยู่กับคุณที่จะตัดสินใจว่าเลขอาถรรพ์คือ 13 หรือ 6227020800


Ah, คุณลืม, @Apollys, หมายเลขมายากลสากลคือ 42. : D
Mr.Zeus


1

หากคุณยินดีที่จะใช้c++11คุณสามารถใช้ตัวอักษรสตริงที่ผู้ใช้กำหนดและกำหนดสองฟังก์ชั่นแม่แบบที่เกินตัวดำเนินการบวกสำหรับstd::stringวัตถุและวัตถุอื่น ๆ ข้อผิดพลาดเพียงอย่างเดียวคือการไม่ใส่ตัวดำเนินการบวกของstd::stringมิฉะนั้นคอมไพเลอร์ไม่ทราบว่าตัวดำเนินการที่จะใช้ คุณสามารถทำได้โดยใช้แม่แบบจากstd::enable_if type_traitsหลังจากนั้นสตริงจะทำงานเหมือนใน Java หรือ C # ดูตัวอย่างการใช้งานของฉันสำหรับรายละเอียด

รหัสหลัก

#include <iostream>
#include "c_sharp_strings.hpp"

using namespace std;

int main()
{
    int i = 0;
    float f = 0.4;
    double d = 1.3e-2;
    string s;
    s += "Hello world, "_ + "nice to see you. "_ + i
            + " "_ + 47 + " "_ + f + ',' + d;
    cout << s << endl;
    return 0;
}

ไฟล์ c_sharp_strings.hpp

รวมไฟล์ส่วนหัวนี้ในทุกที่ที่คุณต้องการมีสตริงเหล่านี้

#ifndef C_SHARP_STRING_H_INCLUDED
#define C_SHARP_STRING_H_INCLUDED

#include <type_traits>
#include <string>

inline std::string operator "" _(const char a[], long unsigned int i)
{
    return std::string(a);
}

template<typename T> inline
typename std::enable_if<!std::is_same<std::string, T>::value &&
                        !std::is_same<char, T>::value &&
                        !std::is_same<const char*, T>::value, std::string>::type
operator+ (std::string s, T i)
{
    return s + std::to_string(i);
}

template<typename T> inline
typename std::enable_if<!std::is_same<std::string, T>::value &&
                        !std::is_same<char, T>::value &&
                        !std::is_same<const char*, T>::value, std::string>::type
operator+ (T i, std::string s)
{
    return std::to_string(i) + s;
}

#endif // C_SHARP_STRING_H_INCLUDED

1

บางอย่างเช่นนี้ใช้ได้สำหรับฉัน

namespace detail {
    void concat_impl(std::ostream&) { /* do nothing */ }

    template<typename T, typename ...Args>
    void concat_impl(std::ostream& os, const T& t, Args&&... args)
    {
        os << t;
        concat_impl(os, std::forward<Args>(args)...);
    }
} /* namespace detail */

template<typename ...Args>
std::string concat(Args&&... args)
{
    std::ostringstream os;
    detail::concat_impl(os, std::forward<Args>(args)...);
    return os.str();
}
// ...
std::string s{"Hello World, "};
s = concat(s, myInt, niceToSeeYouString, myChar, myFoo);

1

จากการแก้ปัญหาข้างต้นฉันได้สร้าง var_string สำหรับโครงการของฉันเพื่อทำให้ชีวิตง่ายขึ้น ตัวอย่าง:

var_string x("abc %d %s", 123, "def");
std::string y = (std::string)x;
const char *z = x.c_str();

ชั้นเรียนของตัวเอง:

#include <stdlib.h>
#include <stdarg.h>

class var_string
{
public:
    var_string(const char *cmd, ...)
    {
        va_list args;
        va_start(args, cmd);
        vsnprintf(buffer, sizeof(buffer) - 1, cmd, args);
    }

    ~var_string() {}

    operator std::string()
    {
        return std::string(buffer);
    }

    operator char*()
    {
        return buffer;
    }

    const char *c_str()
    {
        return buffer;
    }

    int system()
    {
        return ::system(buffer);
    }
private:
    char buffer[4096];
};

ยังสงสัยว่าจะมีสิ่งที่ดีกว่าใน C ++ หรือไม่


1

ใน c11:

void printMessage(std::string&& message) {
    std::cout << message << std::endl;
    return message;
}

สิ่งนี้อนุญาตให้คุณสร้างการเรียกใช้ฟังก์ชันเช่นนี้:

printMessage("message number : " + std::to_string(id));

จะพิมพ์: หมายเลขข้อความ: 10


0

คุณยังสามารถ "ขยาย" คลาสสตริงและเลือกโอเปอเรเตอร์ที่คุณต้องการ (<<, &, |, ฯลฯ ... )

นี่คือรหัสที่ใช้โอเปอเรเตอร์ << เพื่อแสดงว่าไม่มีข้อขัดแย้งกับสตรีม

หมายเหตุ: หากคุณไม่แสดงความคิดเห็น s1.reserve (30) มีเพียง 3 คำขอใหม่ () ดำเนินการขอ (1 สำหรับ s1, 1 สำหรับ s2, 1 สำหรับสำรองคุณไม่สามารถจองในเวลาตัวสร้างโชคไม่ดี); โดยไม่ต้องจอง s1 จะต้องขอหน่วยความจำมากขึ้นในขณะที่มันเติบโตดังนั้นมันขึ้นอยู่กับการใช้งานคอมไพเลอร์ของคุณปัจจัยการเติบโต (ฉันดูเหมือนจะเป็น 1.5, 5 สายใหม่ () ในตัวอย่างนี้)

namespace perso {
class string:public std::string {
public:
    string(): std::string(){}

    template<typename T>
    string(const T v): std::string(v) {}

    template<typename T>
    string& operator<<(const T s){
        *this+=s;
        return *this;
    }
};
}

using namespace std;

int main()
{
    using string = perso::string;
    string s1, s2="she";
    //s1.reserve(30);
    s1 << "no " << "sunshine when " << s2 << '\'' << 's' << " gone";
    cout << "Aint't "<< s1 << " ..." <<  endl;

    return 0;
}

0

Stringstream กับมาโคร preproccessor ง่าย ๆ โดยใช้ฟังก์ชั่นแลมบ์ดาดูดี:

#include <sstream>
#define make_string(args) []{std::stringstream ss; ss << args; return ss;}() 

แล้ว

auto str = make_string("hello" << " there" << 10 << '$');

-1

สิ่งนี้ใช้ได้กับฉัน:

#include <iostream>

using namespace std;

#define CONCAT2(a,b)     string(a)+string(b)
#define CONCAT3(a,b,c)   string(a)+string(b)+string(c)
#define CONCAT4(a,b,c,d) string(a)+string(b)+string(c)+string(d)

#define HOMEDIR "c:\\example"

int main()
{

    const char* filename = "myfile";

    string path = CONCAT4(HOMEDIR,"\\",filename,".txt");

    cout << path;
    return 0;
}

เอาท์พุท:

c:\example\myfile.txt

12
ลูกแมวร้องทุกครั้งที่มีคนใช้มาโครในสิ่งที่ซับซ้อนกว่ารหัสผู้รักษาหรือค่าคงที่: P
Rui Marques

1
ข้างลูกแมวที่ไม่มีความสุข: สำหรับแต่ละอาร์กิวเมนต์จะมีการสร้างวัตถุสตริงซึ่งไม่จำเป็น
SebastianK

2
downvoted เนื่องจากการใช้มาโครเป็นวิธีแก้ปัญหาที่ไม่ดีแน่นอน
dhaumann

นี่จะทำให้ฉันสะดุ้งตกใจกลัวแม้กระทั่งกับ C แต่ใน C ++ มันช่างโหดร้าย @RuiMarques: ในสถานการณ์ใดเป็นมาโครที่ดีกว่าสำหรับค่าคงที่มากกว่าconstหรือ (ถ้าต้องการพื้นที่เก็บข้อมูลเป็นศูนย์) enumจะเป็นอย่างไร
underscore_d

@underscore_d คำถามที่น่าสนใจ แต่ฉันไม่มีคำตอบ บางทีคำตอบก็คือไม่มี
Rui Marques

-1

คุณพยายามหลีกเลี่ยงการ + =? ใช้ var = var + ... แทนมันใช้ได้ผลกับฉันแทน

#include <iostream.h> // for string

string myName = "";
int _age = 30;
myName = myName + "Vincent" + "Thorpe" + 30 + " " + 2019;

ฉันใช้ C ++ borland builder 6 และใช้งานได้ดีสำหรับฉัน อย่าลืมใส่ส่วนหัวนี้#include <iostream.h> // string #include <system.hpp> // ansiString
vincent thorpe

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