目标:为string对象提供一个printf形式的格式化函数
方法:vsprintf先输出到一个char[],再拷贝到string变量中
问题:vsprintf输出的char[]缓冲区该开多大?
开小了可能不够,开大了浪费空间,多大是够大?
有没有函数能预先计算出目标串的长度?
有没有其他思路解决这个问题?
char fmt_buf[4096];
int stringprintf( string& str, char* fmt, ... )
{
va_list args;
va_start(args, fmt);
if ( vsnprintf ( fmt_buf, sizeof(fmt_buf)-1, fmt, args ) < 0 ) return -1;
str = fmt_buf;
va_end(args);
return ( str.size() );
}
想到个复杂的办法
虽然不能预先知道多大,但缓冲区不够大时是可以发现的,发现不够大时malloc扩大一倍缓冲区,一直到够大为止
len=1024; //初始缓冲区1024
buf=malloc(len);
while ( vnsprintf(buf,...) == -1 && len <1M ) { // 缓冲区不够大
len *= 2; // 缓冲区扩大一倍
buf=realloc(len);
}
好象有点疯狂
代码说话,这是从我工程里摘取的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
shared_ptr<string> format(
const
char
* fmt, ...)
{
va_list
ap;
va_start
(ap, fmt);
vector<
char
> buf(1024);
int
ret;
while
((ret = vsnprintf_s(&buf[0], buf.size(), buf.size(), fmt, ap)) == -1)
{
buf.resize(buf.size() * 2);
}
va_end
(ap);
if
(ret ==
static_cast
<
int
>(buf.size()))
{
buf[buf.size() - 1] =
'\0'
;
}
return
shared_ptr<string>(
new
string(&buf[0]));
}
|
|
|
-
hairetz
-
心欲小而智欲大
-
等级:
更多勋章
|
#14 得分:0回复于: 2009-04-11 11:17:51 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
int
stringprintf( string& str,
int
num,
int
max,
char
* fmt, ... ) ;
int
main(
int
argc,
char
*argv[])
{
int
n;
string str;
n=stringprintf(str,2,20,
"%d %s"
, 123,
"abcde"
);
cout<<str<<endl;
return
0;
}
int
stringprintf( string& str,
int
num,
int
max,
char
* fmt, ... )
{
va_list
args;
va_start
(args, fmt);
char
*fmt_buf=
new
char
[num*max];
if
( _vsnprintf ( fmt_buf, num*50, fmt, args ) < 0 )
return
-1;
str = fmt_buf;
delete
[]fmt_buf;
va_end
(args);
return
( str.size() );
}
|
只能这样了。
|
|
-
nde123456
-
该用户很懒,没设置昵称
-
等级:
|
#15 得分:0回复于: 2009-04-11 11:19:08 |
13楼的老兄:还真有人这么干啊,看来不是我一个人在钻牛角尖
声明一下,我12楼的内容不是抄你的哦,纯属巧合,看看发表时间和楼层号就知道,呵呵
|