天天看點

C|簡單了解sprintf和sscanf

作者:小智雅彙

sprintf()和sscanf()聲明在stdio.h中,屬于輸入輸出一類操作。

先從了解printf()和scanf()開始。

printf()和scanf()也是聲明在stdio.h中,屬于輸入輸出一類操作,表示與控制台(console)的标準輸入輸出。

我們知道,對于輸入輸出而言,直接操作的都是屬于文本一類的資料,但我們輸入輸出涉及到的資料類型卻不隻是文本,還有數值型資料,如整型,浮點型點。

由此,涉及到類型轉換,C的做法是使用一個“格式化字元串”做參數,這個字元串内可以包含“資料類型轉換符”。這類函數稱為格式化輸入輸出函數,如printf()、scanf(),其中的字母f表示“format”,第一個參數為一個“格式化字元串”,其中的“資料類型轉換符”由符号“%”引導(其中可以選擇性地包含寬度、精度等)。函數通過分析這一個字元串來确定參數清單對應的資料類型。

int printf( const char *format, ... ); // format是格式化字元串,...表示參數清單
int scanf( const char *format, ... ); // format是格式化字元串,...表示參數清單
%說明符(specifier)對應資料類型
描述
%d / %i int
輸出類型為有符号的十進制整數,i 是老式寫法
%o unsigned int
輸出類型為無符号八進制整數(沒有前導 0)
%u unsigned int
輸出類型為無符号十進制整數
%x / %X unsigned int
輸出類型為無符号十六進制整數,x 對應的是 abcdef,X 對應的是 ABCDEF(沒有前導 0x 或者 0X)
%f / %lf double
輸出類型為十進制表示的浮點數,預設精度為6(lf 在 C99 開始加入标準,意思和 f 相同)
%e / %E double
輸出類型為科學計數法表示的數,此處 "e" 的大小寫代表在輸出時用的 “e” 的大小寫,預設浮點數精度為6
%g double
根據數值不同自動選擇 %f 或 %e,%e 格式在指數小于-4或指數大于等于精度時用使用 
%G double
根據數值不同自動選擇 %f 或 %E,%E 格式在指數小于-4或指數大于等于精度時用使用
%c char
輸出類型為字元型。可以把輸入的數字按照ASCII碼相應轉換為對應的字元
%s char *
輸出類型為字元串。輸出字元串中的字元直至遇到字元串中的空字元(字元串以 '\0‘ 結尾,這個 '\0' 即空字元)或者已列印了由精度指定的字元數
%p void *
以16進制形式輸出指針
%% 不轉換參數
不進行轉換,輸出字元‘%’(百分号)本身           

(隻有字元或文本的輸入可以使用getchar()、putchar()、gets()、puts()等函數。)

printf()和scanf()也是标準輸入輸出函數,其中的标準是指資料的輸入輸出的目标裝置或來源裝置,也就是标準輸入輸出裝置stdin、stdout。

輸入輸出資料的目标或來源可不可以是存儲在記憶體中的字元串變量,答案是可以,其對應的函數也就是sprintf()和sscanf(),其第一個字元s,即表示string,其第一個參數也是一個字元串,表示資料的目标或來源,第2個參數,如同printf()和scanf(),是一個“”格式化字元串。

int sprintf(char *string, const char *format [,argument,...]);//根據參數清單将format解析為string
int sscanf(const char *buffer,const char *format, [ argument ] ...);//根據format将buffer解析到參數清單。           

sprintf()除了用于字元串輸出以外,其實也可以用作字元格格式化。

對于scanf(),當發生輸入的類型不比對或溢出時,可能會發現不可預料的結果。建議的做法是使用gets()輸入到一個字元串,然後使用sscanf()對這個字元串解析出目标類型的值:

#include <stdio.h>
void main (void)
{
    char input[256], name[256];
    int age;
    printf ("What is your name, user?\n");
    fgets (input, 256, stdin);
    sscanf (input, "%s", name);
    printf ("Hello, %s. How old are you?\n", name);
    while(1)
    {
        fgets (input, 256, stdin);
        if(sscanf (input, "%d", &age) == 1) break;
        printf ("I don't recognise that as an age - try again!\n");
    }
    printf ("Well, %s, you look young for %d...\n", name, age);
}           

printf函數的目标裝置是标準輸出裝置(抽象為stdout檔案),sprintf函數的目标對象是記憶體中的字元串變量,還有以檔案(FILE結構體描述)為輸出目标的函數,稱為fprintf函數:

#include <stdio.h>
void main (void)
{
    FILE *fp;
    fp = fopen ("/home/pi/output.txt", "wb");
    if(fp)
    {
        fprintf (fp, "This is some text.\n");
        fclose (fp);
    }
}           

相關内容參考:

Sprintf function can writes arbitrary text to string variables. The only difference with printf function is that the first argument it takes is the name of a string variable, and it writes to that instead of to the terminal.

Sprintf函數可以将任意文本寫入字元串變量。與printf函數的唯一差別是,它采用的第一個參數是字元串變量的名稱,并且它寫入字元串變量而不是終端。

(可以了解printf()有一個省略的stdout參數,因為是标準輸出,被省略。)

The sprintf function will automatically add the terminating zero at the end of any string you create with it.

sprintf函數将自動在使用它建立的任何字元串的末尾添加終止零。

We can use sprintf to write variables into a string; what about being able to read variables back out of a string? The function sscanf (‘string scan formatted’) does that for you.

我們可以使用sprintf将變量寫入字元串;從字元串中讀取變量呢?函數sscanf(“字元串掃描格式”)為您實作了這一點。

sscanf uses exactly the same format specifiers as printf. One important difference, though, is that the arguments to sscanf must all be pointers to variables, rather than variables themselves. As always, a function can never change the values of variables provided as arguments, but it can write to their destinations if they are pointers.

sscanf使用與printf完全相同的格式說明符。然而,一個重要的差別是,sscanf的參數必須都是指向變量的指針,而不是變量本身。與往常一樣,函數永遠不能更改作為參數提供的變量的值,但如果變量是指針,則可以寫入它們的目标。

sscanf reads numeric values and words out of a formatted string, allowing you to parse text from elsewhere. Remember that all the arguments to sscanf must be pointers.

sscanf從格式化字元串中讀取數值和單詞,允許您從其他地方解析文本。記住,sscanf的所有參數都必須是指針。

-End-

繼續閱讀