可以创建匿名非const字符数组
Possible to create anonymous non-const char array?
我正在使用一个较旧的c++编译器,它的STL中没有std::to_string(...)
。我想对一个整数进行字符串化,所以我想我只能用char* itoa (int value, char* str, int base)
了。我想避免创建一个名为char[]
的参数,作为itoa()
的第二个参数。这能做到吗?
我知道我可以做
itoa(5, "abcd", 10)
但这实际上是不正确的,因为"abcd"实际上是一个const char[]
,我怀疑所产生的行为充其量是未定义的。当然,抛弃常量是不可接受的。
是否有办法将参数列表中的匿名非const char[]传递给函数?我尝试了各种各样的语法,但什么也没得到。我在网上搜索了一下,包括StackOverflow,并没有遇到任何涵盖这一点的问题。
谢谢你的指导。
更新:
我忽略了在原来的帖子中提到:我还需要在堆栈上的char[],即new
/malloc
的char[]不是这个练习的选项。
我已经得到了一些上下文请求,所以这里是:
重申一下:我使用的是不支持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()))
在我看来,这可能是只见树木不见森林的情况。
正如我理解你的问题,你正试图实现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();
}
您不能获取匿名临时地址并使其保持活动,除非使用一些涉及命名引用的hack ,但这些不适用于数组。
基本上,你需要使用一个命名数组。但是,您可以将其包装在函数调用中,该函数无论如何都会返回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;
}
可以动态分配字符串
char *result = itoa(5, new char[5], 10);
但是你必须记住使用:
delete[] result;
因为您需要避免动态分配,所以您不能使用std::string
,除非您可以确保对于所有相关编译器它使用短缓冲区优化,并且对于所有相关编译器,固定缓冲区足够大以满足所有可能的用例。但我们只能说,你不能使用std::string
。
那么创建一个基于堆栈的缓冲区就很容易了。std::numeric_limits<int>
告诉您十进制位数的最大数目。但是,由于您使用的是较旧的编译器,它可能不支持constexpr
。因此,只需使用<limits.h>
中的静态已知值来计算此值。符号加1,你就有了最大字符数。为0终止添加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( "%sn", Stringified( 42 ).c_str() );
}
- 需要帮助在 c++ 中将字符串转换为字符 ----错误 "const char *" 类型的值不能用于初始化 "char" 类型的实体
- 使用 fopen 打开 .pak 文件并使该文件应用于 const 无符号字符* (C++)
- 如何在 c++ 中将向量转换为<string>常量字符* const*?
- 为什么 const int 适用于字符大括号初始化?
- 为什么我不能使用与"常量字符*"相同的"const int*"创建一个 int 数组?
- 为什么静态常量字符 * const 变量在为左值时可绑定到右值引用参数
- std::转换为常量字符 * 的字符串在 std::unordered_set<const 字符 * 中找不到>
- 从 sub_match<常量字符 *>' 转换为'const char *const &'
- ERROR字符和const字符
- C++ : 为什么我不能使用 sprintf 打印 const 字符*?
- 赛格在一辆汽车上出错,从无符号的字符转换为 const 字符 在C++
- 通过连接另一个字符*初始化const字符*
- 具有模板参数大小与字符指针的 const 字符数组
- 对Const字符字符串[]使用字符串函数
- 将字符串函数复制到非const字符缓冲区
- 可以创建匿名非const字符数组
- 如何在c++中将pid转换为const字符指针
- c++字符到const字符*
- 将字符串转换为 const* 字符
- 无法成功返回我通过在字符串上调用 c_str() 创建的 const 字符*。(C++)