我正在使用其STL中没有std::to_string(...)
的旧C ++编译器。我想将整数字符串化,所以我认为我已经被char* itoa (int value, char* str, int base)
困住了。我想避免创建一个名为char[]
的用作itoa()
的第二个参数。可以这样做吗?
我知道我能做到
itoa(5, "abcd", 10)
但这实际上是错误的,因为" abcd"实际上是一个const char[]
,我怀疑最终的行为最多是未定义的。当然,抛弃常量是不可接受的。
有没有办法将参数列表中的匿名非const char []传递给函数?我在各种尝试中使用了语法,但无法想出任何东西。我在网上看了很多,包括StackOverflow,并没有遇到任何覆盖这个问题的Q& A。
感谢您的指导。
更新
我在原帖中忽略了:我还需要char []在堆栈上,即new
ing / malloc
一个char []不是一个选项这个练习。
更新2:
我已经收到了一些上下文请求,所以这里有:
重申:我坚持使用不支持std::to_string(...)
的旧编译器
我希望这样做:
std::string foo(std::string(itoa(42, < *** non-const stack-allocated char[] *** > , 10)))
即。我真正想做的就是构造一个带有整数字符串化的std::string
。
为什么呢?好的,更多的背景:
我试图创建一个命名信号量,并将其命名为pid。所以这个电话理论上看起来像是:
sem_open(std::string(typeinfo(*this).name()).append(std::string(itoa(getpid(), < *** non-const stack-allocated char[] *** >, 10))))
我为什么要这样做?
在我看来,这可能是错过森林树木的情况
也许。这部分是学术练习,我只是想知道它是否在C ++语法中执行此操作。但除此之外,通过避免堆分配有一个代码卫生元素:我可能会忘记在我的析构函数中delete[]
char
。而且,我的假设char[]
的生命周期实际上只需要用于创建信号量。难道从语法上保证它只能在需要的时间内存活吗?这就是RAII毕竟是什么,所以最终这个问题是RAII是否可以针对这种特定情况实施。
再次感谢您的回答和评论。
更新3
谢谢大家的回答。我认识并理解所给出的答案,但我希望找到一个也避免包装函数的答案。这是我的疏忽,我在最初的问题中没有提到这一点。这个问题可能从一开始就措辞得很厉害;我应该首先揭示上下文是为了创建一个信号量,这可能也引导了评论者的不同。我试图简洁而准确地表达我的问题,但我试图简化问题陈述最终留下了相关的背景;抱歉...
但是,我已经对自己做了一个不敬虔的回答。我可能已经正式潜入IOCCC领域,但是:sem_open(std::string(typeinfo(*this).name()).append(static_cast<std::ostringstream&>(std::ostringstream() << getpid()).str().c_str()))
答案 0 :(得分:3)
在我看来,这可能是错过森林树木的情况。
据我了解你的问题,你正在尝试实现std::to_string
的替换,因为你的编译器没有它。
并且您希望将其用于简单int
转换的用例。
让你的包装函数充分调整std::vector<char>
,将其用于转换的char *
缓冲区,然后从缓冲区构造一个std::string
,替换函数返回。
而且,对于纯C ++解决方案:
std::string int_to_string(int n)
{
std::ostringstream o;
o << n;
return o.str();
}
答案 1 :(得分:2)
您不能获取匿名临时地址并将其保持活动状态,但可能存在一些涉及命名引用的黑客,但这些不适用于数组。
因此,您基本上需要使用命名数组。但是,您可以将其包装在 function 调用中,无论如何都会返回std::string
。
std::string my_to_string(int val, int base)
{
/* Big enough buffer for base=2. */
char buf[sizeof(int) * CHAR_BIT + 1];
(void)itoa(val, buf, base);
return buf;
}
答案 2 :(得分:1)
您可以动态分配字符串。
char *result = itoa(5, new char[5], 10);
但是你必须记得使用:
delete[] result;
答案 3 :(得分:0)
由于您需要避免动态分配,因此您无法使用std::string
,除非您确定所有相关编译器都使用短缓冲区优化,并且对于所有相关编译器而言,固定缓冲区足够大所有可能的用例。但是,我们只能说,你不能使用std::string
。
然后创建基于堆栈的缓冲区很容易。 std::numeric_limits<int>
告诉您最大小数位数。但是,由于您使用的是较旧的编译器,因此它可能不支持constexpr
。因此,只需使用<limits.h>
中的静态已知值进行计算。添加1表示符号,您有最大字符数。添加1表示零终止,并且缓冲区大小为N.
现在创建一个类Stringified
,其内部缓冲区为N char
,构造函数将int
(可能还有一个基数)作为参数。
您可以使用该类创建临时(它持续到完整表达式的结尾)或创建变量,在两种情况下都完全基于堆栈,例如像这样:
#include <stdio.h>
//#include <limits>
#include <limits.h>
#include <stdexcept>
#include <string>
bool hopefully( bool const condition ) { return condition; }
bool fail( std::string const& s ) { throw std::runtime_error( s ); }
int const n_digits_of_int =
//std::numeric_limits<int>::digits10() + 1;
1+ 3*CHAR_BIT*sizeof( int )/10;
class Stringified
{
private:
enum{ buffer_size = n_digits_of_int + 2 };
char buffer[buffer_size];
public:
char const* c_str() const { return buffer; }
explicit Stringified( int const value )
{
int const n_chars = sprintf( buffer, "%d", value );
hopefully( n_chars > 0 )
|| fail( "Stringified::<init>: failed to convert value" );
}
};
int main()
{
printf( "%s\n", Stringified( 42 ).c_str() );
}