我的文件名需要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;
}
当然,返回垃圾。我没有得到指针值。我很确定我用指针犯了一个愚蠢的错误。提前谢谢。
答案 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 copying和employing 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_str
和data
。
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 ++样式。