2014-09-24 41 views
-2

我想C++编写自己的printf FUNC键实践的研究,但我得到以下运行时错误,我想不通为什么:自己的printf函数不起作用

Access violation reading location 0x33333333. 

下面的代码:

void myPrintf(char* szStr, ...) 
{ 
    va_list marker; 
    va_start(marker, szStr); 
    va_arg(marker, char*); 
    char opCode; 
    int nLen = istrlen(szStr); 
    for (int i = 0; i < nLen; i++) 
    { 
     if (szStr[i] != '%') 
      cout << szStr[i]; 
     else 
     { 
      if (i + 1 < nLen) 
      { 
       opCode = szStr[i + 1]; 
       switch (opCode) 
       { 
       case 'd': 
        cout << va_arg(marker, int); 
        i += 2; 
        break; 
       case 'f': 
        cout << va_arg(marker, float); 
        i += 2; 
        break; 
       case 's': 
        cout << va_arg(marker, char*); 
        i += 2; 
        break; 
       default: 
        cout << '%'; 
        break; 
       } 
      } 
      else 
       cout << '%'; 
     } 
    } 
    cout << endl; 
} 

我想不通为什么会这样, 可能有人请告诉我,我做了什么错?

我打电话用下面的代码功能:

myPrintf("%d %s %f", 5, "test", 10.1); 

当程序粉碎它表明我这个代码:

static size_t __CLRCALL_OR_CDECL length(const _Elem *_First) 
    { // find length of null-terminated string 
    return (*_First == 0 ? 0 
     : _CSTD strlen(_First)); 
    } 
+2

所以在调试器,在那里它会崩溃(同样short参数均作为int,等等......通过)?你用什么代码调用你的函数? – lordjeb 2014-09-24 16:06:21

+0

@lordjeb编辑OP – 2014-09-24 16:09:54

+1

是的,但它在哪里崩溃?使用调试器进行调试。 – 2014-09-24 16:12:05

回答

2

第一va_arg(marker, char*);只是va_start(marker, szStr);后也许应该被删除,因为它在szStr(即你的例子中的5)之后消耗了参数。 va_start宏正在消耗开始的论点。

而且float参数始终是作为double传递,因此你va_arg(marker, float);应该是一个va_arg(marker, double);

+0

它不会消耗字符串本身吗? “%d%s%f”? – 2014-09-24 16:24:39

+0

编号'va_start()'设置'marker'指向'szStr'后面的第一个参数。每次调用'va_arg()'时,它都会将'marker'推进到下一个参数并返回一个指向'marker'指向的位置的指针。因此,第一个'va_arg(char *)'消耗'5'参数,所以当解析'“%d”'时,'va_arg(int)'返回''Test“'参数, %s“'然后被解析,'va_arg(char *)'返回'10.1'参数,依此类推。 – 2014-09-24 16:31:53

+0

我认为它消耗了第一个参数,我的不好,我也改变了i + = 2到i ++,因为我忘了它增加了我的每次迭代,除float之外的所有东西都被打印为其他东西,在我的情况下10.1是被打印为4.17233e-008 – 2014-09-24 16:32:41