调用sprintf函数的问题

现在还是人类 2010-03-09 01:28:05
我在写一个类,里面想模拟CString类作一个Format函数,所以就想通过调用sprintf函数来模拟,
我是这么做的

void MCString::Format(char * New_Value, ...)
{
//Value是类里的一个公有变量,是 char * 类型
sprintf(Value, New_Value, (va_list)argptr); //不行
//我也这样试验过
//sprintf(Value, New_Value, ...); 也是不行,可能有点不靠谱,呵呵,不过起码尝试过
}

想问一下了解这方面技术的朋友,我该如何处理这种操作呢?
...全文
229 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
引用 14 楼 jingzhongrong 的回复:
使用下面语句计算格式化后的字符串长度:

C/C++ codelen= _vscprintf( format, args )+1;

VC6里没有这个函数
jingzhongrong 2010-03-09
  • 打赏
  • 举报
回复
使用下面语句计算格式化后的字符串长度:

len = _vscprintf( format, args ) + 1;
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
引用 12 楼 wizardk 的回复:
那你也计算不出来

这到未必,只是比较麻烦,我是想看看有什么比较好的方法实现
WizardK 2010-03-09
  • 打赏
  • 举报
回复
引用 11 楼 supermanking 的回复:
谢谢各位的支持,我开始弄了好久没成功,问题出在空间分配问题,后来虽然搞定了,但是还是觉得每中不足。我的程序是这样的:
C/C++ codevoid MCString::Format(char* New_Value, ...)
{if(Value!=NULL)
Value= (char*)realloc(Value,1024);else
Value= (char*)malloc(1024);
va_list ArgList;
va_start(ArgList, New_Value);
vsprintf(Value, New_Value, ArgList);
va_end(ArgList);
LenB= strlen(Value);
}
空间的分配是指定了一个1024字节大小的空间,不能很合适的分配空间大小,如果内容大于1024个字节,
搞不好还会出问题,我另外一个函数是这样的:
C/C++ codevoid MCString::SetValue(char*New_Value)
{
LenB= strlen(New_Value);if(Value!=NULL)
Value= (char*)realloc(Value,LenB);else
Value= (char*)malloc(LenB);

sprintf(Value,"%s",New_Value);
}
这样就可以先知道预分配的空间大小,无论字符串的大小是所还是少都能够自动分配,
我就一直在想如何让我的Format函数也像SetValue函数一样能够很好的控制空间问题,
所以后来又改了一下程序:
C/C++ codevoid MCString::Format(char* New_Value, ...)
{
va_list ArgList;
va_start(ArgList, New_Value);

LenB= strlen(ArgList)+strlen(New_Value);if(Value!=NULL)
Value= (char*)realloc(Value,LenB);else
Value= (char*)malloc(LenB);

vsprintf(Value, New_Value, ArgList);
va_end(ArgList);
}
但是发现还是有问题,是统计字符串数量不正确而产生的,想问一下该如何解决这种问题,
是不是一定要对字符串中的%s、%d...等作处理通过循环才能计算得出应该分配的大小?


那你也计算不出来
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
谢谢各位的支持,我开始弄了好久没成功,问题出在空间分配问题,后来虽然搞定了,但是还是觉得每中不足。我的程序是这样的:

void MCString::Format(char * New_Value, ...)
{
if(Value!=NULL)
Value = (char *)realloc(Value,1024);
else
Value = (char *)malloc(1024);
va_list ArgList;
va_start(ArgList, New_Value);
vsprintf(Value, New_Value, ArgList);
va_end(ArgList);
LenB = strlen(Value);
}

空间的分配是指定了一个1024字节大小的空间,不能很合适的分配空间大小,如果内容大于1024个字节,
搞不好还会出问题,我另外一个函数是这样的:

void MCString::SetValue(char *New_Value)
{
LenB = strlen(New_Value);
if(Value!=NULL)
Value = (char *)realloc(Value,LenB);
else
Value = (char *)malloc(LenB);

sprintf(Value,"%s",New_Value);
}

这样就可以先知道预分配的空间大小,无论字符串的大小是所还是少都能够自动分配,
我就一直在想如何让我的Format函数也像SetValue函数一样能够很好的控制空间问题,
所以后来又改了一下程序:

void MCString::Format(char * New_Value, ...)
{
va_list ArgList;
va_start(ArgList, New_Value);

LenB = strlen(ArgList)+strlen(New_Value);
if(Value!=NULL)
Value = (char *)realloc(Value,LenB);
else
Value = (char *)malloc(LenB);

vsprintf(Value, New_Value, ArgList);
va_end(ArgList);
}

但是发现还是有问题,是统计字符串数量不正确而产生的,想问一下该如何解决这种问题,
是不是一定要对字符串中的%s、%d...等作处理通过循环才能计算得出应该分配的大小?
zhou1xp 2010-03-09
  • 打赏
  • 举报
回复
哦,程序还比较长啊,可以标记下
不动如岳 2010-03-09
  • 打赏
  • 举报
回复
学习,帮顶一下
某某9 2010-03-09
  • 打赏
  • 举报
回复
引用 7 楼 coding_hello 的回复:
不能直接调用sprintf来处理va_list类型的参数。

就用vsprintf吧

void Format(char * New_Value, ...)
{
  va_list ArgList;
  va_start(ArgList, New_Value);
  char Value[1024];
  vsprintf(Value, New_Value, ArgList);
  va_end(ArgList);
}
有道理!!
野男孩 2010-03-09
  • 打赏
  • 举报
回复
不能直接调用sprintf来处理va_list类型的参数。

就用vsprintf吧

void Format(char * New_Value, ...)
{
va_list ArgList;
va_start(ArgList, New_Value);
char Value[1024];
vsprintf(Value, New_Value, ArgList);
va_end(ArgList);
}
小生我怕怕 2010-03-09
  • 打赏
  • 举报
回复
New_Value是格式字符串,Value是用来储存字符串的缓冲区,就是4楼的写法。

cnzdgs 2010-03-09
  • 打赏
  • 举报
回复
如果New_Value是格式字符串,Value是用来储存字符串的缓冲区,就是4楼的写法。
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
引用 1 楼 cnzdgs 的回复:
用vsprintf,MSDN中有例子。

这么弄?

void MCString::Format(char * New_Value, ...)
{
va_list ArgList;
va_start(ArgList, New_Value);
vsprintf(Value, New_Value, ArgList);
va_end(ArgList);
}
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
引用 2 楼 lhcwjy 的回复:
#include <stdio.h>
#include <stdarg.h>
...

想问一下,不能直接调用类似sprintf这样的函数吗?
白云飘飘飘 2010-03-09
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdarg.h>

// Declaration, but not definition, of ShowVar.
void ShowVar( char *szTypes, ... );
int main() {
ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 );
}

// ShowVar takes a format string of the form
// "ifcs", where each character specifies the
// type of the argument in that position.
//
// i = int
// f = float
// c = char
// s = string (char *)
//
// Following the format specification is a variable
// list of arguments. Each argument corresponds to
// a format character in the format string to which
// the szTypes parameter points
void ShowVar( char *szTypes, ... ) {
va_list vl;
int i;

// szTypes is the last argument specified; you must access
// all others using the variable-argument macros.
va_start( vl, szTypes );

// Step through the list.
for( i = 0; szTypes[i] != '\0'; ++i ) {
union Printable_t {
int i;
float f;
char c;
char *s;
} Printable;

switch( szTypes[i] ) { // Type to expect.
case 'i':
Printable.i = va_arg( vl, int );
printf_s( "%i\n", Printable.i );
break;

case 'f':
Printable.f = va_arg( vl, double );
printf_s( "%f\n", Printable.f );
break;

case 'c':
Printable.c = va_arg( vl, char );
printf_s( "%c\n", Printable.c );
break;

case 's':
Printable.s = va_arg( vl, char * );
printf_s( "%s\n", Printable.s );
break;

default:
break;
}
}
va_end( vl );
}

Copy Code
32.400002
a
Test string
4

cnzdgs 2010-03-09
  • 打赏
  • 举报
回复
用vsprintf,MSDN中有例子。
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
哦,最后忘记
free(tempStr);
现在还是人类 2010-03-09
  • 打赏
  • 举报
回复
我这样做了一个函数来取的长度,大家看看有什么问题吗?(虽然我目前用起来没什么问题)

DWORD MCString::GetFormatStringSize(char * StringHand, va_list args)
{
DWORD StringCount;
DWORD i;
DWORD j;
char * tempStr;
char StrOver;
StringCount = 0;
i = 0;
tempStr = (char *)malloc(255);
while((int)StrOver!=0){
StrOver = StringHand[i];
i++;
if((int)StrOver==0){
break;
}else if((int)StrOver==0x0025){
StrOver = StringHand[i];
switch(StringHand[i]){
case 'i':
memset(tempStr,0,255);
sprintf(tempStr,"%d",va_arg(args,int));
j = 0;
while((int)tempStr[j]!=0){
j++;
}
StringCount += j;
break;
case 'd':
memset(tempStr,0,255);
sprintf(tempStr,"%d",va_arg(args,long));
j = 0;
while((int)tempStr[j]!=0){
j++;
}
StringCount += j;
break;
case 'f':
memset(tempStr,0,255);
sprintf(tempStr,"%f",va_arg(args,double));
j = 0;
while((int)tempStr[j]!=0){
j++;
}
StringCount += j;
break;
case 's':
StringCount += strlen(va_arg(args,char *));
break;
case 'c':
StringCount++;
break;
}
i++;

}else if((int)StrOver==0x005C){
i++;
StringCount++;
}else{
StringCount++;
}
}
return StringCount;
}
Eleven 2010-03-09
  • 打赏
  • 举报
回复
// crt_vsprintf.c
// compile with: /W3
// This program uses vsprintf to write to a buffer.
// The size of the buffer is determined by _vscprintf.

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

void test( char * format, ... )
{
va_list args;
int len;
char *buffer;

// retrieve the variable arguments
va_start( args, format );

len = _vscprintf( format, args ) // _vscprintf doesn't count
+ 1; // terminating '\0'

buffer = (char*)malloc( len * sizeof(char) );

vsprintf( buffer, format, args ); // C4996
// Note: vsprintf is deprecated; consider using vsprintf_s instead
puts( buffer );

free( buffer );
}

int main( void )
{
test( "%d %c %d", 123, '<', 456 );
test( "%s", "This is a string" );
}

Copy Code
123 < 456
This is a string

jingzhongrong 2010-03-09
  • 打赏
  • 举报
回复
引用 15 楼 supermanking 的回复:
引用 14 楼 jingzhongrong 的回复:
使用下面语句计算格式化后的字符串长度:

C/C++ codelen= _vscprintf( format, args )+1;
VC6里没有这个函数


还在用VC6。。。

那就先申请一段足够大的空间,调用vsprintf,然后strlen获得字符串的长度,然后在strcpy复制到Value中

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧