• [轉載]C語言 格式化字符

    1
    C語言 Java IOS C/C++ Go 36305 次瀏覽

    前段時間用C寫了一個程式,發現3年前學的C的基本語法都忘得差不多了。下面的格式化字符,我覺得值得我寫個隨筆,免得下次再寫時,忘記了。

    格式字符控制:

    說明:sprintf(格式化后的字符,"%(長度)格式符",格式化前的字符);

    1、 d格式符。用來輸出十進制數。有以下幾種用法:

    (1)、%d按整數的實際長度輸出。

    (2)、%md,m為指定的輸出字段的寬度。如果數據位數小于m,則左端補以空格,若大于m,則按實際位數輸出。(3)、%ld,輸出長整型數據。例:long a=135790;printf(“%ld”,a);如果用%d輸出就會發生錯誤,因為整型數據的范圍是-32768到32767.對long型數據應當用%ld格式輸出,對長整型數據也可以指定字段寬度,如:%8ld。

    2、 o格式符,以八進制數形式輸出整數。由于內存單元中的各位的值(0或1)按八進制形式輸出,因此輸出的數值不帶符號,即將符號位也一起作為八進制的一部分輸出。

    3、 x格式符,以十六進制數形式輸出整數。同樣不會出現負的十六進制數。同樣可以用%lx輸出長整型數,也可以指定輸出字段寬度。

    4、 u格式符,用來輸出unsigned型數據,即無符號數,以十進制形式輸出。一個有符號整數(int型)也可以用%u格式輸出,反之,一個unsigned型的數據也可以用%d格式輸出。按相互賦值的規則處理。Unsigned型數據也可以用%x格式輸出。

    5、 c格式符,用來輸出一個字符。一個字符型數據也可以用整數形式輸出。

    6、 s格式符,用來輸出一個字符串。

    (1)、%s,printf(“%s”,“HELLO”);

    (2)、%ms輸出字符串占m列,如字符串本身大于m,則突破m的限制,字符串全部輸出,如果小于m,則左補空格。(3)、%-ms如果字符串小于m,則在m范圍內,字符串向左靠,右補空格。

    (4)、%m.ns,輸出占m列,但只取字符串中左端n個字符。這n個字符輸出在m列的右側,左補空格。

    (5)、%-m.ns,其中m,n含義同上,n個字符輸出在m范圍的左側,右補空格。如果n>m,則自動取n值,即保證n個字符正常輸出。

    7、 f格式符,用來輸出實數(包括單,雙精度),以小數形式輸出。

    (1)、%f,不指定字段寬度,有系統自動指定,使整數部分全部如數輸出,并輸出6位小數。應當注意,并非全部數字都是有效數字。單精度實數的有效位數一般是7位。

    (2)、%m.nf指定輸出的數據占m列,其中有n位小數。如果數值長度小于m,則左補空格。

    (3)、%-m.nf與%m.nf基本相同,只是輸出的數值向左端靠,右端補空格。

    8、 e格式符,以指數形式輸出。

    9、 g格式符,用來輸出實數,它根據數值的大小,自動選擇f格式或e格式(選擇輸出時占寬度較小的一種),且不輸出無意義的零。

     

     

    *********************************************************

    Code 格式
    %c 字符
    %d 帶符號整數
    %i 帶符號整數
    %e 科學計數法, 使用小寫"e"
    %E 科學計數法, 使用大寫"E"
    %f 浮點數
    %g 使用%e或%f中較短的一個
    %G 使用%E或%f中較短的一個
    %o 八進制
    %s 一串字符
    %u 無符號整數
    %x 無符號十六進制數, 用小寫字母
    %X 無符號十六進制數, 用大寫字母
    %p 一個指針
    %n 參數應該是一個指向一個整數的指針
    指向的是字符數放置的位置
    %% 一個'%'符號

    一個位于一個%和格式化命令間的整數擔當著一個最小字段寬度說明符,并且加上足夠多的空格或0使輸出足夠長. 如果你想填充0,在最小字段寬度說明符前放置0. 你可以使用一個精度修飾符,它可以根據使用的格式代碼而有不同的含義.

    • 用%e, %E和 %f,精度修飾符讓你指定想要的小數位數. 例如,

       

          %12.6f

      將會至少顯示12位數字,并帶有6位小數的浮點數.

    • 用%g和 %G, 精度修飾符決定顯示的有效數的位數最大值.
    • 用%s,精度修飾符簡單的表示一個最大的最大長度, 以補充句點前的最小字段長度.

    所有的printf()的輸出都是右對齊的,除非你在%符號后放置了負號. 例如,

     

        %-12.4f

    將會顯示12位字符,4位小數位的浮點數并且左對齊. 你可以修改帶字母lh%d, %i, %o, %u和 %x 等類型說明符指定長型和短型數據類型 (例如 %hd 表示一個短整數). %e, %f和 %g 類型說明符,可以在它們前面放置l指出跟隨的是一個double. %g, %f和 %e 類型說明符可以置于字符'#'前保證出現小數點, 即使沒有小數位. 帶%x類型說明符的'#'字符的使用, 表示顯示十六進制數時應該帶'0x'前綴. 帶%o類型說明符的'#'字符的使用, 表示顯示八進制數時應該帶一個'0'前綴.

     

    ****************************格式化符在sscanf函數中的強大用法*****************************

    1. 常見用法。

      char buf[512] ;

      sscanf("123456 ", "%s", buf);//此處buf是數組名,它的意思是將123456以%s的形式存入buf中!

      printf("%s\n", buf);

      結果為:123456

      2. 取指定長度的字符串。如在下例中,取最大長度為4字節的字符串。

      sscanf("123456 ", "%4s", buf);

      printf("%s\n", buf);

      結果為:1234

      3. 取到指定字符為止的字符串。如在下例中,取遇到空格為止字符串。

      sscanf("123456 abcdedf", "%[^ ]", buf);

      printf("%s\n", buf);

      結果為:123456

      4. 取僅包含指定字符集的字符串。如在下例中,取僅包含1到9和小寫字母的字符串。

      sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);

      printf("%s\n", buf);

      結果為:123456abcdedf

      當輸入:

      sscanf("123456abcdedfBCDEF","%[1-9A-Z]",buf);

      printf("%s\n",buf);

      結果為:123456

      5. 取到指定字符集為止的字符串。如在下例中,取遇到大寫字母為止的字符串。

      sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);

      printf("%s\n", buf);

      結果為:123456abcdedf

      6、給定一個字符串iios/12DDWDFF@122,獲取 / 和 @ 之間的字符串,先將 "iios/"過濾掉,再將非'@'的一串內容送到buf中

      sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);

      printf("%s\n", buf);

      結果為:12DDWDFF

      7、給定一個字符串“hello, world”,僅保留world。(注意:“,”之后有一空格,%s遇空格停止,加*則是忽略第一個讀到的字符串)

      sscanf(“hello, world”, "%*s%s", buf);

      printf("%s\n", buf);

      結果為:world

      %*s表示第一個匹配到的%s被過濾掉,即hello被過濾了

      如果沒有空格則結果為NULL。

      sscanf的功能很類似于正則表達式, 但卻沒有正則表達式強大,所以如果對于比較復雜的字符串處理,建議使用正則表達式.

      //-------------------------------------------------------

      用它來分隔類似這樣的字符串2006:03:18:

      int a, b, c;

      /*sscanf("2006:03:18", "%d:%d:%d", a, b, c); */ /*錯誤方法, 要在變量a,b,c前加上取地址符, modified by huanmie_09*/

      sscanf("2006:03:18", "%d:%d:%d", &a, &b, &c);

      以及2006:03:18 - 2006:04:18:

      char sztime1[16] = "", sztime2[16] = "";

      sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);

      但是后來,我需要處理2006:03:18-2006:04:18

      僅僅是取消了‘-’兩邊的空格,卻打破了%s對字符串的界定。

      我需要重新設計一個函數來處理這樣的情況?這并不復雜,但是,為了使所有的代碼都有統一的風格,我需要改動很多地方,把已有的sscanf替換成我自己的分割函數。我以為我肯定需要這樣做,并伴隨著對sscanf的強烈不滿而入睡;一覺醒來,發現其實不必。

      format-type中有%[]這樣的type field。如果讀取的字符串,不是以空格來分隔的話,就可以使用%[]。

      %[]類似于一個正則表達式。[a-z]表示讀取a-z的所有字符,[^a-z]表示讀取除a-z以外的所有字符。

      所以那個問題也就迎刃而解了:

      sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2);

      在softmse (Jake) 的問題貼http://community.csd(去掉我)n.n(去掉我)et/Expert/topic/4843/4843294.xml?temp=.4321558中 ,給出了一個很cool的sscanf用例,而后通過學習,發現sscanf真棒,現做一總結。

     

     

    搜集一些特殊用法:

     

    %[ ] 的用法:%[ ]表示要讀入一個字符集合, 如果[ 后面第一個字符是”^”,則表示反意思。

                         [ ]內的字符串可以是1或更多字符組成。空字符集(%[])是違反規定的,可

                         導致不可預知的結果。%[^]也是違反規定的。
             

    %[a-z] 讀取在 a-z 之間的字符串,如果不在此之前則停止,如

                  char s[]="hello, my friend” ; // 注意: ,逗號在不 a-z之間

                  sscanf( s, “%[a-z]”, string ) ; // string=hello


    %[^a-z] 讀取不在 a-z 之間的字符串,如果碰到a-z之間的字符則停止,如

                  char s[]="HELLOkitty” ; // 注意: ,逗號在不 a-z之間


                  sscanf( s, “%[^a-z]”, string ) ; // string=HELLO

     

    %*[^=] 前面帶 * 號表示不保存變量。跳過符合條件的字符串。

                  char s[]="notepad=1.0.0.1001" ;

           char szfilename [32] = "" ;

           int i = sscanf( s, "%*[^=]", szfilename ) ;

    // szfilename=NULL,因為沒保存


    int i = sscanf( s, "%*[^=]=%s", szfilename ) ;

    // szfilename=1.0.0.1001


    %40c 讀取40個字符


    %[^=] 讀取字符串直到碰到’=’號,’^’后面可以帶更多字符,如:

                  char s[]="notepad=1.0.0.1001" ;

                  char szfilename [32] = "" ;

                 int i = sscanf( s, "%[^=]", szfilename ) ;

               // szfilename=notepad


           如果參數格式是:%[^=:] ,那么也可以從 notepad:1.0.0.1001讀取notepad

     

     

     

    注意:當碰到不滿足條件的字符后,sscanf就會停止執行,不再掃描之后的字符。

     

    ********************strtok字符串分割函數也是個實戰性較強的函數,但是已被strsep函數取代***********************


     

     #include <string.h>
     char *strtok( char *str1, const char *str2 );

    功能:函數返回字符串str1中緊接“標記”的部分的指針, 字符串str2是作為標記的分隔符。如果分隔標記沒有找到,函數返回NULL。為了將字符串轉換成標記,第一次調用str1 指向作為標記的分隔符。之后所以的調用str1 都應為NULL。

    例如:

        char str[] = "now # is the time for all # good men to come to the # aid of their country";
        char delims[] = "#";
        char *result = NULL;
     
        result = strtok( str, delims );
     
        while( result != NULL ) {
            printf( "result is \"%s\"\n", result );
             result = strtok( NULL, delims );
        }

    以上代碼的運行結果是:

        result is "now "
        result is " is the time for all "
        result is " good men to come to the "
        result is " aid of their country"

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

    char* strname=NULL;
        strname=(char*)malloc(sizeof(char));
     memset(strname,0,sizeof(char));
     strcpy(strname,"tong|sun|java|google");
     
        char delims[] = "|";
        char* ret=NULL;
        ret=(char*)malloc(sizeof(char));
     memset(ret,0,sizeof(char));
     ret=strtok(strname,delims);
     while(ret!=NULL)
     {
      printf("%s\n",ret);
       ret=(char*)malloc(sizeof(char));
      memset(ret,0,sizeof(char));
      ret=strtok(NULL,delims); 
     }

     

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

     

      strsep

    baikeViewInfo={id:"2466295",editable:"true",title:"strsep",expIndex:"0"};

      原型:char *strsep(char **stringp, const char *delim);
      功能:分解字符串為一組字符串。從stringp指向的位置起向后掃描,遇到delim指向位置的字符后,將此字符替換為NULL,返回stringp指向的地址。

     

     *********************strncat字符串截取拼接*********************************

     

    strncat

    baikeViewInfo={id:"1028544",editable:"true",title:"strncat",expIndex:"0"};

      原型:extern char *strncat(char *dest,char *src,int n);
      用法:#include <string.h>
      功能:把src所指字符串的前n個字符添加到dest結尾處(覆蓋dest結尾處的'\0')并添加'\0'。
      說明:src和dest所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字符串。
      返回指向dest的指針。
      舉例:
      // strncat.c
      #include <syslib.h>
      #include <string.h>
      main()
      {
      char d[20]="Golden Global";
      char *s=" View WinIDE Library";
      clrscr();
      strncat(d,s,5);
      printf("%s",d);
      getchar();
      return 0;
      }

     

    以上代碼的運行結果是:

    Golden Global View  注意view前面有個空格字符。

     

    ***********************strncasecmp***************************

     

    strncasecmp

    baikeViewInfo={id:"1589829",editable:"true",title:"strncasecmp",expIndex:"0"};

      相關函數:bcmp, memcmp, strcmp, strcoll, strncmp
      表頭文件:#include <string.h>
      函數定義:int strncasecmp(const char *s1, const char *s2, size_t n)
      函數說明:strncasecmp()用來比較參數s1和s2字符串前n個字符,比較時會自動忽略大小寫的差異
      返回值 :若參數s1和s2字符串相同則返回0 s1若大于s2則返回大于0的值 s1若小于s2則返回小于0的值
      #include <string.h>

      char *a="acddfefekr";
      char *b="AbCddfefekr";
      printf("%d\n",strncasecmp(a,b,2));

      以上代碼的運行結果是:1

    ******************************strcasecmp*************************

     

    strcasecmp

    (忽略大小寫比較字符串)

      相關函數 bcmp,memcmp,strcmp,strcoll,strncmp

      表頭文件 #include<string.h>

      定義函數 int strcasecmp (const char *s1, const char *s2);

      函數說明 strcasecmp()用來比較參數s1和s2字符串,比較時會自動忽略大小寫的差異。

      此原文這里有錯誤:返回值 若參數s1和s2字符串相同則返回0。s1長度大于s2長度則返回大于0 的值,s1 長度若小于s2 長度則返回小于0的值。

      strcasecmp是比較兩個字符串,但比較的不是它們的長度,而是字符的編碼大小——但字母不區分大小寫,如果S1小于S2,返回小于0的一個整數;如果S1等于S2,返回值是0;如果S1>S2,返回一個大于0的整數。

      #include <string.h>

      main()

      {

        char *a="aBcddfefekr";
       char *b="AbCddfefekr";
       printf("%d\n",strcasecmp(a,b));

      }

     

      執行 aBcDeF=AbCdEf

      以上代碼的運行結果是:0

      注意與strncasecmp()的區別,不要弄混了。

      該函數是二進制安全的,且對大小寫不敏感。

    *************************strncpy*******************************

      strncpy:字串復制  原型:char * strncpy(char *dest, char *src, size_t n);

      功能:將字符串src中最多n個字符復制到字符數組dest中(它并不像strcpy一樣遇到NULL才停止復制,而是等湊夠n個字符才開始復制),返回指向dest的指針。

      說明:

      如果n > dest串長度,dest棧空間溢出產生崩潰異常。

      否則:

      1)src串長度<=dest串長度,(這里的串長度包含串尾NULL字符)

      如果n=(0, src串長度),src的前n個字符復制到dest中。但是由于沒有NULL字符,所以直接訪問dest串會發生棧溢出的異常情況。

      如果n = src串長度,與strcpy一致。

      如果n = dest串長度,[0,src串長度]處存放于desk字串,(src串長度, dest串長度]處存放NULL。

      2)src串長度>dest串長度

      如果n =dest串長度,則dest串沒有NULL字符,會導致輸出會有亂碼。如果不考慮src串復制完整性,可以將dest最后一字符置為NULL。

      綜上,一般情況下,使用strncpy時,建議將n置為dest串長度(除非你將多個src串都復制到dest數組,并且從dest尾部反向操作),復制完畢后,為保險起見, 將dest串最后一字符置NULL,避免發生在第2)種情況下的輸出亂碼問題。當然嘍,無論是strcpy還是strncpy,保證src串長度<dest串長度才是最重要的。

     

    *******************************snprintf*******************************

     

    snprintf

    baikeViewInfo={id:"1966670",editable:"true",title:"snprintf",expIndex:"0"};

      int snprintf(char *str, size_t size, const char *format, ...);
      將可變個參數(...)按照format格式化成字符串,然后將其復制到str中
      (1) 如果格式化后的字符串長度 < size,則將此字符串全部復制到str中,并給其后添加一個字符串結束符('\0');
      (2) 如果格式化后的字符串長度 >= size,則只將其中的(size-1)個字符復制到str中,并給其后添加一個字符串結束符('\0')
      函數返回值:若成功則返回欲寫入的字符串長度,若出錯則返回負值。 --------------------------------------------

        int snprintf(char *restrict buf, size_t n, const char * restrict  format, ...);

      函數說明:最多從源串中拷貝n-1個字符到目標串中,然后再在后面加一個0。所以如果目標串的大小為n

          的話,將不會溢出。

      函數返回值:若成功則返回欲寫入的字符串長度,若出錯則返回負值。

      Result1(推薦的用法)

      #include <stdio.h>

      #include <stdlib.h>

      int main()

      {

           char str[10]={0,};

           snprintf(str, sizeof(str), "0123456789012345678");

           printf("str=%s\n", str);

           return 0;

      }

     
     
      #include <stdio.h> //snprintf()
      #include <string.h> //strlen()
      int main()
      {
      char toname[30];
      char *name = "yangtaiping";
      printf("strlen(name) = %d\n", strlen(name));
      snprintf(toname, sizeof(toname), "姓名:%s", name);
      printf("toname = %s\n", toname);
      printf("strlen(name) = %d\n", strlen(name));
      }
      strcpy() sprintf() strcat() 存在安全隱患, 其對應的安全版為:strncpy() snprintf() strncat() 。 
      snprintf(s, 100, "%.*S", 3, "abcd");s的值為abc %.*s 表示有兩項, 第一項指定了長度,第二項則是%s的內容,所以取前三位 詞條圖冊更多圖冊
      類似的函數還有:
      #include <stdio.h>
      int printf(const char *format, ...); //格式化輸出到標準輸出設備
      int fprintf(FILE *stream,const char *format, ...); //格式化輸出到文件流
      int sprintf(char *str,const char *format, ...); //格式化的輸出字符串輸出到str指向的地址空間

     

    **************************************************************

      實戰常用函數:

      printf scanf sscanf strcat strncat fprint fwrite fread fopen fclose

      sprintf snprintf strcmp strncmp strstr strchr strlen strcasecmp strncasecmp

      memcpy strcpy strncpy

    相似問題

    相關經驗

    相關資訊

    相關文檔

  • sesese色