2017-06-13 20 views
0

我的工作是從文件中讀取文本的程序,並解析文本文字和操縱它們,我就是那樣的使用的fscanf解析的話我怎麼能檢查時,我跳過線

的fscanf解析當
while (fscanf (fp, " %32[^ ,.\t\n]%*c", word) == 1) 

{ 
/*manipulate the text word by word 

} 

我想要寫相鄰的,我覺得字,其中線我發現她

有沒有辦法,我可以檢查,當我下移一行
使用功能的fscanf當的方法嗎?

+2

'fscanf'不區分行,實際上大多數格式說明符都忽略所有空格。嘗試使用'fgets'來讀取每行,然後使用字符串分割函數。 –

+0

...例如'strsep'或'strtok'及其派生詞,如果你想分析單詞。 –

+0

'fscanf(fp,「%32 [^,。\ t \ n]%* c」,單詞)'在不同的地方跳過''\ n'':領先''''也許''* c「' 。使用'fgets()'來讀取_line_。 – chux

回答

3

最穩健的建議是使用fgets()或許POSIX getline()讀線,然後考慮使用 sscanf()解析每一行。您可能需要考慮how to use sscanf() in a loop。還有許多其他選項可用於解析該行而不是sscanf(),例如strtok_r()或較不理想的strtok() - 或者在Windows上,strtok_s(); strspn(), strcspn(), strpbrk();和其他不規範的功能。

如果您認爲必須使用fscanf(),那麼您可能需要捕獲尾隨上下文。這方面的一個簡單的版本是:

char c; 
while (fscanf(fp, " %32[^ ,.\t\n]%c", word, &c) == 2) 
    … 

這抓住了單詞後,假設有一個。如果您的文件沒有以換行符結尾,則可能會丟失一個單詞。錯過換行也很容易。例如,如果行在換行符之前以句號結束(句號),則c將保存.,換行符將在下一次迭代循環中跳過。你可以克服用:

char s[33]; 
while (fscanf(fp, " %32[^ ,.\t\n]%32[ ,.\t\n]", word, s) == 2) 
    … 

注意格式字符串的長度必須大於變量聲明的長度少一個!

成功調用fscanf()後,字符串s可能包含多個換行符和空格等。 fscanf()函數大多不關心換行符,並且如果s的掃描集是數據文件中的內容,它將在一行中讀取多個換行符。

如果你明確地從fscanf()捕捉狀態,可以是,沒有一個換行符(或者一個標點符號)結尾的文件,或引起其他問題更加敏感:

char s[33]; 
int rc; 
while ((rc = fscanf(fp, " %32[^ ,.\t\n]%32[ ,.\t\n]", word, s)) != EOF) 
{ 
    switch (rc) 
    { 
    case 2: 
     …proceed as normal, checking s for newlines. 
     break; 
    case 1: 
     …probably an overlong word or EOF without a newline. 
     break; 
    case 0: 
     …probably means the next character is one of comma or dot. 
     …spaces, tabs, newlines will be skipped without detection 
     …by the leading space in the format string. 
     break; 
    default: 
     assert(0); 
     break; 
    } 
} 

如果你開始關心約!?;:'"字符 - 更不用說() - 生活變得更加複雜依然。事實上,在這一點上,sscanf()的替代品開始看起來好多了。

這是很難正確地使用scanf()家庭的功能。他們只是新手的工具,至少一旦你開始需要做任何複雜的事情。你可以看看A beginner's guide to not using scanf(),其中包含很多有價值的信息。我不完全相信最後幾個應該是防彈用途scanf()的例子。 (正確使用sscanf()會稍微簡單一些,但是您仍然需要了解詳細信息。)

1

fgets()然後讀線使用sscanf解析它們:

char buff[1024]; 
int lineno = 0; 
int offset = 0; 
while (fgets(buff, 1024, fp)) { 
    lineno++; 
    offset = 0; 
    while (sscanf(buff + offset, " %32[^ ,.\t\n]%*c", word) == 1) 
    { 
    /* manipulate the text word by word */ 

    } 
} 

在第二環路必須增加緩衝器,以便正確地解析線適當偏移。爲此,例如,您可以使用%n來獲取讀取字節。

+3

但請注意[在循環中使用'sscanf()'](http://stackoverflow.com/questions/3975236/how-to-use-sscanf-in-loops)。 –

+0

謝謝,我補充說。 @JonathanLeffler –