_stprintf_s和_stscanf_s函数与UNICODE编码

12 篇文章 0 订阅
_stprintf_s和_stscanf_s函数与UNICODE编码 
一、核心内容 
 该文档适用于微软的visual C++ 平台。  需要头文件:<TCHAR.H> 
 MSDN上对stprintf_s和_stscanf_s函数的定义:  

TCHAR.H routine   

_stprintf_s  _stscanf_s  

_UNICODE & _MBCS not defined  sprintf_s  sscanf_s

_MBCS defined    sprintf_s sscanf_s

_UNICODE defined   swprintf_s    swscanf_s 

对应的代码为: 
#ifdef UNICODE 
#define _stprintf_s    swprintf_s #else 
#define _stprintf_s    sprintf_s 
 前面的t表示编码,后面的_s表示检查内存溢出,前面的_表示非标准库函数。 
 从上我们可以看出,_stprintf_s和_stscanf_s是为适应不同编码而定义的两个宏,在不同的编码环境下他们所表示的函数是不同的。  _s是security的意思,具体含义参见后面的Security Remarks部分。  

(1)

int   sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format [, argument] ... );  //ANSI版本 

int   swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format [,argument]...); //UNICODE版本

           这个函数的主要作用是将若干个argument按照format格式存到buffer中。  
            buffer:输出的字符 

            sizeOfBuffer:buffer的长度,以能存放的字符数计算,而不是已占用的字节数计算。非常关键。一个UNICODE字符占用2个字节。        

format:格式字符串,比如%s            

argument:可选参数 

(2)

int   sscanf_s( const char *buffer, const char *format [, argument ] ... ); 

int   swscanf_s( const wchar_t *buffer, const wchar_t *format [, argument ] ... ); 
 
函数具体细节参考http://msdn.microsoft.com/en-us/library/t6z7bya3(v=vs.80).aspx 。 
     这个函数的主要作用是从buffer中读取指定格式(format)的字符到相应的argument中。参数同上 Security Remarks: 
Unlike the less secure version sscanf, a buffer size parameter sizeOfBuffer is required when using the type field characters c, C, s, S and [. This parameter must be supplied as an additional parameter after each buffer which requires it. 用于检查内存是否溢出。 几个需要注意的细节: 
 为了让编译器识别Unicode字符串,必须以在前面加一个“L”, 定义宽字节类型方法如下:L“ABC”,表示字符串“ABC”是用UNICODE编码
的。 
 char与wchar_t的区别: char中存放的是单字节型的字符,wchar_t中存放的是双字节型的字符,TCHAR在定义了_UNICODE时等同于wchar_t,
在未定义_UNICODE时等同于char。 
 
例子1 (sscanf_s和printf_s,用于ANSI编码): 
// crt_sscanf_s.c 
// This program uses sscanf_s to read data items // from a string named tokenstring, then displays them.   

#include <stdio.h>  
int main( void ) { 
   char  tokenstring[] = "15 12 14...";    char  s[81];    char  c;    int   i;    float fp;  
   // Input various data from tokenstring: 
   // max 80 character string plus NULL terminator 

   sscanf_s( tokenstring, "%s", s, sizeof(s) ); //对照上面的Security Remarks部分进行理解    

   sscanf_s( tokenstring, "%c", &c, sizeof(char) );    

   sscanf_s( tokenstring, "%d", &i );    

   sscanf_s( tokenstring, "%f", &fp );  

   // Output the data read 

   printf_s( "String    = %s\n", s );    

   printf_s( "Character = %c\n", c );    

   printf_s( "Integer:  = %d\n", i );    

   printf_s( "Real:     = %f\n", fp );    

   return 0; } 

 
例子2 (swscanf_s和wprintf_s,用于UNICODE编码): 

// crt_swscanf_s.c 
// This program uses swscanf_s to read data items // from a string named tokenstring, then displays them.   
#include <stdio.h>  
int main( void ) { 
   wchar_t  tokenstring[] = L"15 12 14...";    wchar_t  s[81];    wchar_t  c;    int   i;    float fp;  
   // Input various data from tokenstring: 
   // max 80 character string plus NULL terminator    cout<<sizeof(wchar_t)<<"  "<<_countof(s)<<endl; 
   swscanf_s( tokenstring, L"%s", s, _countof(s));  

   swscanf_s( tokenstring, L"%c", &c, sizeof(wchar_t) );    

   swscanf_s( tokenstring, L"%d", &i );    

   swscanf_s( tokenstring, L"%f", &fp );  

   // Output the data read 

   wprintf_s( L"String    = %s\n", s );    

   wprintf_s( L"Character = %c\n", c );    

   wprintf_s( L"Integer:  = %d\n", i ); 

   wprintf_s( L"Real:     = %f\n", fp );    

   return 0; } 

 
例子3 (_stscanf_s和_tprintf_s,将例1和例2的代码统一处理): 
#include <stdio.h>  
int main( void ) { 
   TCHAR  tokenstring[] = TEXT("15 12 14...");    TCHAR  s[81];    TCHAR  c;    int   i;    float fp;  
   // Input various data from tokenstring: 
   // max 80 character string plus NULL terminator    cout<<sizeof(TCHAR)<<"  "<<_countof(s)<<endl; 

   _stscanf_s( tokenstring, TEXT("%s"), s, _countof(s));     

   _stscanf_s( tokenstring, TEXT("%c"), &c, sizeof(TCHAR) );    

   _stscanf_s( tokenstring, TEXT("%d"), &i );   

    _stscanf_s( tokenstring, TEXT("%f"), &fp );  

   // Output the data read 

   _tprintf_s( TEXT("String    = %s\n"), s );    

   _tprintf_s( TEXT("Character = %c\n"), c );

wchar_t *fgetws( wchar_t *string, int n, FILE *stream);   //UNICODE版本 
 其中,第二个参数n的值是最多可以读出的字符数目,该值不应该大于参数一所对应的字符数组的长度。 
 函数的作用是从第三个参数指定的文件流中读取文件的一行信息,存放到参数一string所对应的字符数组中,读出的字符数据包括换行符“\n”。这
一点需要注意。 
 如果想从键盘读入一行字符,第三个参数为 stdin . 例如,char buf[10];  fgets(buf, 10, stdin)   gets()函数已经过时了,用fgets()函数代替gets()函数。 
 _fgetts是一个宏,如果定义了UNICODE,就是fgetws函数;如果未定义UNICODE,就是fgets函数。  用TCHAR代替char,用_fgetts代替fgets或fgetws。就将ANSI和UNICODE函数编码统一起来了。 对这两个函数的更具体的讲解,请参考http://wenku.baidu.com/view/d66839f57c1cfad6195fa781.html 
3. ANSI和UNICODE字符和字符串处理函数,参考网页http://blog.sina.com.cn/s/blog_6b5a0745010108fh.html 
  统一ANSI和UNICODE字符和字符串处理函数的宏定义,在上述网页中没有列出,这些宏的规律是“把UNICODE字符和字符串处理函数中的w标识替换为t,并在前面加上一个下划线_”。例如, 
TCHAR.H routine 
_UNICODE defined 
_MBCS defined 
_UNICODE & _MBCS not defined 
_tcslen 
wcslen 
strlen 
strlen 
_fgetts fgetws fgets fgets _tcsncpy 
wcsncpy 
strncpy 
strncpy 
 
4. 注意:如果在程序中使用了TCHAR,那么就不应该使用ANSI的strXXX函数或者Unicode的wcsXXX函数了,而必须使用tchar.h中定义的_tcsXXX函数。 
5. 有人建议,不要再使用TCHAR和_T了!他分析了原因后总结:如果您正开始一个新的项目,请无论如何也要顶住压力,直接使用UNICODE编码!切记!您只需要对您的组员进行10分钟的培训,记住strcpy用 wcscpy,sprintf用swprintf代替,常数前加L,就可以了!它不会花您很多时间的,带给您的是稳定和安全!个人觉得有道理。



  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
#include <graphics.h> // 引用图形库头文件 #include <conio.h> #include<time.h> #if 0 int main1() { initgraph(640, 480); MOUSEMSG m; int r;// 创建绘图窗口,大小为 640x480 像素 while (1) { m = GetMouseMsg(); switch (m.uMsg) { case WM_MOUSEMOVE: setcolor(RGB(rand() % 91 + 10, rand() % 91 + 10, rand() % 91 + 10)); if (m.mkLButton) { circle(m.x, m.y, rand() % 91 + 10); break; } else if (m.mkRButton) { r = rand() % 91 + 10; rectangle(m.x - r, m.y - r, m.x + r, m.y + r); } } } _getch(); // 按任意键继续 closegraph(); // 关闭绘图窗口 } const int BoardW = 5; const int BoardH = 5; const int GridSz = 100; const int Edge = 30; void drawGrid() { setbkcolor(RGB(0, 162, 232));//背景颜色 cleardevice();//用当前背景颜色全涂色 setcolor(RGB(0, 0, 0));//边框用黑线 for (int i = 0; i <= BoardH; ++i) { line(Edge, Edge + i*GridSz, Edge + BoardW*GridSz, Edge + i*GridSz); } for (int i = 0; i <= BoardH; ++i) { line(Edge + i*GridSz, Edge, Edge + i*GridSz, Edge + BoardH*GridSz); } } void drawLayout(int layout[BoardH][BoardW]) { int r = GridSz * 4 / 10; int x, y; setcolor(RGB(255, 201, 14));//棋子边的颜色 setfillcolor(RGB(255, 201, 14));//棋子的填充色 for (int i = 0; i<BoardH; i++) { for (int j = 0; j<BoardW; j++) { if (1 == layout[i][j]) { x = Edge + j*GridSz + GridSz / 2; y = Edge + i*GridSz + GridSz / 2; fillcircle(x, y, r); } } } } void UpdateLayout(int Layout[BoardH][BoardW], int x, int y) { if (x <= Edge || x >= Edge + BoardW*GridSz || y <= Edge || y >= Edge + BoardH*GridSz) { return; } int i, j; i = (y - Edge) / GridSz; j = (x - Edge) / GridSz; Layout[i][j] = 1 - Layout[i][j]; if (i - 1 >= 0) { Layout[i - 1][j] = 1 - Layout[i - 1][j]; } if (i + 1 < BoardH) { Layout[i + 1][j] = 1 - Layout[i + 1][j]; } if (j - 1 >= 0) { Layout[i][j - 1] = 1 - Layout[i][j - 1]; } if (j + 1 < BoardW) { Layout[i][j + 1] = 1 - Layout[i][j + 1]; } } int isGameOver(int layout[BoardH][BoardW]) { int sum = 0; for (int i = 0; i < BoardH; i++) { for (int j = 0; j<BoardW; j++) { sum += layout[i][j]; } } if (0 == sum) { return 1; } else { return 0; } } int initLayout(int layout[BoardH][BoardW]) { int k = 0; srand((int)time(0)); for (int i = 0; i<BoardH; i++) { for (int j = 0; j<BoardW; j++) { k = rand() % 5; if (0 == k || 1 == k) { layout[i][j] = k; } } } return layout[BoardH][BoardW]; } int main() { int layout[BoardH][BoardW] = { 0 };//layout 布局 (棋盘的布局) HWND hwnd; hwnd = initgraph(BoardW*GridSz + 2 * Edge, BoardH*GridSz + 2 * Edge); while (1) { initLayout(layout); drawGrid();//画棋盘 drawLayout(layout);//画棋盘布局 MOUSEMSG m; while (!isGameOver(layout)) { m = GetMouseMsg(); switch (m.uMsg) { case WM_LBUTTONDOWN: UpdateLayout(layout, m.x, m.y); break; } drawGrid();//画棋盘 drawLayout(layout);//画棋盘布局 } MessageBox(hwnd, _T("恭喜过关!"), _T("提示"), MB_OK); } _getch(); closegraph(); return 0; } #endif //贴图 #if 0 int main() { initgraph(640, 480); IMAGE imgMask, imgSrc; loadimage(&imgMask;, _T("./mask.jpg")); loadimage(&imgSrc;, _T("./src.jpg")); putimage(100, 200, &imgMask;, SRCAND); putimage(100, 200, &imgSrc;, SRCPAINT); _getch(); closegraph(); return 0; } #endif //时间及文本显示 #if 0 int main() { initgraph(640, 480); time_t start, end; time(&start;); _getch(); time(&end;); TCHAR s[128]; _stprintf(s, _T("相隔时间:%d秒"), (end - start)); settextcolor(RGB(255, 255, 0)); settextstyle(100, 0, _T("隶书")); outtextxy(0, 0, s); _getch(); closegraph(); return 0; } #endif //声音播放 #if 0 #include"mmsystem.h" #pragma comment(lib,"winmm.lib") int main() { mciSendString(_T("open BGM.mp3 alias bgm"), NULL, 0, NULL); mciSendString(_T("open 123.mp3 123 bgm"), NULL, 0, NULL); while (1) { char key = _getch(); switch (key) { case 'p': mciSendString(_T("seek bgm to 0"), NULL, 0, NULL); mciSendString(_T("play bgm"), NULL, 0, NULL); break; //case 's': // mciSendString(_T("stop bgm"), NULL, 0, NULL); // break; case 't': mciSendString(_T("pause bgm"), NULL, 0, NULL); break; case 'r': mciSendString(_T("resume bgm"), NULL, 0, NULL); break; case 'c': goto lp; break; case 'o': mciSendString(_T("play 123"), NULL, 0, NULL); break; } } lp: mciSendString(_T("close bgm"), NULL, 0, NULL); return 0; } #endif #if 0 #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { srand(time(NULL));//1970.1.1 00:00:00 for (int i = 0; i < 10; ++i) { printf("%d,", rand()); } return 0; } /* 伪随机 */ #endif

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值