1. 程式人生 > >C++中sprintf()函式的使用詳解

C++中sprintf()函式的使用詳解

轉載文章:http://www.jb51.net/article/36937.htm

參考文章:sprintf用法  http://blog.sina.com.cn/s/blog_980cf62a0100ya0z.html

在將各種型別的資料構造成字串時,sprintf 的強大功能很少會讓你失望。由於sprintf 跟printf 在用法上幾乎一樣,只是列印的目的地不同而已,前者列印到字串中,後者則直接在命令列上輸出。這也導致sprintf 比printf 有用得多。

函式簡介

  函式功能:把格式化的資料寫入某個字串   函式原型:int sprintf( char *buffer, const char *format [, argument] … );
  返回值:字串長度(strlen)

引數說明及應用舉例

  sprintf格式的規格如下所示。[]中的部分是可選的。   %[指定引數][識別符號][寬度][.精度]指示符   若想輸出`%'本身時, 請這樣`%%'處理。   1. 處理字元方向。負號時表示從後向前處理。   2. 填空字元。 0 的話表示空格填 0;空格是內定值,表示空格就放著。   3. 字元總寬度。為最小寬度。   4. 精確度。指在小數點後的浮點數位數。   =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

轉換字元

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-   %% 印出百分比符號,不轉換。
  %c 整數轉成對應的 ASCII 字元。   %d 整數轉成十進位。   %f 倍精確度數字轉成浮點數。   %o 整數轉成八進位。   %s 整數轉成字串。   %x 整數轉成小寫十六進位。   %X 整數轉成大寫十六進位。

使用sprintf 的常見問題

  sprintf 是個變參函式,使用時經常出問題,而且只要出問題通常就是能導致程式崩潰的記憶體訪   問錯誤,但好在由sprintf 誤用導致的問題雖然嚴重,卻很容易找出,無非就是那麼幾種情況,通   常用眼睛再把出錯的程式碼多看幾眼就看出來了。   sprintf_s()是sprintf()的安全版本,通過指定緩衝區長度來避免sprintf()存在的溢位風險 。在使用VS2008時如果你使用了sprintf函式,那麼編譯器會發出警告:使用sprintf存在風險,建議使用sprintf_s。這個安全版本的原型是:
  int sprintf_s(char *buffer,size_t sizeOfBuffer,const char *format [,argument] ... ); 緩衝區溢位   第一個引數的長度太短了,沒的說,給個大點的地方吧。當然也可能是後面的引數的問   題,建議變參對應一定要細心,而列印字串時,儘量使用”%.ns”的形式指定最大字元數。   忘記了第一個引數   低階得不能再低階問題,用printf 用得太慣了。//偶就常犯。:。(   變參對應出問題   通常是忘記了提供對應某個格式符的變參,導致以後的引數統統錯位,檢查檢查吧。尤   其是對應”*”的那些引數,都提供了嗎?不要把一個整數對應一個”%s”,編譯器會覺得你   欺她太甚了(編譯器是obj 和exe 的媽媽,應該是個女的,:P)。   strftime   sprnitf 還有個不錯的表妹:strftime,專門用於格式化時間字串的,用法跟她表哥很像,也   是一大堆格式控制符,只是畢竟小姑娘家心細,她還要呼叫者指定緩衝區的最大長度,可能是為   了在出現問題時可以推卸責任吧。這裡舉個例子:   time_t t = time(0);   //產生"YYYY-MM-DD hh:mm:ss"格式的字串。   char s[32];   strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&t));   sprintf 在MFC 中也能找到他的知音:CString::Format,strftime 在MFC 中自然也有她的同道:   CTime::Format,這一對由於從面向物件哪裡得到了贊助,用以寫出的程式碼更覺優雅。
sprintf 是個變參函式,定義如下:
int sprintf( char *buffer, const char *format [, argument] ... );
除了前兩個引數型別固定外,後面可以接任意多個引數。而它的精華,顯然就在第二個引數:
(1)格式化字串上。
printf 和sprintf 都使用格式化字串來指定串的格式,在格式串內部使用一些以“%”開頭的格式說明符(format specifications)來佔據一個位置,在後邊的變參列表中提供相應的變數,最終函式就會用相應位置的變數來替代那個說明符,產生一個呼叫者想要的字串。
格式化數字字串
sprintf 最常見的應用之一莫過於把整數列印到字串中,所以,spritnf 在大多數場合可以替代itoa。
如:
//把整數123 列印成一個字串儲存在s 中。
sprintf(s, "%d", 123); //產生"123"
可以指定寬度,不足的左邊補空格:
sprintf(s, "%8d%8d", 123, 4567); //產生:" 123 4567"
當然也可以左對齊:
sprintf(s, "%-8d%8d", 123, 4567); //產生:"123 4567"
也可以按照16 進位制列印:
sprintf(s, "%8x", 4567); //小寫16 進位制,寬度佔8 個位置,右對齊
sprintf(s, "%-8X", 4568); //大寫16 進位制,寬度佔8 個位置,左對齊
這樣,一個整數的16 進位制字串就很容易得到,但我們在列印16 進位制內容時,通常想要一種左邊補0 的等寬格式,那該怎麼做呢?很簡單,在表示寬度的數字前面加個0 就可以了。
sprintf(s, "%08X", 4567); //產生:"000011D7"
上面以”%d”進行的10 進位制列印同樣也可以使用這種左邊補0 的方式。
這裡要注意一個符號擴充套件的問題:比如,假如我們想列印短整數(short)-1 的記憶體16 進製表示形式,在Win32 平臺上,一個short 型佔2 個位元組,所以我們自然希望用4 個16 進位制數字來列印它:
short si = -1;
sprintf(s, "%04X", si);
產生“FFFFFFFF”,怎麼回事?因為spritnf 是個變參函式,除了前面兩個引數之外,後面的引數都不是型別安全的,函式更沒有辦法僅僅通過一個“%X”就能得知當初函式呼叫前引數壓棧時被壓進來的到底是個4 位元組的整數還是個2 位元組的短整數,所以採取了統一4 位元組的處理方式,導致引數壓棧時做了符號擴充套件,擴充套件成了32 位的整數-1,列印時4 個位置不夠了,就把32 位整數-1 的8 位16 進位制都打印出來了。
如果你想看si 的本來面目,那麼就應該讓編譯器做0 擴充套件而不是符號擴充套件(擴充套件時二進位制左邊補0 而不是補符號位):
sprintf(s, "%04X", (unsigned short)si);
就可以了。或者:
unsigned short si = -1;
sprintf(s, "%04X", si);
sprintf 和printf 還可以按8 進位制列印整數字符串,使用”%o”。注意8 進位制和16 進位制都不會打
印出負數,都是無符號的,實際上也就是變數的內部編碼的直接的16 進位制或8 進製表示。
控制浮點數列印格式
浮點數的列印和格式控制是sprintf 的又一大常用功能,浮點數使用格式符”%f”控制,預設保
留小數點後6 位數字,比如:
sprintf(s, "%f", 3.1415926); //產生"3.141593"
但有時我們希望自己控制列印的寬度和小數位數,這時就應該使用:”%m.nf”格式,其中m 表
示列印的寬度,n 表示小數點後的位數。比如:
sprintf(s, "%10.3f", 3.1415626); //產生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產生:"3.142"
注意一個問題,你猜
int i = 100;
sprintf(s, "%.2f", i);
會打出什麼東東來?“100.00”?對嗎?自己試試就知道了,同時也試試下面這個:
sprintf(s, "%.2f", (double)i);
第一個打出來的肯定不是正確結果,原因跟前面提到的一樣,引數壓棧時呼叫者並不知道跟i相對應的格式控制符是個”%f”。而函式執行時函式本身則並不知道當年被壓入棧裡的是個整數,於是可憐的儲存整數i 的那4 個位元組就被不由分說地強行作為浮點數格式來解釋了,整個亂套了。不過,如果有人有興趣使用手工編碼一個浮點數,那麼倒可以使用這種方法來檢驗一下你手工編排的結果是否正確。

相關推薦

C++建構函式

                                        c++類的建構函式詳解                         一、 建構函式是幹什麼的 class Counter { public:          // 類Counter的建構函式          // 特點:

C++ malloc函式(轉載)

一、原型:extern void *malloc(unsigned int num_bytes); 標頭檔案:#include <malloc.h> 或 #include <alloc.h> (注意:alloc.h 與 malloc.h

C++sprintf()函式的使用

轉載文章:http://www.jb51.net/article/36937.htm 參考文章:sprintf用法  http://blog.sina.com.cn/s/blog_980cf62a0100ya0z.html 在將各種型別的資料構造成字串時,sprintf 的

整理:C++sprintf()函式的使用

sprintf 是個變參函式,定義如下:int sprintf( char *buffer, const char *format [, argument] ... ); 除了前兩個引數型別固定外,後面可以接任意多個引數。而它的精華,顯然就在第二個引數:(1)格式化字串上。printf 和sprintf 都使

C/C++extern關鍵字

編譯器 fin 生成 接口 bcd 只需要 c++環境 結束 編程 轉自:http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777431.html 1 基本解釋:extern可以置於變量或者函數前,以標示變量或者

C/C++作用域(轉)

防止 局部作用域 gist 文件中 方式 為什麽不使用 形式參數 lan archive 作用域規則告訴我們一個變量的有效範圍,它在哪兒創建,在哪兒銷毀(也就是說超出了作用域)。變量的有效作用域從它的定義點開始,到和定義變量之前最鄰近的開括號配對的第一個閉括號。也就是說,作

C#const用法

htm 鏈接 服務器 span img body 用法詳解 -s 設計 本文實例講述了C#中const用法。分享給大家供大家參考。具體用法分析如下: const是一個c語言的關鍵字,它限定一個變量不允許被改變。使用const在一定程度上可以提高程序的安全性和可靠性,另外,

C#protected用法

base 而是 報錯 public 我們 此刻 訪問 .html 定義 轉自(https://www.cnblogs.com/wangyt223/archive/2012/08/08/2627801.html) 在c#的可訪問性級別中,public和private算是最

c/c++static的

extern info system pan 特點 靜態成員 額外 定義 全局 C 語言的 static 關鍵字有三種(具體來說是兩種)用途: 1. 靜態局部變量:用於函數體內部修飾變量,這種變量的生存期長於該函數。 int foo(){ st

C#ToString()格式

padding design otn href 有效 詳解 pattern console AS 以下內容均摘自博客園,僅供資料查詢。原文連接http://www.cnblogs.com/xdotnet/archive/2009/01/17/tostring_format.

C++的繼承

C++ 繼承 [TOC] 繼承基本知識 定義:  繼承是面向對復用的重要手段。通過繼承定義一個類,繼承是類型之間的關系建模,共享公有的東西,實現各自本質不同的東西。 繼承關系:  三種繼承關系下基類成員的在派生類的訪問關系變化(圖) 舉個栗子(公有繼承) ```c+

C++列舉enum

轉載部落格地址:https://blog.csdn.net/bruce_0712/article/details/54984371     眾所周知,C/C++語言可以使用#define和const建立符號常量,而使用enum工具不僅能夠建立符號常量,還能定義新

C/C++volatile關鍵字

asm 運行 多線程並發 這樣的 修改 由於 設定 其他 硬件 1. 為什麽用volatile? C/C++ 中的 volatile 關鍵字和 const 對應,用來修飾變量,通常用於建立語言級別的 memory barrier。這是 BS 在 "The C++ P

《隨筆十七》—— C++的 “ 指標

目錄 指標的概念 指標所指向的型別 指標的值 指標本身所佔據的記憶體區 指標的算術運算          運算子&和* 指標表示式 陣列和指標的關係 指標和結構型別的關係 指標和函式的關係

C++的string

標準庫型別string表示可變長的字元序列,為了在程式中使用string型別,我們必須包含標頭檔案: #include <string>  宣告一個字串 宣告一個字串有很多種方式,具體如下: 1 string s;//呼叫預設建構函式,s為一個空

C++string類(轉載)(最下面有程式碼實現)

作者:yzl_rex 來源:CSDN 原文:https://blog.csdn.net/yzl_rex/article/details/7839379 要想使用標準C++中string類,必須要包含 #include < string>// 注意是< string>

linuxfork() 函式

fork入門知識 一個程序,包括程式碼、資料和分配給程序的資源。fork()函式通過系統呼叫建立一個與原來程序幾乎完全相同的程序,也就是兩個程序可以做完全相同的事,但如果初始引數或者傳入的變數不同,兩個程序也可以做不同的事。 一個程序呼叫fork()函式後,系統先給新的程序分配資源,例如儲存資料和程式碼的

C++const關鍵字

const關鍵字作用    1. 修飾變數        用法:const 型別說明符 變數名。        含義:說明該變數不可以被改變。        用途:常量命名等    2. 修飾

MATLABaccumarray函式

  原文連結:https://blog.csdn.net/liuhuicsu/article/details/70739459?utm_source=blogxgwz0 先看看subs和val的具體內容 subs = [1 1 1; 2 1 2; 2 3 2; 2 1 2; 2

基於C++的circshift 函式

函式講解 circshift函式是matlab中表示迴圈移位的函式,呼叫形式如下:B= circshift(A,K,m); 輸入引數解釋如下: A表示待移位的向量或矩陣; K表示所移位數,可以是數字,也可以是二維陣列,若是數字則可以和m協同作用來決定是行移