2012-10-10 29 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被终止。