zoukankan      html  css  js  c++  java
  • 字符串格式化输出

        C 语言中提供了一些基本字符串格式化处理函数,包括:

        1)puts("this is a string");  简单输出字符串到 standard output 中,该函数只有多字节版本;

        2)int len = printf("1 + 2 = %d", 1 + 2); 格式化输出字符串到 standard output 中,返回值表示输出字符串长度,其 Unicode 版本为 wprintf(const wchar_t *_Format, ...);

        3)int len = sprintf(szBuffer, "1 + 2 = %d", 1 + 2); 格式化输出字符串到 szBuffer 中,返回值表示输出字符串长度,其中 szBuffer 定义:char szBuffer[1024];

        4)当需要自己构造 printf-like 格式函数,可以借助 vsprintf 函数,具体如下:

     1 int MyMessageBox (char* szCaption, char* szFormat, ...)
     2 {
     3      char szBuffer [1024] ;
     4      va_list pArgList ;
     5 
     6      // The va_start macro (defined in STDARG.H) is usually equivalent to:
     7      // pArgList = &szFormat + sizeof (szFormat) ;
     8 
     9      va_start (pArgList, szFormat) ;
    10 
    11      vsprintf (szBuffer, szFormat, pArgList) ;
    12 
    13      // The va_end macro just zeroes out pArgList for no good reason
    14      va_end (pArgList) ;
    15 
    16      return MessageBoxA (NULL, szBuffer, szCaption, 0) ;
    17 }

         va_list 保存了函数参数栈第一个可变参数指针,结合格式化字符串 szFormat 给出每个格式化数据类型,vsprintf 访问每一个参数,完成格式化工作。这是可变参数函数工作原理。具体解析如下:

        a. 定义 typedef char *va_list;

        b. va_start (pArgList, szFormat) ;语句使 pArgList 指向第一个可变参数,szFormat 给出第一个可变参数前一个参数位置;

        c. type va_arg(va_list ap, type);语句取出下一个可变参数值,其中 type 指定该可变参数类型;在以上代码中 vsprintf 内部完成了该工作;

        d. va_end (pArgList) ; 语句关闭 pArgList 指针,保持程序健壮性;

        以上方法实现可变参数访问,在函数调用中,函数参数从右到左入栈。只要直到其中任意一个参数位置,可以根据参数位置以及参数类型访问到任意一个参数。下面构造一个简单的可变参数访问函数以说明其原理:

        

     1 // agrc 表示可变参数个数,可变参数类型均为整数
     2 void ArgAnalyze(int argc, ...)
     3 {
     4     int *ptr = &argc;
     5     ++ptr;
     6     for(int i = 0; i < argc; ++i)
     7     {
     8         std::cout<<"argv"<<i + 1<<" = "<<*ptr<<std::endl;
     9         ++ptr;
    10     }
    11 }

        5) sprintf, vsprintf 函数存在一些缺陷,当传入 Buffer 空间小于格式化字符串空间时,函数会覆盖邻近区域,可能导致程序异常错误。因此,微软特别定义了一些安全函数:_snprintf, _vsnprintf,通过增加传入空间参数来避免该错误。同时,微软也给出了对应的 windows 版本函数,基本与C库版本一致。以下给出 sprintf, vsprintf 相关的安全版本, Unicode 版本以及通用版本:

                                            ASCII            Wide-Character      Generic

        standard version         sprintf            swprintf                  _stprintf

        safe version                _snprintf         _snwprintf              _sntprintf

        windows version         wsprintfA        wsprintfW              wsprintf

        -------------------------------------------------------------------------------------

        standar version           vsprintf            vswprintf               _vstprintf

        safe version                _vsnprintf        _vsnwprintf           _vsntprintf

        windows version         wvsprintfA       wvsprintfW            wvsprintf

       在 c++ 库中,也提供了相应的字符串格式化输出,具体如下:

        

     1 // 输出到 standart output(多字节版本)
     2 std::cout<<"1 + 2 = "<<1 + 2<<std::endl;  
     3 
     4 // 输出到 standart output(宽字节版本)
     5 std::wcout<<L"1 + 2 = "<<1 + 2<<std::endl; 
     6 
     7 // 输出到字符串中(多字节版本)
     8 std::stringstream ss;
     9 ss<<"1 + 2 = "<<1 + 2<<std::endl;
    10 std::string s = ss.str();
    11 
    12 // 输出到字符串中(宽字节版本)
    13 std::wstringstream wss;
    14 wss<<L"1 + 2 = "<<1 + 2<<std::endl;
    15 std::wstring ws = wss.str();

        参考资料 Programming Windows by Charles Petzold

  • 相关阅读:
    原生JS发送Ajax请求、JSONP
    python Flask中html模版中如何引用css,js等资源
    python 单例与数据库连接池 及相关选择
    费曼致学生真野光一
    Winform判断EventHandler是否已经添加
    The list of pre-build cross-compiler
    Extended VM Disk In VirtualBox or VMware (虚拟机磁盘扩容)
    一张图了解SSH端口转发
    显卡驱动卸载清理工具
    Oracle分析函数
  • 原文地址:https://www.cnblogs.com/luofeiju/p/12566065.html
Copyright © 2011-2022 走看看