2013-07-10 73 views
0

我有一個sscanf函數的問題。爲了更具體的我想讀一個txt文件中的浮動(我只想要一個浮子線),但sscanf不承認這些情況:sscanf和正確的格式文件

3.4t 

4.t6 

4.5 6.5 

(this is an empty line) 

我用這個代碼:

#define LUNRIGA 200  

char riga[LUNRIGA+1]; 

while (fgets(riga,LUNRIGA,f) != NULL) { 
     r = sscanf(riga,"%f",&numeri[i]); 
     if (r == 1) { /* riga valida */ 
     printf("OK"); 
     }else{ 
     printf("Error"); 
     return 1; 
     }  
} 
+2

你的意思是'fprintf'或'sscanf'? – Barmar

+0

對不起,您是對的。我要修改我的問題。問題出在sscanf – user2467899

+0

你想用4.t6做什麼? –

回答

1

sscanf是出了名的挑剔輸入。使用strtodstrtol可以獲得更好的運氣 - 即使後面跟着垃圾,他們也可以讀取值。更改您的代碼如下:

​​3210

說明,你似乎沒有在循環遞增i的方式 - 你可能想看看這其實你想要什麼,或者如果你想增加它每次你得到一個有效的數字(假設你不只是想要最後一個值,但它們都是......)

作爲strtod行爲的一個小演示,我寫了幾行代碼:

#include <stdio.h> 
#include <stdlib.h> 
int main(void) { 
    char* s1="123.45t"; 
    char* p1; 
    char* s2 = " notanumber"; 
    double d1, d2; 
    d1 = strtod(s1, &p1); 
    printf("the number is %.2lf; the pointer is now %p; string is at %p\n", d1, s1, p1); 
    d2 = strtod(s2, &p1); 
    printf("the number is %.2lf; the pointer is now %p; string is at %p\n", d2, s2, p1); 
} 

這個的輸出是:

The number is 123.45; the pointer is now 0x400668; string is at 0x40066e 
The number is 0.00; the pointer is now 0x400670; string is at 0x400670 

正如您所看到的,當讀取垃圾時,指針返回指向字符串開頭的位置 - 指示「失敗」。如果成功的話,指針指向「在那裏我不讀」,這是「後成功轉換的位串的一倍。

+0

謝謝,但我打算使用浮點數。不是雙重或INT數 – user2467899

+1

然後你可以使用'strtof' –

+0

@ user2467899或'關於strtod()'。真的,不要使用'scanf()'。這是邪惡的。提到的其他替代方案提供了更好的解決方案。 (並且你知道,'double'可以隱式轉換爲'float'。) – 2013-07-10 17:12:57

0

如果你想確保有線路上無垃圾,你可以使用在%n指令找出轉換停止,並決定該怎麼做之後會發生什麼就行了:

char riga[LUNRIGA]; 
float numeri[NUM_VALUES]; 
int offset; 
int i; 

for (i = 0; i < NUM_VALUES && fgets(riga, sizeof(riga), f) != NULL; i++) 
{ 
    int r = sscanf(riga, "%f%n", &numeri[i], &offset); 
    if (r == 1 && riga[offset] == '\n') 
     printf("OK (got %f from <<%s>>\n", numeri[i], riga); 
    else 
    { 
     printf("Error processing <<%s>>\n", riga); 
     return 1; 
    }  
} 

您可以sscanf()之前做一些額外的處理,例如檢查你讀一個換行符(這樣沒有一個超長線的殘留物仍然被讀取),並刪除換行符(但你需要改變的條件)。

請注意sizeof(riga)的使用,以及通過在代碼上施加for循環而不溢出numeri的檢查,並且打印每條消息結尾處出現換行符。

+1

'我'沒有在OP循環中增加,所以沒有溢出的風險......只是覆蓋。 – Floris

+0

噢 - 是的,我忘記了我已經注意到並修復了這個錯誤!我傾向於認爲這是最小化過程中的疏忽,但我可能太慈善了。 –

+0

慈善是一種美德。無論哪種方式,您的代碼都是對原始代碼的改進。儘管你的方法讓它「幾乎可口」,但我對這種任務越來越不喜歡'sscanf'。除非文件的最後一行沒有換行符... – Floris