RTSP協議的一些分析(二)——printf類似函數、sscanf以及log保存到內存中(printf輸入重定位)

PTSP協議介紹

RTSP協議的一些分析(一)——部分字符串函數的使用

RTSP協議的一些分析(二)——printf類似函數、sscanf以及log保存到內存中(printf輸入重定位)

1、printf函數

       #include <stdio.h>
       int printf(const char *format, ...);
       int fprintf(FILE *stream, const char *format, ...);
       int sprintf(char *str, const char *format, ...);
       int snprintf(char *str, size_t size, const char *format, ...);

       #include <stdarg.h>
       int vprintf(const char *format, va_list ap);
       int vfprintf(FILE *stream, const char *format, va_list ap);
       int vsprintf(char *str, const char *format, va_list ap);
       int vsnprintf(char *str, size_t size, const char *format, va_list ap);
#include <stdio.h>
#include <string.h>
 
//data and place them in the string named buffer.
// 程序使用sprintf 將各種數據格式化後置於字符數組buffer中
#include <stdio.h>
int main( void )
{
	char  buffer[200], s[] = "computer", c = 'l';
	int   i = 35, j;
	float fp = 1.7320534f;
	// 格式化並打印各種數據到buffer
	j  = sprintf( buffer,"   String:    %s\n", s ); // C4996
	j += sprintf( buffer + j, "   Character: %c\n", c ); // C4996
	j += sprintf( buffer + j, "   Integer:   %d\n", i ); // C4996
	j += sprintf( buffer + j, "   Real:      %f\n", fp );// C4996

	printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
	  return 0;
}

2、printf重定位

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

int myPrintf(const char *fmt,...)
{
	int i;
	char str_tmp[100];
	va_list args;
	/* void va_start(va_list ap, last) */
	va_start(args,fmt);
	/* 
	*  int vprintf(const char *format, va_list ap);
    *  int vfprintf(FILE *stream, const char *format, va_list ap);
    *  int vsprintf(char *str, const char *format, va_list ap);
    *  int vsnprintf(char *str, size_t size, const char *format, va_list ap);
    */
	i=vsnprintf(str_tmp,100,fmt,args); 
	/* void va_end(va_list ap) */
	va_end(args);

	/* 可以打印,或者保存到緩衝區中 */
	printf("i = %d, %s",i,str_tmp);
}
int main(int argc,char **agrv)
{
	int i = 5,j = 6;
	char *str = "123456";
	myPrintf("[yangguoyu]: i = %d,j= %d,str = %s\n",i,j,str);
	return 0;
}

    1)va_list:一個字符指針,可以理解爲指向當前參數的一個指針,取參必須通過這個指針進行。
    2)va_start:對ap進行初始化,讓ap指向可變參數表裏面的第一個參數。第一個參數是 ap 本身,第二個參數是在變參表前面緊挨着的一個變量,即“...”之前的那個參數;
    3)va_arg: 獲取參數。它的第一個參數是ap,第二個參數是要獲取的參數的指定類型。按照指定類型獲取當前參數,返回這個指定類型的值,然後把 ap 的位置指向變參表中下一個變量的位置;
    4)va_end:釋放指針,將輸入的參數 ap 置爲 NULL。通常va_start和va_end是成對出現。 

int vsnprintf (char * s, size_t n, const char * format, va_list arg )

描述:   
     將格式化數據從可變參數列表寫入大小緩衝區,如果在printf上使用格式,則使用相同的文本組成字符串,但使用由arg標識的變量參數列表中的元素而不是附加的函數參數,並將結果內容作爲C字符串存儲在s指向的緩衝區中 (以n爲最大緩衝區容量來填充)。如果結果字符串的長度超過了n-1個字符,則剩餘的字符將被丟棄並且不被存儲,而是被計算爲函數返回的值。在內部,函數從arg標識的列表中檢索參數,就好像va_arg被使用了一樣,因此arg的狀態很可能被調用所改變。在任何情況下,arg都應該在調用之前的某個時刻由va_start初始化,並且在調用之後的某個時刻,預計會由va_end釋放。
參數:
    s:指向存儲結果C字符串的緩衝區的指針。緩衝區應至少有n個字符的大小。
    n:在緩衝區中使用的最大字節數。生成的字符串的長度至多爲n-1,爲額外的終止空字符留下空間。size_t是一個無符號整數類型。
    format:包含格式字符串的C字符串,其格式字符串與printf中的格式相同。
    arg:標識使用va_start初始化的變量參數列表的值。va_list是在<cstdarg>中定義的特殊類型。

返回值:
如果n足夠大,則會寫入的字符數,不包括終止空字符。
如果發生編碼錯誤,則返回負數。
注意,只有當這個返回值是非負值且小於n時,字符串才被完全寫入。

3. sscanf

int sscanf(const char *str, const char *format, ...);

作用: 從一個字符串中讀進與指定格式相符的數據.  
參數:buffer 存儲的數據 
     format 格式控制字符串 
返回值:成功則返回參數數目,失敗則返回0,錯誤原因存於errno中。 

說明:
  sscanf與scanf類似,都是用於輸入的,只是後者以鍵盤(stdin)爲輸入源,前者以固定字符串爲輸入源。   
 第一個參數可以是一個或多個 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符號} 
 注: 
  1、 * 亦可用於格式中, (即 %*d 和 %*s) 加了星號 (*) 表示跳過此數據不讀入. (也就是不把此數據讀入參數中) 
  2、{a|b|c}表示a,b,c中選一,[d],表示可以有d也可以沒有d。 
  3、width表示讀取寬度。 
  4、{h | l | I64 | L}:參數的size,通常h表示單字節size,I表示2字節 size,L表示4字節size(double例外),l64表示8字節size。 
  5、type :這就很多了,就是%s,%d之類。 
  6、特別的:%*[width] [{h | l | I64 | L}]type 表示滿足該條件的被過濾掉,不會向目標參數中寫入值 
  失敗返回0 ,否則返回格式化的參數個數 

支持集合操作:
  %[a-z] 表示匹配a到z中任意字符,貪婪性(儘可能多的匹配)  
  %[aB'] 匹配a、B、'中一員,貪婪性 
  %[^a] 匹配非a的任意字符,並且停止讀入,貪婪性 。

#include <stdio.h>
#include <string.h>
int main(int argc,char **argv[])
{
	char buf[512]; 

	/* 1.常用用法 */
	sscanf("123456 ","%s",buf);/*此處buf是數組名,它的意思是將123456以%s的形式存入buf中!*/
	printf("1,-%s-\n",buf); 

	/* 2.取指定長度的字符串。如在下例中,取最大長度爲4字節的字符串。*/
	sscanf("123456 ", "%4s", buf);
	printf("2,-%s-\n",buf); 

	/* 3. 取到指定字符爲止的字符串。如在下例中,取遇到空格爲止字符串。 */
	sscanf("123456 abcdedf", "%[^ ]", buf);
	printf("3,-%s-\n",buf);

	/* 4. 取僅包含指定字符集的字符串。如在下例中,取僅包含1到9和小寫字母的字符串。  */
	sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
	printf("4,-%s-\n",buf);

	/* 5. 取到指定字符集爲止的字符串。如在下例中,取遇到大寫字母爲止的字符串*/
	sscanf("123456abcdedfBCDEF","%[^A-Z]", buf);
	printf("5,-%s-\n",buf);

	/* 6. 給定一個字符串iios/12DDWDFF@122,獲取/和 @ 之間的字符串,先將 "iios/"過濾掉,再將非'@'的一串內容送到buf中 */
	sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); 
	printf("6,-%s-\n",buf);

	/* 7. 給定一個字符串"hello, world",僅保留world。(注意:","之後有一空格,%s遇空格停止,加*則是忽略第一個讀到的字符串)  */
	sscanf("hello, world", "%*s%s", buf); 
	printf("7,-%s-\n",buf);	
	return 0;
}

運行結果:
1,-123456-
2,-1234-
3,-123456-
4,-123456abcdedf-
5,-123456abcdedf-
6,-12DDWDFF-
7,-world-

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章