0
string A = "test";
double B = 123.45;
float  C = 43.23;
char   D = 'c';

试图加入他们以产生一个字符串string res = "test,123.45,43.23,c"。最快的方法是什么?

ostringstream很好,但似乎不够快。

4

5 回答 5

1

我不知道最快的方法。我只知道如何在 C++ 中完成它。:)

这是一个演示程序,显示了两种方法

#include <iostream>
#include <string>
#include <sstream>

int main() 
{
    std::string A = "test";
    double B = 123.45;
    float  C = 43.23;
    char   D = 'c'; 

    std::string res1 = A + ',' + std::to_string( B ) + ',' + 
                       std::to_string( C ) + ',' + D;

    std::cout << res1 << std::endl;

    std::ostringstream is;

    is << A << ',' << B << ',' << C << ',' << D;

    std::string res2 = is.str();

    std::cout << res2 << std::endl;

    return 0;
}

程序输出为

test,123.450000,43.230000,c
test,123.45,43.23,c

所以你可以选择你喜欢的。:)

为了使方法更快,您应该使用成员函数为字符串保留足够的内存reserve

于 2015-04-21T06:52:46.547 回答
1

您的问题包括两个任务:

  • 将变量转换为字符串
  • 将字符串连接到单个字符串。

第二步可以通过使用 std::string::reserve() 保留一些内存来加速。通常,当重复追加到末尾时,std::string 将不得不多次重新分配内存。如果提前知道结果字符串的大小,则可以避免这种情况。然后可以使用 std::string::reserve() 来告诉 std::string ,这样它就可以减少重新分配内存的调用,这可能会显着提高长字符串的性能。

于 2015-04-21T06:54:11.430 回答
1

您始终可以使用以下C方式:

char outbuf[256];
sprintf(outbuf, "%s,%3.2d,%2.2f,%c", A.c_str(), B, C, D);

请注意,我写的那行非常具体;因为您对双精度、浮点数、字符串长度、...的格式一无所知

于 2015-04-21T06:43:30.283 回答
0

在 Visual Studio 2013 下,sprintf 比 ostringstream 快两倍(在发布时测量)。原因可能是因为 ostringstream 做了很多分配,我使用了 _CrtSetAllocHook 并且它在下面的代码示例中被触发了 74 次,而它甚至没有为 sprintf 触发 - 这是在调试中测量的。

附言。stringstream 可以自定义,您可以编写自己的自定义缓冲区,这将是您需要的最佳选择。

#include <Windows.h>
#include <iostream>
#include <sstream>

struct TimeMe {
    ULONG64 start;
    TimeMe() {
        QueryThreadCycleTime(GetCurrentThread(), &start);
    }
    ULONG64 total() {
        ULONG64 end;
        QueryThreadCycleTime(GetCurrentThread(), &end);
        return (end - start);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::string A = "test";
    double B = 123.45;
    float  C = 43.23;
    char   D = 'c';

    char outbuf[256];
    std::ostringstream is;

    ULONG64 sum=0;
    for ( int k = 0; k < 100; ++k ) {
        TimeMe me;

        // ~8800 ticks
        //is.str("");
        //is.clear();
        //is << A << ',' << B << ',' << C << ',' << D;
        //std::string res2 = is.str();

        // ~4500 ticks
        sprintf(outbuf, "%s,%3.2lf,%2.2f,%c", A.c_str(), B, C, D);

        sum += me.total();
    }
    std::cout << "CPU ticks: " << (sum)/100 << std::endl;
    return 0;
}
于 2015-04-21T07:15:41.903 回答
0

我认为ostringstream是一个非常好的方法,“似乎不够快”可能不是那么重要,除非你有很多数字和字符串要处理。

也许[sprintf][1] http://www.cplusplus.com/reference/cstdio/sprintf/

是一种替代方法,我认为如果您知道结果的长度,这可能会更快:

new char[length]在开始时做一个。

例如:

char * buffer = new char[LENGTH];
int a = 1;
double b = 2.0;
string c = "3.0";
int n = sprintf(buffer, "%d plus %f is %s", a, b, c.c_str());

此外,snprintf建议因为它更安全

于 2015-04-21T06:47:20.787 回答