C#具有语法功能,您可以在一行中将多种数据类型连接在一起。
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.";
上面的代码会产生错误。
答案 0 :(得分:214)
#include <sstream>
#include <string>
std::stringstream ss;
ss << "Hello, world, " << myInt << niceToSeeYouString;
std::string s = ss.str();
看看Herb Sutter撰写的本周大师文章:The String Formatters of Manor Farm
答案 1 :(得分:58)
s += "Hello world, " + "nice to see you, " + "or not.";
那些字符数组文字不是C ++ std :: strings - 你需要转换它们:
s += string("Hello world, ") + string("nice to see you, ") + string("or not.");
要转换整数(或任何其他可流式类型),您可以使用boost lexical_cast或提供自己的函数:
template <typename T>
string Str( const T & t ) {
ostringstream os;
os << t;
return os.str();
}
您现在可以说:
string s = "The meaning is " + Str( 42 );
答案 2 :(得分:57)
5年没有人提到.append
?
#include <string>
std::string s;
s.append("Hello world, ");
s.append("nice to see you, ");
s.append("or not.");
答案 3 :(得分:40)
您的代码可以写成 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 “可写为”:这仅适用于字符串文字。连接由编译器完成。
答案 4 :(得分:22)
使用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";
答案 5 :(得分:16)
提供更多单线的解决方案:可以实现函数concat
以将“经典”基于字符串流的解决方案减少为单一语句。
它基于可变参数模板和完美转发。
<强>用法:强>
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();
}
答案 6 :(得分:7)
boost :: format
或std :: stringstream
std::stringstream msg;
msg << "Hello world, " << myInt << niceToSeeYouString;
msg.str(); // returns std::string object
答案 7 :(得分: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.";
另一个解决方案是为每个连接步骤组合一个字符串和const char*
string s;
s += "Hello world, "
s += "nice to see you, "
s += "or not.";
答案 8 :(得分:4)
使用{fmt} library即可:
auto s = fmt::format("{}{}{}", "Hello world, ", myInt, niceToSeeYouString);
该库的一个子集建议标准化为P0645 Text Formatting,如果接受,上述内容将变为:
auto s = std::format("{}{}{}", "Hello world, ", myInt, niceToSeeYouString);
免责声明:我是{fmt}图书馆的作者。
答案 9 :(得分:3)
正如其他人所说,OP代码的主要问题是运算符i
不会连接+
;但它适用于const char *
。
这是另一个使用C ++ 11 lambdas和std::string
的解决方案,并允许提供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;
}
答案 10 :(得分:3)
auto s = string("one").append("two").append("three")
答案 11 :(得分:3)
也许你喜欢我的&#34; Streamer&#34;真正做到这一点的解决方案:
$config['path']
答案 12 :(得分:3)
你必须为你想要设想的每个数据类型定义operator +(),但是因为operator&lt;&lt;对于大多数类型定义,您应该使用std :: stringstream。
该死的,50秒后击败......
答案 13 :(得分:1)
你也可以&#34;延伸&#34;字符串类并选择您喜欢的运算符(&lt;&lt;,&amp;,|等等)
以下是使用运算符&lt;&lt;的代码显示与流没有冲突
注意:如果取消注释s1.reserve(30),则只有3个new()运算符请求(s1为1,s2为1,保留为1;不幸的是,你不能在构造函数时保留);没有保留,s1必须在增长时请求更多内存,所以它取决于你的编译器实现增长因子(在这个例子中我的似乎是1.5,5个new()调用)
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;
}
答案 14 :(得分:1)
如果您愿意使用c++11
,可以使用user-defined string literals并定义两个函数模板,这些模板会使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;
}
将此头文件包含在您想要拥有这些字符串的所有位置。
#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
答案 15 :(得分:1)
您可以在此方面使用此标题:https://github.com/theypsilon/concat
using namespace concat;
assert(concat(1,2,3,4,5) == "12345");
您将使用std :: ostringstream。
答案 16 :(得分: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);
答案 17 :(得分: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 ++中是否会有更好的东西?
答案 18 :(得分:1)
在c11:
void printMessage(std::string&& message) {
std::cout << message << std::endl;
return message;
}
这允许你创建这样的函数调用:
printMessage("message number : " + std::to_string(id));
将打印:消息号:10
答案 19 :(得分:1)
这是一线解决方案:
#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+
的(从左到右)评估顺序来确保其 left 操作数始终为{ {1}}。通过这种方式,我们将左侧的std::string
与右侧的std::string
操作数连接起来,并返回另一个const char *
,以级联效果。
注意:正确的操作数有几个选项,包括std::string
,const char *
和std::string
。
由您决定魔术数是13还是6227020800。
答案 20 :(得分:0)
带有使用lambda函数的简单前置宏的Stringstream看起来不错:
#include <sstream>
#define make_string(args) []{std::stringstream ss; ss << args; return ss;}()
然后
auto str = make_string("hello" << " there" << 10 << '$');
答案 21 :(得分:-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
答案 22 :(得分:-1)
您是否尝试避免+ =? 而是使用var = var + ... 它对我有用。
#include <iostream.h> // for string
string myName = "";
int _age = 30;
myName = myName + "Vincent" + "Thorpe" + 30 + " " + 2019;