我如何连接str和int ptr

时间:2017-02-05 00:14:15

标签: c++

我的文件名需要char*。它应该是这样的:cards/h11.bmp

我有一个函数,我从各种SO文章拼凑而成:

char* getFileName(int* pc1_no, char* suite)
{
    int number;
    char pCard1[80];
    strcpy_s(pCard1, "cards/");
    strcat_s(pCard1, suite);
    number = *pc1_no;
    cout << number << endl;
    string str = to_string(number);
    char const *pchar = str.c_str();
    strcat_s(pCard1, pchar);
    strcat_s(pCard1, ".bmp");

    return pCard1;
}

当然,返回垃圾。我没有得到指针值。我很确定我用指针犯了一个愚蠢的错误。提前谢谢。

3 个答案:

答案 0 :(得分:10)

完成所有这些操作的最佳方法是摆脱所有指针并一直使用字符串:

std::string getFileName(int pc1_no, 
                        const std::string & suite)
{
    std::string pCard1 = "cards/" + suite + std::to_string(pc1_no) + ".bmp";
    return pCard1;
}

或者如果构建到std::to_string不可用的旧C ++标准:

std::string getFileName(int pc1_no, 
                        const std::string & suite)
{
    std::stringstream pCard1;
    pCard1<< "cards/" << suite << pc1_no << ".bmp";
    return pCard1.str();
}

理性

char pCard1[80];

是一个局部变量。它会在函数结束时死掉,因此函数返回一个指向无效内存的指针。结果可能会发生许多不好的事情,很少有好处。注意少数好处。他们是等待最合适的罢工时间的骗子。

维护OP结构的最简单方法是使用std::string在函数内部执行字符串操作。

std::string getFileName(int* pc1_no, char* suite)
{
    std::string pCard1 = "cards/";
    pCard1 += std::string(suite);
    pCard1 += std::to_string(*pc1_no);
    pCard1 += std::string(".bmp");
    return pCard1;
}

以上是可怕的代码,既冗长又低效,但我们已经在介绍中介绍了正确的方法。这只是通向正确方式的逻辑进展的接触点。

更快,更简单的是利用std::stringstream无需外界帮助即可格式化c风格的字符串和数字。在std::to_string可用于C ++ 11标准之前,这种方法可能是最好的。

std::string getFileName(int* pc1_no, char* suite)
{
    std::stringstream pCard1;
    pCard1<< "cards/" << suite << *pc1_no << ".bmp";
    return pCard1.str();
}

有可能性能损失会使string按值返回,但过去几十年的编译器擅长检测并利用opportunities to omit unnecessary copyingemploying move semantics behind the scenes

按值返回string也远比动态分配存储并将存储返回给调用者并且期望调用者释放它更容易出错。任何可能存在的性能损失很可能都是值得的。 Profile the code to be sure.

改善功能调用:

pc1_no作为指针传递并没有任何帮助。除非您需要修改函数内部的值,否则只需按值传递。如果您确实需要更改值,请选择参考。

std::string getFileName(int pc1_no, char* suite)

如果您尝试传递字符串文字:例如:

getFileName(&somenumber, "string literal");

字符串文字可能位于不可写的内存中,并且在C ++中始终为const char *。将const值传递到可能尝试更改值的空间是不好的形式。这允许在较旧的C ++标准下向后兼容C,尽管它可能会产生警告,但在C ++ 11标准之后是非法的。

如果你的函数不需要修改char数组的内容,而这不是,那么将字符串标记为const并允许编译器防止意外发生是一个好习惯。您的编译器是否允许const进行非const分配:

std::string getFileName(int pc1_no, const char* suite)

如果您使用对const std::string的引用,则可能具有更多功能,因为它可以从const和非const char数组隐式转换,并允许其余部分您的计划可以充分利用std::string的诸多好处,而无需拨打c_strdata

std::string getFileName(int pc1_no, 
                        const std::string & suite)

这让我们回到了这个答案的位置。

答案 1 :(得分:7)

以下是此代码在C ++中的外观:

#include <string>

std::string getFileName(int* n, const std::string& suite) {
  return "cards/" + suite + std::to_string(*n) + ".bmp";
}

更好的方法是按值(int n)取第一个参数,并在必要时在呼叫站点取消引用。

答案 2 :(得分:0)

char* getFileName(int pc1_no, char* suite)
{
    static char pCard1[80]; // Guarantee safe pointer return
    strcpy_s(pCard1, "cards/");
    strcat_s(pCard1, suite);
    string str = to_string(pc1_no);
    char const *pchar = str.c_str();
    strcat_s(pCard1, pchar);
    strcat_s(pCard1, ".bmp");

    return pCard1; // Now you don't lose the result.
}

或者您可以使用已经回答的推荐C ++样式。