2012-10-10 70 views
2

我有以下格式的多TSV文件:力FSCANF消耗可能的空白

Type\tBasic Name\tAttribute\tA Long Description\n 

正如你所看到的,基本的名稱和描述可以同時包含空格一些數字。我正在嘗試讀取每行並提取元素。現在,我已經縮小到只提取基本名稱。我的fscanf如下:

fscanf(file_in, "%*[^ ]s\t%128[^ ]s\t%*[^ ]s\t%[^ ]s\n", name_string, desc_string); 

這並不像我希望的那樣工作,而且我無法縮小錯誤範圍。有誰知道我該如何正確閱讀這些文字?

回答

3

我大多數人都同意巴勃羅(即scanf家族並不擅長解析器),但是值得了解如何編寫scanf模式。您正在尋找的模式是這樣的:

fscanf(" %*[^\t] %128[^\t] %*[^\t] %128[^\n]", name_string, desc_string) 

注:

  1. %[xyz]是一個指令。 %[xyz]s是兩個指令,其中第二個據一個我知道相匹配的文字s

  2. ,沒有辦法匹配單個字面製表符,因爲在形成圖案的任何空白匹配空白的任何量(包括沒有)在輸入中。我在我的例子中使用了一個空格,它將匹配一個終止標籤,但它也會匹配任意數量的連續標籤,因此空字段不會被正確解析。

  3. 128個字符的限制不包括終止NUL字符。

  4. 此外,如果由於字符限制超出而停止掃描,它將不會自動跳過字段的其餘部分,因此最終會與輸入不同步。

一個更好的模式是:

fscanf(" %*[^\t] %128[^\t]%*[^\t] %*[^\t] %128[^\n]%*[^\n]", name_string, desc_string) 

其中明確跳過在該領域中剩餘的字符,如果需要的話。更好的解決方案是使用a修改器,併爲您獲取fscanfmalloc內存。

+0

啊,我明白了。我對使用[]有點困惑,但這是有道理的。雖然,我不確定在%128 [^ \ t]上看到使用%128 [^ \ t]%* [^ \ t]來讀取數據的好處。 – Tanaki

+1

@Tanaki因爲如果限制爲128個字符,它將在128個字符後停止掃描,並且字段中的其餘字符將與下一個指令相匹配,該指令應與下一個字段匹配。 – rici

+0

你是救命的人,我忘記了潛在的溢出! – Tanaki

0

首先,如前所述,%[]本身就是一個轉換說明符。 []之後沒有s。您在格式字符串中使用的s不會被視爲轉換說明符的一部分。你必須擺脫這些s -es。其次,如你所說,你的文件是TAB分隔的。這意味着您應該使用%[^\t]轉換說明符(或最後一部分的%[^\n]說明符)來提取序列的連續部分。你爲什麼使用%[^ ],你是如何看待它的? %[^ ]實際上停止在空格字符解析,這是你想要的相反。

在您的例子說明符的適當組合將是

fscanf(file_in, "%*[^\t]\t%128[^\t]\t%*[^\t]\t%[^\n]\n", name_string, desc_string); 

此格式字符串假定字符串的所有4個部分被保證是存在,以及最後部分是保證由\n被終止。