2014-04-25 30 views
0

我想了解sscanf行爲,因爲我已經執行了兩個程序。C sscanf行爲

void main() 
{ 
     char *a = "225.311"; 
     int x = 0, y = 0; 
     sscanf(a, "%d.3%d", &x, &y); 
     printf("x is %d, y is %d\n", x, y); 
} 

輸出

x is 255, y is 11 

下面程序工作不按我的期望。

void main() 
{ 
     char *a = "225.311"; 
     int x = 0, y = 0; 
     sscanf(a, "%d5.3%d", &x, &y); 
     printf("x is %d, y is %d\n", x, y); 
} 

我期待25,11,但輸出

x is 255, y is 0 

我期待sscanf行爲應該完全一樣在相反的方式sprintf的。但它沒有在我的第二個程序中工作。如果格式指定爲%d5.3%d,則必須將5視爲分隔符。但它不考慮和讀取x的所有數字,然後點與5.3%d不匹配,因此它在那裏退出。

有人可以解釋一下。

+1

總是檢查'[s] scanf'的返回值。如果它不等於你使用的佔位符的數量,那麼你會意識到發生了一些錯誤。 – Crozin

+0

閱讀'scanf'的文檔或手冊頁,不要假設...這個文本解析函數族具有很大的權力,但我會說權力比責任更重要,更不用說默認值了從用戶的角度來看可能是不直觀的。用標準的C'fgets'或者GNU/POSIX2008'getline'讀一行,然後用'sscanf'解析通常會更好。 – hyde

回答

4

這是因爲%d轉換說明符意味着sscanf將繼續讀取由a指向的緩衝區,直到它在緩衝區中遇到一個非數字字符。這意味着%d將在第二個示例中的字符串文字"225.311"中消耗至225

如果指定的格式是%d5.3%d,那麼它必須考慮5爲 分度。

不,這是不正確的。格式字符串中的5表示sscanf將在它讀取的緩衝區中完全匹配(在讀取int後)。如果它不匹配,則sscanf將返回並且值y保持不變。您可以通過存儲sscanf的結果來檢查。返回值等於成功匹配和分配的輸入項目的數量。

char *a = "225.311"; 
int x = 0, y = 0; 
int retval = sscanf(a, "%d5.3%d", &x, &y); 
printf("%d\n", retval); // prints 1 

但是,請注意,如果數字字符在緩衝區中的順序是太長爲int,則行爲是因爲有符號整數溢出的不確定。

1

建議使用不同的格式並檢查sscanf()的結果。還要區分「0.001」和「0.1」等分數,請注意位置。

const char *a = "225.0311"; 
int ipart = 0; 
unsigned fractionpart; 
int n1, n2; 
if (sscanf(a, "%d.%n%u%n", &ipart, &n1, &fractionpart, &n2) != 2) { 
    Handle_BadInput(); 
} 

printf("ipart is %d, fractionpart is %0*u\n", ipart, n2 - n1, fractionpart); 
// ipart is 225, fractionpart is 0311 

由於@ajay討論,"%d5.3%d"尋找一個int,然後"5.3"然後又int