Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
强制fscanf使用可能的空白_C_Whitespace_String Formatting_Scanf - Fatal编程技术网

强制fscanf使用可能的空白

强制fscanf使用可能的空白,c,whitespace,string-formatting,scanf,C,Whitespace,String Formatting,Scanf,我有一个多行TSV文件,格式如下: 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); 这并不像我希望的那样有效,而且我在缩小误差方面遇到了困难。有

我有一个多行TSV文件,格式如下:

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);

这并不像我希望的那样有效,而且我在缩小误差方面遇到了困难。有人知道我如何正确地阅读这些行吗?

我宁愿使用
strtok
。它比fscanf更精确,因为此函数族仅在格式为100%OK时工作,否则将丢失值

看一看,我在这里更详细地解释了如何使用strtok

因此,用
fgets
阅读每一行,并用
strtok
解析每一行。我基本上同意Pablo的观点(即
scanf
家族并不是很好的解析器),但理解如何编写
scanf
模式是值得的。您正在寻找的模式如下所示:

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

  • %[xyz]
    是一个指令
    %[xyz]s
    是两个指令,第二个指令与文本
    s

  • 据我所知,没有办法匹配单个文本制表符,因为模式中的任何空格都匹配输入中的任意数量的空格(包括无空格)。在我的示例中,我使用了一个空格,它将匹配一个终止选项卡,但它也将匹配任意数量的连续选项卡,因此空字段将无法正确解析

  • 128个字符的限制不包括终止NUL字符

  • 此外,如果扫描因超出chracter限制而停止,它不会自动跳过字段的其余部分,因此最终会与输入不同步

  • 更好的模式是:

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

    如有必要,将显式跳过字段中的其余字符。一个更好的解决方案是使用
    a
    修饰符并为您获得
    fscanf
    malloc
    内存。

    首先,正如已经指出的那样,
    %[]
    本身就是一个转换说明符。在
    []
    之后没有
    s
    。格式字符串中的
    s
    -es将不被视为转换说明符的一部分。你必须摆脱那些
    s
    -es

    第二,正如你自己所说,你的文件是分开的。这立即意味着您应该使用
    %[^\t]
    转换说明符(或最后一部分的
    %[^\n]
    说明符)提取序列的连续部分。为什么要使用
    %[^]
    ,您希望它如何工作?
    %[^]
    实际上停止了对空格字符的解析,这与您想要的相反

    在您的示例中,说明符的正确组合是

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

    此格式字符串假定字符串的所有4部分都保证存在,并且最后一部分保证由
    \n

    终止。噢,哇,strtok实际上更适合于此!非常感谢。啊,我现在明白了。我对[]的用法有点困惑,但这是有道理的。虽然,我不确定使用%128[^\t]%*[^\t]读取数据比使用%128[^\t]读取数据有什么好处。@Tanaki因为如果您限制为128个字符,它将在128个字符后停止扫描,字段中的剩余字符将由下一个指令匹配,而下一个指令本应与下一个字段匹配。您是救命恩人,我忘记了溢出潜力!